Reputation: 3581
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
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
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
Reputation: 59451
Compile with -Wall
and -Werror
and your problem will magically go away.
gcc -Wall -Werror file.c
Upvotes: 0
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