用户在scanf中键入null终止符

时间:2016-12-20 14:57:30

标签: c input scanf

用户是否可以在输入中键入null终止符,使用的是scanf,因此输入的长度为0?

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

4 个答案:

答案 0 :(得分:8)

在许多系统上,答案是“是”。

通常,魔术序列是 Control - @

@的字符代码通常是64,比A(65)的字符代码少一个。 Control-A是字符代码1;少一个是字符代码0,又名'\0'

请注意,要获得零长度输入,您必须键入空字节作为第一个非空格字符,并且仍然需要按返回以输入输入。您的程序会发现很难可靠地识别空字节后输入的其他内容。

答案 1 :(得分:4)

某些系统允许终端用户通过按 Ctrl - @ 输入NUL字节。然后scanf()将此字节存储到目标数组中,但很可能不会将此字节视为字分隔符,因此输入解析将一直持续到文件结尾或输入空行字符(如换行符)。

如果NUL字节存储在其他字符之后,则无法从目标数组中判断,也不能确切地知道在此NUL字节之后读取了多少其他字符。但是,如果scanf()返回1msg的长度为零,则唯一的可能是用户在空白字符可能为空的序列之后输入了NUL字节。

这也是fgets()在传递大小超过1的目标数组时返回空字符串的唯一可能性。

如果从文件而不是终端读取输入,则文件始终可能包含NUL字节,并且应注意避免未定义的行为(如果发生)。例如,这是一个经典的错误:

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!
    }
    ...
}

另请注意,您的代码存在缺陷:要存储到目标中的最大字符数应为999,而不是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");
    }
}

答案 2 :(得分:2)

  

用户是否可以在输入中键入null终止符,使用的是scanf,因此输入的长度为0?

除了用户typing in a null character之外,stdin还可以使用包含空字符的重定向输入。

foo < data.bin

详细信息:当扫描的第一个字符是空字符'\0'时,它会像任何其他字符一样被读取,并像任何其他非空白字符一样保存。因此输入的长度仍然大于0,但strlen(msg)报告的值被嵌入的空字符欺骗并返回零。

在这方面,

fgets()scanf()存在同样的问题:strlen(msg) 总是 报告读取的字符数。

非标准getline()确实会返回读取的字符数,并且远离此。

@Stargateur提到使用"%n"存储msg中保存的字符数。也许就像

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

IAC,我们正在努力应对scanf()和家人的角落弱点。最好的读取输入解决方案取决于OP未提及的其他因素。

答案 3 :(得分:0)

是的,可能因为'\0'是非白色空间。 scanf()会认为这是字符串的结尾。所以%s可以匹配一个空字符串。

您可以使用m说明符分配相应的缓冲区来保存输入。请注意,这是POSIX 200112L标准。

#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");
    }
}