简体   繁体   中英

C Using isdigit to check if optarg is a digit

If optarg (the argument after the flag -s, from Getop library) isn't a digit, I want an error message to be printed and the program terminated, and if it is a digit, size needs to be set to optarg. The problem I have is while a command like the -sr will hit the error message, -s 2 will also, meaning it's interpreting the 2 as a string.

Debugging with for -s 2

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

I get the int value 2 for line #1, and an int value of 0 for line #2.

So I was wondering why isdigit(atoi(optarg))) gives me a 0, when atoi(optarg) gives me an int. Is there a better way to check if optarg is an 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;
        }  

isdigit takes a character and tells you if it is a digit. atoi takes a string (char *) and returns the number that the string represents. So when you call isdigit(atoi( ... you're taking a number and treating it as a character. Since the charater codes for digits are 48..57, any number other than one of those will return false.

You probably want isdigit(*optarg) -- this will tell you if the first character of the argument (string) is a digit character. Of course, this only looks at the first character, so you might want isdigit(optarg[0]) && optarg[1] == 0 instead.

If you want to accept a number rather than a digit (and only a number), strtol works much better than atoi as it allows you to check for failures. Something like:

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; }

Chris Dodd has a great answer. Another, possibly simpler method is as follows ( assuming you just want to know if optarg is a SINGLE digit:

#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;
}

Output:

a 0
9 1
10 0
1a 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM