How to receive a null character in gets function from the user input?
The obsolete, since c11, function gets()
reads a line of text and then saves it (without the '\n'
) with an appended null character insuring a string.
gets()
The gets function reads characters from the input stream pointed to by stdin, into the array pointed to by s, until end-of-file is encountered or a new-line character is read. Any new-line character is discarded, and a null character is written immediately after the last character read into the array. C99 §7.19.7.7 2
line
A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. C99dr §7.19.2 2
string
A string is a contiguous sequence of characters terminated by and including the first null character. C99dr §§7.1.1 1
Is there an input that will cause that?
Yes. Entering a null character on various keyboards is not easy. Sometimes a Ctrl Shift 2 (Ctrl @) will work. Some keyboards lack or obscure any way to input a null character. Usually a re-directed input from a file that contains a null character into stdin
will suffice.
Entering \ 0 Enter is not entering a null character.
An important consideration is that with gets()
or fgets()
, the input of a null character is not special in its reception. A following Enter ('\n'
) or end-of-file-signal is still needed. After which a null character is appended.
With gets()
, the size of the input buffer needs to be at least 2 to read in any input more than an empty line of just Enter, so char str[1];
is too small to save an input of a null character with the appended null character.
If the input was Enter, gets(str)
would save no input in str[0]
and then append a null character to str[0]
.
If the input was Ctrl @, Enter, gets(str)
would save the user inputted null character to str[0]
and then append a null character to str[1]
.
Let us try an example with fgets()
.
int main(void) {
// Form a file of 1 byte
FILE *f = fopen("zero.txt", "w");
if (f == NULL) {
return EXIT_FAILURE;
}
fputc('\0', f);
fclose(f);
f = fopen("zero.txt", "r");
if (f == NULL) {
return EXIT_FAILURE;
}
char buf[80];
memset(buf, 42, sizeof buf);
fgets(buf, sizeof buf, f);
for (int i = 0; i < 5; i++) {
printf("%d\n", buf[i]);
}
fclose(f);
return 0;
}
Output
0 // from the file zero.txt
0 // the appended null character
42
42
42
Text processing functions like fgets()
, scanfs()
, fscanfs()
and the obsolete gets()
having to cope with a user inputed null character is a corner case. Such input is either a mistake or, more likely, a hacker attempt to break the program.