C double printf()当在我的scanf()中放入空格时

C double printf()当在我的scanf()中放入空格时,c,while-loop,scanf,strtol,C,While Loop,Scanf,Strtol,我一直在努力使这段代码正常工作: #include <stdio.h> #include <stdlib.h> int main(int argc, char const **argv) { char buf[100]; int var = 0; do { printf("Write a number :\n"); scanf("%s", buf); } while

我一直在努力使这段代码正常工作:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const **argv) {
    char buf[100];
    int var = 0;
    do {
        printf("Write a number :\n");
        scanf("%s", buf);
    } while ((int)strtol(buf, NULL, 10) == 0);

    return 0;
}
我不明白为什么程序在
while
循环的第二次迭代中停止并忽略我的
scanf()

以下是步骤:

  • 第一次迭代打印
    写一个数字:
    和一个换行符
  • scanf(“%s”,buf)
    没有从stdin读取的内容,因此请求输入,
    • 键入
      F10
      并按enter键
    • scanf(“%s”,buf)
      读取
      f
      并在空格处停止
  • strtol(buf,NULL,10)
    返回
    0
    ,因此循环继续
  • 第二次迭代打印
    写一个数字:
    和一个换行符
  • scanf(“%s”,buf)
    读取
    10
    并在换行符处停止
  • strtol(buf,NULL,10)
    返回
    10
    ,因此循环退出
  • 程序以
    0
    状态(成功)结束
这就是您观察到的情况:如果您提供了多个单词,则多个
scanf()
调用会在从终端请求更多输入之前读取它们。

以下是步骤:

  • 第一次迭代打印
    写一个数字:
    和一个换行符
  • scanf(“%s”,buf)
    没有从stdin读取的内容,因此请求输入,
    • 键入
      F10
      并按enter键
    • scanf(“%s”,buf)
      读取
      f
      并在空格处停止
  • strtol(buf,NULL,10)
    返回
    0
    ,因此循环继续
  • 第二次迭代打印
    写一个数字:
    和一个换行符
  • scanf(“%s”,buf)
    读取
    10
    并在换行符处停止
  • strtol(buf,NULL,10)
    返回
    10
    ,因此循环退出
  • 程序以
    0
    状态(成功)结束

这就是您观察到的情况:如果您提供了多个字,则多个
scanf()
调用会在从终端请求更多输入之前读取它们。

不相关,但为了避免从一开始就养成坏习惯:始终将从外部源读取的数据长度限制为缓冲区长度。在这里,使用
scanf
读取
buf
的输入容易出现缓冲区溢出,这是最常见的安全漏洞之一。请参阅手册页,了解如何正确限制字符数。您是否检查了
scanf
errno
的返回值?为什么要使用
strtol
?如果要使用scanf,只需使用
%ld
转换说明符即可。您必须检查scanf.Not related返回的值,但要避免从一开始就养成坏习惯:始终将从外部源读取的数据长度限制为缓冲区长度。在这里,使用
scanf
读取
buf
的输入容易出现缓冲区溢出,这是最常见的安全漏洞之一。请参阅手册页,了解如何正确限制字符数。您是否检查了
scanf
errno
的返回值?为什么要使用
strtol
?如果要使用scanf,只需使用
%ld
转换说明符即可。你必须检查scanf返回的值。谢谢,伙计,我理解了。我的问题是我不知道scanf()在stdin中没有任何内容可读取时请求输入。编辑:无法升级我的信誉点不足15。我只有1个问题scanf是否在上一个循环中的stdin中的每个循环上保存一个指向记忆的指针?@MeryVorente:
scanf()
不这样做,是流结构做的。
文件
对象是一种结构,它保存有关流的信息,例如当前位置、从设备或文件读取但尚未被
getc()
fgets()
scanf()
fread()
读取的字符缓冲区。类似地,缓冲区保留由
putc()
fputs
fprintf
fwrite
写入的字节,直到将其刷新到终端或文件系统为止。通常,从连接到终端的
stdin
读取输入时,从用户处读取整行输入。。。。。。进入流缓冲区,
getc()
从中读取单个字节,
scanf()
读取足够的字节以执行格式字符串中指定的转换,即:直到读取的字节不再匹配预期语法。这个字节被推回到流中,就像被
ungetc()
一样,并将被下一个读取函数读取。谢谢,伙计,我理解了。我的问题是我不知道scanf()在stdin中没有任何内容可读取时请求输入。编辑:无法升级我的信誉点不足15。我只有1个问题scanf是否在上一个循环中的stdin中的每个循环上保存一个指向记忆的指针?@MeryVorente:
scanf()
不这样做,是流结构做的。
文件
对象是一种结构,它保存有关流的信息,例如当前位置、从设备或文件读取但尚未被
getc()
fgets()
scanf()
fread()
读取的字符缓冲区。类似地,缓冲区保留由
putc()
fputs
fprintf
fwrite
写入的字节,直到将其刷新到终端或文件系统为止。通常,从连接到终端的
stdin
读取输入时,从用户处读取整行输入。。。。。。进入流缓冲区,
getc()
从中读取单个字节,
scanf()
读取足够的字节以执行格式字符串中指定的转换,即:直到读取的字节不再匹配预期语法。这
chaouchi@chaouchi:~/workspace/Demineur$ ./a.out
Write a number :
f 10
Write a number :
chaouchi@chaouchi:~/workspace/Demineur$