2017-09-14 81 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