Scooby
Scooby

Reputation: 3581

How to check if the argument passed is a string in c?

I have the following code :

void test(int N)
{
    printf("%d", N);

}
int main(int ac, char **av)
{
    test("");
    return 0;
}

I have a function test that expects an integer argument, but in the main when I call the function I give a string argument and c converts it to a integer and prints it for me. But what I want is that if someone passes a string than I give an error. How to check whether the argument is a string though ?

Thanks !

Upvotes: 0

Views: 4075

Answers (4)

wholerabbit
wholerabbit

Reputation: 11546

what I want is that if someone passes a string than I give an error

That's not really your problem. Most compilers will give a warning for this, I think -- presuming warnings are enabled.

The issue is that C always passes by value, but a string argument is an array, and its value is the address of the first character in the array -- a pointer, but pointer values can be treated as integers. Again, most compilers are smart enough to catch this ambiguity, if you use them properly.

You can't completely bulletproof your code against people who use it improperly. You write an API, you document it, but you don't have to cover cases for those who cannot use basic tools properly.

The core standard C library does not include checks of the sort you are looking for here, so it seems pointless to incorporate them into your API -- there are oodles of built-in standard commands with int args to which an array can be passed in the same way. Saving someone from doing something stupid with your library won't save them from doing the exact same thing with the base C lib -- i.e., you can't stop them from passing pointers in place of ints. Period.

Upvotes: 0

Keith Thompson
Keith Thompson

Reputation: 263357

void test(int N) { /* ... */ }

...

test("");

That function call is simply invalid. test requires an argument of type int, or of something that's implicitly convertible to int (any arithmetic type will do). "" is a string literal; in this context, it's converted to a char* value which points to the '\0' character which is the first (and last, and only) character of the array.

There is no implicit conversion from char* to int. A conforming compiler must issue a diagnostic for the invalid call, and it may (and IMHO should) reject it outright. It's exactly as invalid as trying to take the square root of a string literal, or add 42 to a structure.

Older versions of C (before the 1989 ANSI standard) were more lax about this kind of thing, and that laxity survives into some modern compilers. It's likely that, if your compiler doesn't reject the call, it will take the address of the string literal and convert it to an int. The result of this conversion is largely meaningless; such a compiler really isn't doing you any favors by permitting it.

If your compiler doesn't reject, or at the very least warn about, the call, you should enable whatever options are necessary to make it do so. For gcc, for example, you might try something like:

gcc -std=c99 -pedantic -Wall -Wextra filename.c

You can drop the -pedantic if you want to use gcc-specific extensions. There are several possible arguments for the -std= option. See the gcc documentation for more information -- or the documentation for whatever compiler you're using.

If you're asking about validating user input (i.e., input from someone running your program rather than writing C code), user input is not generally in the form of numbers. It's in the form of text, sequences of characters. For example, you might use the fgets() function to read a line of text from standard input. You can then, if you like, check whether that line has the form of an integer literal. One way to do that is to use the sscanf function. A quick example:

#include <stdio.h>
int main(void) {
    char line[200];
    int n;

    printf("Enter an integer: ");
    fflush(stdout);
    fgets(line, sizeof line, stdin);
    if (sscanf(line, "%d", &n) == 1) {
        printf("You entered %d (0x%x)\n", n, (unsigned)n);
    }
    else {
        printf("You did not enter an integer\n");
    }
}

But if your question is about someone writing C code that calls a function you provide, the compiler will check that any arguments are of a valid type.

Upvotes: 1

Amarghosh
Amarghosh

Reputation: 59451

Compile with -Wall and -Werror and your problem will magically go away.

gcc -Wall -Werror file.c

Upvotes: 0

paddy
paddy

Reputation: 63481

The naive approach is something like this:

int is_integer( const char *s )
{
    if( *s == '-' || *s == '+' ) s++;
    while( isdigit(*s) ) s++;
    return *s == 0;
}

That will tell you if all characters are digits, with an optional sign. It's not particularly robust, however. It can't handle whitespace, and it doesn't check the integer is in the valid range.

However, it might be enough for your needs.

Example:

int main( int argc, char **argv )
{
    int val;

    if( argc <= 1 || !is_integer(argv[1]) ) {
        fprintf( stderr, "Syntax: %s val\n\nWhere val is an integer\n", argv[0] );
        return 1;
    }

    val = strtol( argv[1], NULL, 10 );
    test(val);

    return 0;
}

Upvotes: 0

Related Questions