2017-09-14 49 views
2

如果optarg(來自Getop庫的標誌-s之後的參數)不是數字,我希望打印出錯誤消息並終止程序,如果它是一個數字,大小需要設置爲optarg。我遇到的問題是,像-s r這樣的命令會輸出錯誤信息,-s 2也會,這意味着它將2解釋爲字符串。C使用isdigit檢查optarg是否是數字

調試與-s 2

#1 printf("%d",atoi(optarg)); 
#2 printf("%d",isdigit(atoi(optarg))); 

我得到線#1, int值2和0爲線路#2 int值。

所以我想知道爲什麼isdigit(atoi(optarg)))給了我一個0,當atoi(optarg)給了我一個int。有沒有更好的方法來檢查optarg是否是int?

int main (int argc, char *argv[]){ 


int size; 
char option; 
size = 0; 
const char *optstring; 
optstring = "rs:pih"; 

while ((option = getopt(argc, argv, optstring)) != EOF) { 
    switch (option) { 
     case 'r': 
      type_set = 1; 
      break; 
     **case 's': 
      capacity_set = 1; 
      if(isdigit(atoi(optarg))==0){ 
       fprintf(stderr,"Argument after -s needs to be an int\n"); 
       return 0; 
      }** 
      else{ 
       size = atoi(optarg); 
      } 
      break; 

     default{ 
     return 0; 
     } 

回答

3

isdigit需要一個字符並告訴您它是否是數字。 atoi需要一個字符串(char *)並返回該字符串表示的數字。所以,當你撥打isdigit(atoi( ......你正在考慮一個號碼並將其當作角色來對待。由於數字的特徵碼是48..57,除了其中一個以外的任何數字都將返回錯誤。

你可能想要isdigit(*optarg) - 這會告訴你,如果參數(字符串)的第一個字符是數字字符。當然,這隻看第一個字符,所以你可能想要isdigit(optarg[0]) && optarg[1] == 0

如果你想接受而非數字(也是唯一的一個數字),strtol作品比atoi,因爲它可以讓你檢查失敗要好得多。喜歡的東西:

char *end; 
errno = 0; 
size = strtol(optarg, &end, 10); 
while (isspace(*end)) ++end; 
if (errno || *end) { 
    // an error occurred on conversion, or there is extra cruft 
    // after a number in the argument. 
    fprintf(stderr,"Argument after -s needs to be an int\n"); 
    return 0; } 
+0

不過需要注意的(我知道你知道克里斯),那的atoi提供*零*能夠捕獲任何轉換錯誤只需傳遞第一個字符就可以了,只要'+/-'不能進行數字轉換。 –

+0

這就是爲什麼我建議不要使用atoi,特別是如果你只是想要一個數字(如OP說的)如果你真的想接受一個*號*而不是一個*數字*,那麼你需要別的東西 –

+0

沒有敲門,我投了票,我只是想要確定OP瞭解'atoi'是有侷限性的。我特別喜歡使用第一個字符,但如果用戶試圖指定「+/-」(這確實是一個角落 - 但是是真實的),它也具有'isdigit'限制。 –

2

多德有一個偉大的答案。另外,可能更簡單的方法如下(假設你只是想知道,如果OPTARG是一個單一的數字:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

// Assuming ASCII. "string" must be one character long and it 
// must be a digit 
int isSingleDigit(char *str) 
{ 
    return((strlen(str) == 1) && (*str >= '0' && *str <= '9')); 
} 

int main (void) 
{ 

    char *str = "a"; 
    char *str1 = "9"; 
    char *str2 = "10"; 
    char *str3 = "1a"; 


    printf("%s %d\n", str, isSingleDigit(str)); 
    printf("%s %d\n", str1, isSingleDigit(str1)); 
    printf("%s %d\n", str2, isSingleDigit(str2)); 
    printf("%s %d\n", str3, isSingleDigit(str3)); 


    return 0; 
} 

輸出:

a 0 
9 1 
10 0 
1a 0 
+1

當然'* str> ='0'...'比'* str> 0x2F更易於理解和移植......' – chux