User enters null terminator in scanf

Can the user enter a null terminator in the input that scanf is used for, so the input length will be 0?

char msg[1000]; scanf("%1000s",msg); // the user would type nothing: '' or '\0' 
+6
source share
4 answers

On many systems, the answer is yes.

Usually magic sequence Control-@ .

The character code for @ is usually 64, which is less than A (65). Control-A - character code 1; one less is character code 0, aka '\0' .

Note that to get zero-length input, you need to enter zero byte as the first character without a space, and you still need to press return to enter the input. It will be difficult in your program to reliably determine what else was entered after the zero byte.

+8
source

Some systems allow a terminal user to enter NUL bytes by pressing Ctrl - @ . scanf() then store this byte in the target array, but most likely will not consider this byte as a word delimiter, so parsing of the input will continue to the end of the file or the space character, such as a new line.

It is not possible to specify from the destination array if the NUL byte was saved after other characters, and also exactly how many other characters were read after this NUL byte. But if scanf() returns 1 and msg is of zero length, the only possibility is that the user entered a NUL byte after a possible empty sequence of whitespace characters.

This will also be the only way for fgets() to return an empty string when passing the target array with a size greater than 1.

If the input is read from a file, and not from the terminal, there is always the possibility for a file to contain NUL bytes, and care should be taken to avoid undefined behavior if this happens. For example, here is a classic error:

 char msg[1000]; if (fgets(msg, sizeof msg, stdin)) { int len = strlen(msg); if (msg[len - 1] == '\n') { // potential undefined behavior! msg[--len] = '\0' // potential undefined behavior! } ... } 

Also note that your code has flaws: the maximum number of characters to store at the destination should be 999 , not 1000 :

 char msg[1000]; if (scanf("%999s",msg) == 1) { /* word was read from the user */ if (*msg == '\0') { printf("user entered a NUL byte\n"); } } 
+4
source

Can the user enter a null terminator in the input that scanf is used for, so the input length will be 0?

In addition to the user, enter a null character stdin can use redirected input containing null characters.

 foo < data.bin 

Details: When the first character you have checked is a null character or '\0' , it is read like any other character and saved like any other non-white space character. Thus, the input length is even greater than 0, but the value reported by strlen(msg) is misled by the built-in null character and returns zero.

fgets() has the same problem as scanf() in this regard: strlen(msg) does not always report the number of characters read.

The non-standard getline() returns the number of characters read and is the way out of this.


@Stargateur mentions using "%n" to store the number of characters stored in msg . Maybe,

 char msg[1000 + 1]; int start, end; if (1 == scanf(" %n%1000s%n", &start, msg, &end)) { printf("%d characters read\n", end - start); } 

IAC, we are trying to deal with the angular weakness of scanf() and the family. The best read input solution depends on additional factors not mentioned by the OP.

+2
source

Yes, perhaps because '\0' is a non-white space. scanf() will consider this to be the end of the line. Therefore, %s may correspond to an empty string.

You can use the m specifier to allocate the appropriate buffer for storing input. Please note that this is the POSIX 200112L standard.

 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { char *str; int n; if (scanf("%ms%n", &str, &n) == 1) { printf("I read %d character(s).\n", n); if (strlen(str) != 0) { printf("str = %s\n", str); } else { printf("str is empty"); } free(str); } else { printf("The user enter nothing"); } } 
0
source

Source: https://habr.com/ru/post/1013343/


All Articles