2012-03-17 51 views
18

Tôi cần kiểm tra xem chuỗi C có phải là số nguyên hợp lệ không.Xác định xem chuỗi C là một int hợp lệ trong C

tôi đã cố gắng cả

int num=atoi(str); 

int res=sscanf(str, "%d", &num); 

Nhưng gửi chuỗi "8 -9 10" trong cả hai dòng trở lại chỉ đơn giản là 8, mà không cho thấy sự vô hiệu của chuỗi này.

Ai đó có thể đề xuất giải pháp thay thế không?

+0

'atoi' không kiểm tra lỗi; hành vi của nó nếu 'str' không chứa một biểu diễn của một giá trị' int' là không xác định. (Các hiện thực điển hình trả về '0'.)' Sscanf' là tốt hơn, nhưng hành vi của nó là không xác định nếu giá trị trong chuỗi không thể biểu diễn như một 'int'. Ngoài ra, tiêu đề của bạn nói rằng bạn muốn kiểm tra một int hợp lệ, nhưng phần thân của câu hỏi của bạn nói "số nguyên hợp lệ"; chúng không giống nhau. 'int' là một trong nhiều loại * số nguyên *. –

Trả lời

29

Hãy xem strtol(), nó có thể cho bạn biết về các phần không hợp lệ của chuỗi bằng cách con trỏ trả về.

Và hãy cẩn thận với mã ví dụ nhiệt tình .. xem trang hướng dẫn xử lý lỗi toàn diện.

+0

strtol() chỉ đặt con trỏ tới "đối tượng" tiếp theo trong chuỗi. Nó không xác nhận bất cứ điều gì. –

+1

@ g24l Nếu con trỏ đó kết thúc bằng trỏ tới NULL, thì bạn biết toàn bộ chuỗi là hợp lệ. Nếu không, thì không. Tadaa! – blueshift

+0

Nếu nó là một chuỗi chấm dứt null. –

8

Có lẽ tôi sẽ nhận được Flamed cho không sử dụng strtol hoặc tương tự libc chức năng, nhưng lý luận về vấn đề này không phải là khó:

#include <stdbool.h> // if using C99... for C++ leave this out. 
#include <ctype.h> 

bool is_valid_int(const char *str) 
{ 
    // Handle negative numbers. 
    // 
    if (*str == '-') 
     ++str; 

    // Handle empty string or just "-". 
    // 
    if (!*str) 
     return false; 

    // Check for non-digit chars in the rest of the stirng. 
    // 
    while (*str) 
    { 
     if (!isdigit(*str)) 
     return false; 
     else 
     ++str; 
    } 

    return true; 
} 

[NB: Tôi có thể có nếu không thực hiện isdigit(*str++) thay vì else để giữ nó ngắn hơn nhưng hồi ức của tôi là các tiêu chuẩn nói rằng có thể là isdigit là một macro.]

Tôi đoán một giới hạn là điều này không trả về false nếu số trong chuỗi không khớp với số nguyên. Điều đó có thể hoặc có thể không quan trọng với bạn.

+1

"không phải là khó", nhưng bạn phải quay lại và thay đổi nó;) – blueshift

+1

@blueshift Điểm lấy, nhưng 1 chỉnh sửa trong 5 phút khi gõ mã vào một biểu mẫu web không phải là xấu với tôi. :-) – asveikau

+0

Trong trường hợp này tôi không biết nếu nó có nhiều lỗi dễ bị cuộn của riêng bạn hoặc để thử và có được xử lý lỗi cho strtol() phải .. Tôi có lẽ vẫn khuyên bạn nên strtol. – blueshift

2

Một cách đơn giản để làm điều này một cách mạnh mẽ sẽ được đọc int và chắc chắn rằng nó đại diện chuỗi được trùng với chuỗi đầu vào, ví dụ như kết hợp atoiitoa:

int is_int(char const* p) 
{ 
    return strcmp(itoa(atoi(p)), p) == 0; 
} 
+0

Ý tưởng hay :). Tuy nhiên, điều này cũng sẽ yêu cầu cắt tỉa các khoảng trắng ở đầu và cuối để làm cho nó hoạt động. – sara

+3

Lưu ý rằng giải pháp này không tuân thủ ANSI. –

0

Đối với kiểm tra nếu chuỗi có chứa một số hợp lệ bạn có thể sử dụng cụm từ thông dụng. Ví dụ cho số nguyên sử dụng:

[- +] [0-9] +

và một trường hợp chung cho số dấu chấm động:?

[+ -] [0-9] + [ .]? [0-9] * ([eE] [- +]? [0-9] +)?

Trong trường hợp hàm C++ 11 biểu thức chính quy có sẵn trong thư viện, ví dụ: "std :: regex_match (.....)" cho kết quả chính xác. Mã nên trông như thế này:

#include <regex> 
..... 
std::string strnumber("-1.234e+01"); 
float number; 
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?")) 
number=std::stof(strnumber); 
else 
std::cout<<"error, string is not a valid number"; 
0

Xin lỗi vì đào lên chủ đề này, nhưng vì lợi ích của sự hoàn chỉnh và vì chủ đề này là trận đấu đầu tiên khi thực hiện một tìm kiếm google ...

Có thể sử dụng một cái gì đó như:

ret = sscanf(string, "%d%n", &number, &idx); 
if (ret == 0 || string[idx] != '\0') 
    /* handle the error */ 

các %n chỉ thị, mà có vẻ là tiêu chuẩn C theo man page, đếm số ký tự xử lý.

[Chỉnh sửa] sscanf dường như không cung cấp cách phát hiện tràn, do đó gia đình chức năng strtoX nên được ưu tiên IMHO.

Các vấn đề liên quan