2015-05-20 19 views
5

Tôi đang cố gắng tạo một ứng dụng dòng lệnh trong C++ và tôi muốn đảm bảo rằng đầu vào là một số nguyên sau một đối số lệnh nhất định.Cách kiểm tra xem argv [count] có phải là số nguyên

Ví dụ này, tôi muốn kiểm tra xem đối số tiếp theo có phải là số nguyên sau đối số lệnh "-p" hay không. Đây là đoạn mã của tôi ngay bây giờ.

while (count < argc){ 
    if (strcmp("-p", argv[count]) == 0){ 
     has_p = true; //Boolean 
     pid = atoi(argv[count + 1]); 
     if (pid == 0 && argv[count + 1] != "0"){ 
      err = 1; 
      cout << "pid argument is not a valid input" << endl; 
      pid = -1; 
     } 
     count++; 
    } 
... 
} 

Bây giờ mã này bắt một cách chính xác các lỗi trong đầu vào này:

  • -p 1777
  • -p sss
  • -p sss17
  • -p [không gian] -U

nhưng không thành công ở định dạng nhập này

  • -p 17sss

Tôi cố gắng để khắc phục điều này bằng cách cố gắng để so sánh nó sử dụng sprintf. Thật không may là cung cấp sprintf với con trỏ mảng char chỉ xuất ra 1 ký tự trong buffer2.

while (count < argc){ 
    if (strcmp("-p", argv[count]) == 0){ 
     has_p = true; //Boolean 
     pid = atoi(argv[count + 1]); 
     sprintf(buffer, "%d", pid); 
     sprintf(buffer2, "%d", *argv[count + 1]); 
     if (pid == 0 && argv[count + 1] != "0" || (buffer != buffer2)){ 
      err = 1; 
      cout << "pid argument is not a valid input" << endl; 
      pid = -1; 
     } 
     count++; 
    } 
... 
} 

Có cách nào để làm cho sprintf đọc toàn bộ mảng char không? Nếu không, có giải pháp nào tốt hơn cho việc này ngoài việc lặp qua con trỏ cho đến khi tôi nhấn "\ 0"

+8

Chọn ngôn ngữ. Bạn nói C++, nhưng bạn đang sử dụng các thành ngữ C và câu hỏi được gắn thẻ cả hai. –

+1

['isdigit'] (http://www.cplusplus.com/reference/cctype/isdigit/) – 101010

+0

Sử dụng' strcmp' để so sánh hai chuỗi chứ không phải '! ='.Bạn có thể sử dụng 'if (isdigit (argv [count]))' để kiểm tra xem đối số có phải là một chữ số hay không. –

Trả lời

13

atoi() không thể thực hiện những gì bạn muốn. Bạn cần sử dụng strtol() để đạt được điều này. Nó có nhiều khả năng kiểm tra lỗi được cải thiện.

Chữ ký:

long int strtol(const char *nptr, char **endptr, int base); 

Hàm này trả về số không thể thiếu được chuyển đổi như một giá trị int dài, nếu không không có giá trị được trả về. Sau khi chuyển đổi, bạn có thể kiểm tra nội dung của endptr và quyết định điều đó.

+1

Trên một lưu ý phụ: 'endptr' sẽ được thiết lập để trỏ đến ký tự đầu tiên sau số, vì vậy nếu số là một số nguyên hợp lệ, nó sẽ trỏ đến một null-terminator kết thúc chuỗi. Nói cách khác, để kiểm tra xem chuyển đổi có thành công hay không, làm 'if (* endptr == 0)' – szczurcio

+0

bạn có thể sử dụng hàm trả về giá trị để quyết định. – ANjaNA

+2

@ANjaNA - Không, bạn không thể sử dụng giá trị trả về để xác định xem chuyển đổi có thành công không vì giá trị trả lại khi chuyển đổi không thành công cũng là kết quả có thể từ chuyển đổi thành công. Bạn ** phải ** sử dụng giá trị 'endptr'. –

0

Bạn cũng có thể sử dụng lựa chọn thay thế C++ 11, được triển khai dưới dạng strtol (xem stol).

+0

Điều này không xứng đáng với các downvotes khi nó được đăng trong khi câu hỏi cũng được gắn thẻ C++ .... –

3

Sau đây là một thuận tiện one-liner ...

sscanf(argv[count + 1], "%d%*c", &n) == 1 

... đó sẽ đánh giá đúng nếu nó đã có thể đọc vào int n và không có nhân vật dấu sau đó. Các '*' trong %*c ngăn chặn chuyển nhượng, vì vậy không cần phải chuyển con trỏ đến biến giả char. Xem scanf docs here.

+0

Tôi đã thử điều này và nó giống như vấn đề trên. Làm việc với những đầu vào sau nhưng không thành công khi bắt lỗi cho "-p 17ss" đầu vào – MDuh

+0

@MDuh: làm thế nào để nó "thất bại"? - bạn có thể thấy [ở đây] (http://ideone.com/fiMTbo) cách 'sscanf' với văn bản đó trả về' 0' ... theo thử nghiệm '== 1' ở trên, điều đó có nghĩa là nó đã gặp lỗi . Đó là khi nó trả về chính xác 1 rằng đầu vào là hợp lệ và 'n' sẽ được đặt thành giá trị số của chúng. –

+0

Để rõ ràng hơn, đối với trường hợp sử dụng cụ thể của bạn, bạn muốn 'if (sscanf (argv [count + 1],"% d% * c ", & pid)! = 1) {err = 1; cout << "đối số pid không phải là đầu vào hợp lệ" << endl; pid = -1; } 'etc ... –

1

Trong C, bạn có thể chỉ cần đi qua các char * và kiểm tra nếu có chữ số chỉ.

char c = '0'; 
int i = 0; 
int err = 0 
while (c != '\0'){ 
    if (arg[i] < 47 || arg[i] > 57){ 
     err = 1; 
     break; 
    } 
Các vấn đề liên quan