AbuAminu
AbuAminu

Reputation: 67

convert argv[1] to integer, without trusting the user input

`

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

// function prototypes

int get_key(int argc, char *argk[]);

int main(int argc, char *argv[]){
    char *argv1 = argv[1];
    get_key(argc, argv1);        
    
    return 0;
}

// function defination.

int get_key(int argc, char *argk){
    // ensure single cmd line arg
    if(argc < 2 || argc > 2){
        printf("usage: ./caesar key(int) !\n");
        return 1;
    } 
    char str1[] = "2";
    char str2[] = "23";
    char str3[] = "a23";
    char str4[] = "23b";
    char str5[] = "a23b";
    
    int len = strlen(str3);
    int number;
    
    for(int i = 0; i < len; i++){ 
        if(isdigit(str3[i])){ // since isdigit() accept only char, not char*.
            number = atoi(str3); // meaning if str3 did contain digits 0-9 from ascii chart.
        }
    }
    return number;
    
}   

`

hello guys, please i want to convert argv[1] to integer, without trusting the user. since isdigit() accept only char, not char*, thats why i am iterating through the str3 and atoi accepts char*. it works fine with str1 and str2. but for other string variables, it returns digits within them, for which cant be converted using atoi() or any other calculations. i want to report error messsage if any of argv[1] elements contains non digits 0-9 from ascii chart. thanks.

Upvotes: 1

Views: 408

Answers (1)

Andreas Wenzel
Andreas Wenzel

Reputation: 25396

Since you are stating that the user input cannot be trusted, I don't recommend using the function atoi, for two reasons:

  1. The behavior is undefined if the converted number is not representable as an int (i.e. if the number is out of range).

  2. The function will return 0 when the conversion failed. However, when this happens, you will not know whether the user actually entered 0 or whether you got this value due to conversion failure.

Both of these problems can be solved if you use the functon strtol instead of atoi.

In your question, you state that you want to reject the input if it contains any non-digit characters. One problem with the function strtol is that it will skip any leading whitespace characters (e.g. space and tab characters) before attempting to convert a number. If you instead want to reject the input if it contains any leading whitespace characters, then you will have to compare each character with isdigit, before using the function strtol. Doing this will also solve the problem of invalid characters after the number, so that input such as 123abc will get rejected.

Here is a program which will attempt to convert argv[1] to an integer, while performing full input validation:

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

int main( int argc, char *argv[] )
{
    long num;
    char *p;

    //verify that argv[1] is valid
    if ( argc < 2 )
    {
        printf( "not enough parameters!\n" );
        exit( EXIT_FAILURE );
    }

    //verify that argv[1] consists only of digits
    for ( p = argv[1]; *p != '\0'; p++ )
    {
        if ( !isdigit( (unsigned char)*p ) )
        {
            printf( "first program argument must consist only of digits!\n" );
            exit( EXIT_FAILURE );
        }
    }

    //attempt to convert argv[1] to integer
    errno = 0;
    num = strtol( argv[1], &p, 10 );

    //verify that conversion was successful
    if ( p == argv[1] )
    {
        printf( "unable to convert to integer\n" );
        exit( EXIT_FAILURE );
    }

    //verify that no range error occurred
    if ( errno == ERANGE )
    {
        printf( "input is out of range\n" );
        exit( EXIT_FAILURE );
    }

    //everything is ok, so print the result
    printf( "The result is: %ld\n", num );

    return 0;
}

Upvotes: 1

Related Questions