scanf
with %d
will only read integers - anything that's not an integer won't get read.
Unfortunately, this means you can get partial matches as you've experienced - "1.5"
is not an integer, but scanf
will read and assign the 1
to cislo
and return success.
The way around this is to read the next input as text (not try to read it as an integer or float) and do the conversion separately using a library function like strtol
or by doing your own conversion manually. Here's an example using strtol
:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFFER_SIZE 11 // up to 10 digits for a 32-bit int plus sign
/**
* We don't want to use a naked "%s" in our scanf call, since
* if the user types in more characters than the buffer is sized
* to hold, we'll write past the end of the buffer. You can specify
* the maximum number of characters to read as part of the "%s"
* conversion like "%11s", but unlike with printf you can't specify
* it with a runtime argument - it has to be hardcoded.
*
* We're going to create a format string based on the value of BUFFER_SIZE;
* when we're done, FMT will expand to "%" "11" "s", which will
* be interpreted as "%11s".
*/
#define EXPAND(x) #x
#define STR(x) EXPAND(x)
#define FMT "%" STR(BUFFER_SIZE) "s" // Make sure we don't read more characters than the buffer can hold
int main( void )
{
int cislo = 0;
char buffer[BUFFER_SIZE+1]; // +1 for string terminator
if ( scanf ( FMT, buffer ) == 1 )
{
/**
* strtol will take a string representation of an integer
* like "123" and convert it to the corresponding integer
* value. chk will point to the first character in the
* string that *isn't* part of an integer constant. If that
* character isn't whitespace or 0 (the string terminator),
* then the input is not a properly formed integer.
*/
char *chk;
int tmp = strtol( buffer, &chk, 10 );
if ( !isspace( *chk ) && *chk != 0 )
{
fprintf( stderr, "%s is not a valid integer input!\n", buffer );
return -1;
}
cislo = tmp;
}
printf( "cislo = %d\n", cislo );
return 0;
}
Examples:
$ ./converter
123
cislo = 123
$ ./converter
abc
abc is not a valid integer input!
$ ./converter
123c
123c is not a valid integer input!
$ ./converter
12.3
12.3 is not a valid integer input!