我在尝试识别 C 中标准输入上的空行时遇到了一些困难。我有以下代码:
char *line = NULL;
int done = 0;
while (!done) {
scanf("%m[^\n]", &line);
if (line != NULL)
//do something with line
else
done = 1;
scanf("\n");
free(line);
这些行应该是用户的命令。假设他只允许打电话
insert something
delete something
或
exit
在任何其他情况下,程序都应该输出,比如说“命令不允许”。在每种情况下我都可以做到这一点,除了一种情况 - 当输入上有空行时 - 我不知道如何识别它。我希望能得到一些帮助。
不要使用
scanf()
,而是使用 fgets()
或 *nix getline()
。
scanf()
旨在读取格式化数据 - 它与 lines 配合使用效果稍好。fgets()
旨在读取 line(0 个或更多字符,直至并包括最后的 '\n'
),并通过将空字符 '\0'
附加到目标缓冲区将其转换为 C 字符串。
char line[100];
while (!done) {
// scanf("%m[^\n]", &line);
if (fgets(line, sizeof line, stdin) == NULL) {
// EOF or input error occurred, for now let us just clear line
line[0] = 0;
}
// get rid of potential trailing \n
line[strcspn(line, "\n")] = 0;
if (line[0])
//do something with line
else
done = 1;
}
m
中的"%m[^\n]"
在C规范中没有指定。它是一些 C 库使用的扩展。
此答案中的所有信息均摘自
man scanf
。
%[
格式代码不会匹配空字符串:
匹配指定接受字符集中的非空序列字符[
记住
scanf
有一个非常有用的返回值:
这些函数返回成功匹配和分配的输入项的数量,该数量可能少于提供的数量,如果早期匹配失败,甚至为零。
您应该始终检查 scanf 的返回值,因为如果无法成功匹配相应的输入项,则输出参数具有未指定的值。
在这种情况下,返回值将告诉您换行符前面是否有非空字符串。
如所示,您的代码存在内存泄漏(假设读取了不止一行),因为
m
修饰符会导致分配内存,而不会查看最初存储在相应参数中的值。因此,如果参数保存了先前分配的存储的地址,它将被新分配的存储的地址覆盖,并且先前的分配将会泄漏。
循环应该是:
while (!done) {
line = NULL; /* Not strictly necessary */
if (scanf("%m[^\n]", &line) == 1) {
/* Do something with line */
free(line);
} else {
/* Handle an empty line */
}
/* skip trailing newline. See below. */
getchar();
}
scanf("\n")
不仅仅跳过单个换行符。与scanf(" ")
没有什么不同; scanf 格式中的任何空格:
匹配输入中任意数量的空格,包括无空格。
如果您只想跳过单个换行符,请使用
getchar()
。