C: Checking command line argument is integer or no

2019-05-07 05:32发布

Signature of isdigit

int isdigit(int c);

Signature of atoi

int atoi(const char *nptr);

I just wanted to check whether the command line argument passed was an integer or not.Here is the C Code:

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

int main(int argc, char *argv[])
{
    if (argc == 1)
        return -1;

    printf ("Hai, you have executed the program : %s\n", argv[0]);
    if (isdigit(atoi(argv[1])))
        printf ("%s is a number\n", argv[1]);
    else
        printf ("%s is not a number\n", argv[1]);
    return 0;
}

But the output is not as expected, when I am passing a valid number:

$ ./a.out 123
Hai, you have executed the program : ./a.out
123 is not a number
$ ./a.out add
Hai, you have executed the program : ./a.out
add is not a number

I couldn't figure out the error.

6条回答
Summer. ? 凉城
2楼-- · 2019-05-07 06:05

isdigit() function checks for a digit character ('0' to '9') which of course depends on ASCII values. Now value returned from your atoi does not fall within ASCII value between '0' to '9'. so it is showing that it is not a number.

查看更多
姐就是有狂的资本
3楼-- · 2019-05-07 06:11

When you refer argv[1], it refers to a character array containing value 123. isdigit function is defined for a single character input.

So to handle with this situation, it is better to define a function as follows:

bool isNumber(char number[])
{
    int i = 0;

    //checking for negative numbers
    if (number[0] == '-')
        i = 1;
    for (; number[i] != 0; i++)
    {
        //if (number[i] > '9' || number[i] < '0')
        if (!isdigit(number[i]))
            return false;
    }
    return true;
}
查看更多
Emotional °昔
4楼-- · 2019-05-07 06:11

I thought I'd add something to the answers already here. In addition to checking for numbers in base 10, I thought it would be useful to check for and allow hexadecimal numbers as well. I also allow negative numbers.

I also added a few things to check for bad input (e.g. null pointer, letters inside of a string representing a decimal number, or invalid letters inside a string representing a hexadecimal number).

Note that I use the to_lower(char c) function to ensure that letters representing hexadecimal will be lower case, just for convenience.

I return 1 (or true) if the string is a valid number, 0 if it isn't. If it is a valid number, I store the base inside the parameter base.

// Return 1 if str is a number, 0 otherwise.
// If str is a number, store the base (10 or 16) in param base.
static int is_number(char *str, int *base)
{
    // Check for null pointer.
    if (str == NULL)
        return 0;

    int i;
    int len = strlen(str);

    // Single character case.
    if (len == 1)
    {
        *base = 10;
        return isdigit(str[0]);
    }

    // Hexadecimal? At this point, we know length is at least 2.
    if ((str[0] == '0') && (str[1] == 'x'))
    {
        // Check that every character is a digit or a,b,c,d,e, or f.
        for (i = 2; i < len; i++)
        {
            char c = str[i];
            c = to_lower(c);
            if (!(
                (c >= '0' && c <= '9') || 
                (c >= 'a' && c <= 'f')))
                return 0;
        }
        *base = 16;
    }
    // It's decimal.
    else
    {
        i = 0;
        // Accept signs.
        if (str[0] == '-' || str[0] == '+')
            i = 1;

        // Check that every character is a digit.
        for (; i < len; i++)
        {
            if (!isdigit(str[i]))
                return 0;
        }
        *base = 10;
    }
    return 1;
}

I used this function like this:

int base, num;
if (is_number(str, &base)
    num = strtol(str, NULL, base);
查看更多
Animai°情兽
5楼-- · 2019-05-07 06:14

I don't know what isdigit exactly does, but due to name I think it should take a char argument, check for the char being a digit, is it?

I would write like this: (omitted the function shell, just show the core code)

char* p = argv[1];
while (*p != '\0')
{
    if (*p<'0' || *p>'9')
    {
        printf("%s is not a number", argv[1]);
        return 0;
    }
    p++;
}
printf("%s is a number", argv[1]);
return 0;
查看更多
Emotional °昔
6楼-- · 2019-05-07 06:21
// Since There is an implicit conversion from const char* to std::string
// You May use this simplified version of the check_string instead

     bool isNumeric(const string str) 
    {
        // loop Through each character in the string
        for(char x:  str)
            if(!isdigit(x)) // Check if a single character "x" its a digit
            return false;  // if its not return false 

      return true; // else return true
    }  
查看更多
男人必须洒脱
7楼-- · 2019-05-07 06:26
if (isdigit(atoi(argv[1]))) 

will be:

if (isdigit(atoi("123")))

which will be:

if (isdigit(123))

which will be:

if ( 0 )

since 123 represents the ASCII character '{'.

查看更多
登录 后发表回答