Làm thế nào tôi có thể trích xuất một số nguyên từ trong một chuỗi?


8

Tôi đang làm việc trên một bài tập và là một phần của nó, tôi cần trích xuất số nguyên từ một chuỗi.

Tôi đã thử sử dụng atoi()hàm, nhưng nó luôn trả về a 0, vì vậy sau đó tôi đã chuyển sang strtol(), nhưng nó vẫn trả về a 0.

Mục tiêu là trích xuất các số nguyên từ chuỗi và chuyển chúng dưới dạng đối số cho một hàm khác. Tôi đang sử dụng một hàm sau đó sử dụng các giá trị này để cập nhật một số dữ liệu ( update_stats).

Xin lưu ý rằng tôi khá mới đối với lập trình bằng ngôn ngữ C, nhưng đây là nỗ lực của tôi:

void get_number (char str[]) {
    char *end;
    int num;
    num = strtol(str, &end, 10);
    update_stats(num);
    num = strtol(end, &end, 10);
    update_stats(num);
}

Mục đích của việc này là trong một chuỗi "e5 d8"(ví dụ) tôi sẽ trích xuất 58từ chuỗi đó.

Định dạng của chuỗi luôn giống nhau.

Tôi có thể làm cái này như thế nào?


1
Không có lỗi rõ ràng trong phần này của mã, vì vậy vấn đề không thể được sao chép.
Lundin

1
Bạn có thể sử dụng các vòng lặp để bỏ qua tất cả các ký tự không có chữ số isdigittrước khi sử dụngstrtol
Bodo

1
Cả hai atoistrtolmong đợi nhận được con trỏ tới ký tự đầu tiên của một chữ số. Con trỏ của bạn phải được trỏ đến một chữ số. Không phải là số điện tử hay dữ liệu là một chữ số khi cơ sở là 10. Để tìm các chữ số trong chuỗi, bạn nên viết mã để kiểm tra từng ký tự để xác định xem đó có phải là một chữ số hay không. Khi bạn đã tìm thấy một chữ số, bạn có thể chuyển đổi nó (chỉ một chữ số) hoặc chuỗi các chữ số (vài chữ số) ở đó thành một số, tùy thuộc vào nhu cầu của bạn là gì.
Eric Postpischil

@Lundin: Có một lỗi hoàn toàn rõ ràng; đi qua một con trỏ tới ký tự đầu tiên của "e5 d8"để strtolkhông phải là một cách chính xác để tìm ra “5” và chuyển nó sang dạng số.
Eric Postpischil

@EricPostpischil Thật vậy, nếu đó là đầu vào thực tế. Khó để nói mà không có mã gọi.
Lundin

Câu trả lời:


7

strtolkhông tìm thấy một số trong một chuỗi. Nó chuyển đổi số ở đầu chuỗi . (Nó bỏ qua khoảng trắng, nhưng không có gì khác.)

Nếu bạn cần tìm nơi bắt đầu một số, bạn có thể sử dụng một cái gì đó như:

const char* nump = strpbrk(str, "0123456789");
if (nump == NULL) /* No number, handle error*/

( man strpbrk)

Nếu số của bạn có thể được ký, bạn sẽ cần một cái gì đó tinh vi hơn một chút. Một cách là làm như trên và sau đó sao lưu một ký tự nếu ký tự trước đó là -. Nhưng xem ra cho sự bắt đầu của chuỗi:

if ( nump != str && nump[-1] == '-') --nump;

Chỉ cần đưa -vào strpbrkđối số sẽ tạo ra kết quả khớp sai trên đầu vào như thế nào non-numeric7.


2

Nếu định dạng luôn như thế này, thì nó cũng có thể hoạt động

#include <stdio.h>

int main()
{
    char *str[] = {"a5 d8", "fe55 eec2", "a5 abc111"};
    int num1, num2;

    for (int i = 0; i < 3; i++) {
      sscanf(str[i], "%*[^0-9]%d%*[^0-9]%d", &num1, &num2);
      printf("num1: %d, num2: %d\n", num1, num2);
    }
    return 0;
}

Đầu ra

num1: 5, num2: 8                                                                                                                                                                   
num1: 55, num2: 2                                                                                                                                                                  
num1: 5, num2: 111

%[^0-9]sẽ phù hợp với bất kỳ ký tự không chữ số. Bằng cách thêm *như thế này %*[^0-9]chỉ ra rằng dữ liệu sẽ được đọc từ chuỗi, nhưng bị bỏ qua.


Sử dụng tốt đẹp của sscanf. Tôi thực sự đánh giá cao những nỗ lực. Tuy nhiên, không nơi nào quy định rằng định dạng là cách bạn đã được cấp. Cố gắng thêm một chút hào phóng nếu bạn có thể. Ngoài ra, nếu người dùng bị kẹt trong I / O và chuyển đổi chuỗi thành số nguyên, có khả năng cao là anh ấy / cô ấy mới. Vì vậy, sẽ rất hữu ích khi thêm hoặc ít nhất là cung cấp một liên kết đến tài liệu, ví dụ, trong trường hợp này , sscanf. Câu trả lời hay đấy :)
d4rk4ng31

1
Vâng cảm ơn. Nhưng cũng lưu ý rằng câu hỏi "Định dạng của chuỗi luôn giống nhau.", Điều này ngụ ý điều này có thể giống nhau. Sự rộng lượng là một điều tốt, nhưng sự vắng mặt của nó cho phép giải pháp hoạt động như thế này. Lượt truy cập đầu tiên trên google cho sscanflà tài liệu. Tôi nghĩ những gì thực sự là ngẫu hứng ở đây là ít lời giải thích về định dạng, mà tôi có thể thêm vào đây.
Eraklon

Đúng Lấy làm tiếc. Tôi đoán tôi đã bỏ lỡ tuyên bố cuối cùng. Câu trả lời hay đấy :)
d4rk4ng31

2

Tôi đề nghị bạn tự viết logic. Tôi biết, nó giống như phát minh lại bánh xe , nhưng trong trường hợp đó, bạn sẽ có cái nhìn sâu sắc về cách các chức năng thư viện thực sự hoạt động.

Đây là một chức năng tôi đề xuất:

bool getNumber(str,num_ptr)
char* str;
long* num_ptr;
{
    bool flag = false;
    int i = 0;
    *num_ptr = 0;
    char ch = ' ';
    while (ch != '\0') {
        ch = *(str + i);
        if (ch >= '0' && ch <= '9') {
            *num_ptr = (*num_ptr) * 10 + (long)(ch - 48);
             flag = true;
        }
        i++;
    }
    return flag;
}

Đừng quên chuyển một chuỗi có một \0kết thúc :)


Hàm này quét toàn bộ chuỗi và trả về một số bao gồm các chữ số theo thứ tự.
d4rk4ng31

xem xét c, bạn có thể chuyển đổi bool để int và truefalsetới 10tương ứng
d4rk4ng31
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.