I have a program where I need to scanf a string, which I know it will be only 2 characters long. (for example: \"ex\"). what is the proper way to do that?
I was goin
but when I enter a 10-letter word it also works just fine. How come? Does the [3] has no meaning?
I doesn't work fine. See in this example:
#include <stdio.h>
int
main(int argc, char **argv)
{
char second[5] = "BBBB";
char myStr[3] = {0};
scanf("%s", myStr);
printf("second = %s\n", second);
printf("myStr = %s\n", myStr);
return 0;
}
writing only two characters in myStr
is fine:
a.exe
AA
second = BBBB
myStr = AA
writing more data overrides the near by memory of second
:
a.exe
AAAAAAA
second = AAAA
myStr = AAAAAAA
You need to limit the number of characters scanf
reads using something like
scanf("%2s", myStr);
, 2
is the size of myStr - 1
.
You can´t do that.
scanf will do nothing to prevent it, but it can (or, in larger programs, will)
lead to problems later on. Like unexpectly changed variable values, program crashes...
Use fgets
The proper way to limit the input using scanf()
is
if (scanf("%2s", myStr) != 1) /* error */;
But consider using fgets()
rather than scanf()
if (fgets(myStr, sizeof myStr, stdin) == NULL) /* error */;
It works just fine, but when I enter a 10-letter word it also works just fine.
It only appears to work fine but it's actually undefined behaviour. That is because scanf
stores the characters it reads from stdin
into the buffer pointed to by myStr
. The size of myStr
is 3
. Therefore, there's space for only 2
characters. One character space is saved for the terminating null byte to mark the end of the string which is added by scanf
automatically. When the input string is longer than 2
characters, scanf
overruns the buffer accessing memory out of the bound of the array. It is illegal to access memory out of the array bound and invokes undefined behaviour.
The next time, it may very well crash. It's unpredictable and you should always avoid it.
To guard against it, you should specify maximum field width for the conversion specifier %s
in the format string of scanf
. It should be one less than the array size to accommodate the terminating null byte.
char myStr[3];
scanf("%2s", myStr);
Better still, I suggest you to use fgets
.
char myStr[3];
// read and store at most one less than
// sizeof(myStr) chars
fgets(myStr, sizeof myStr, stdin);