C的scanf函数+EOF+C扩展的fflush函数

本文详细解析了C语言中的scanf函数,包括其定义、参数、返回值及特殊使用情况等。并通过实例说明了如何正确使用scanf函数进行输入,以及与cin的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scanf函数:

  1. 定义:格式输入函数
  2. 参数:格式控制字符串,变量地址列表
  3. 作用:读取stdin标准输入缓冲区 中 某数据 送至 某地址
  4. 过程:当stdin流为空时,scanf会等待用户输入,

      否则scanf每操作一个stdin流中的按键ASCII码,就将它在stdin中清除;
    
      其中符合格式控制符字符串  要求的  字符串中 的 字符  分三类情况
    
      A.合法数据:存入相应地址,eg:十进制数合法于%d
      B.分隔符:略去          eg:未指定分隔符时,输入的空白符<下文有介绍>
      C.未指定操作:无操作     eg:格式控制符字符串最后一个字符为分隔符<下文有实例>
    
  5. 返回值:返回成功赋值的数据个数,读到文件末尾出错则返回EOF

  6. 与printf的格式控制字符串的区别:scanf没有精度控制

  7. 总结:

用scanf函数进行输入,必须指定输入的数据的类型和格式,不仅繁琐复杂,且易错。
C++保留scanf只为了兼容C,以便过去用C语言写的程序可以在C++的环境下运行。
C++的编程人员都愿意使用cin进行输入,很少使用scanf。

EOF

(1)翻译:end of file
(2)意义:“文字流”的结尾
(3)定义:定义在stido.h首部的常量,一般值为-1
#define EOF (-1);
(4)对象:此处的“文字流”,可以是文件,或者 标准输入(stdin)
(5)区别:stdin无法预知长度,必须手动输入一个字符,达到EOF
Eg:输入ctl+Z

scanf函数的常见特殊情况

背景

  • 键盘缓冲区:缓存按下enter键之前的按键ASCII码,并显示依序按键对应内容

  • stdin流:按下enter键之后,缓存键盘缓冲区的ASCII码序列,包括enter键,然后清空键盘缓冲区

  • scanf标识当前数据结束:分隔符,或者不合要求格式的数据 eg:%d,输入1.23

分隔符
一.意义:标识着当前数据已读完,且该符号后面还有待读取的数据
二.分类
A.空白符
(1)组成:制表符tab,空格space,新行符enter
(2)特点:无需在格式控制字符串中指定,就算指定了具体某空白符,也是按所有空白符算

scanf(“%d %d”,&a,&b);//指定space作为分隔符,但实际输入时,用tab,enter做分割符也可以

(3)特殊:在仅%c的情况下,空白符当成合法字符;即输入空白符时,scanf(“%c”,&c)等同c=getchar();
(4)说明:putchar和getchar均在ctype.h

B.非空白符:一旦在格式控制字符串中指定,就必须使用这种分割符,不能使用空白符做为分隔符

scanf(“%d,%d”,&a,&b);//指定逗号作为分隔符

(若此部分过于生涩,可以直接看下面的实例)

特殊:
(1)格式字符为%s时,空白符照常当作分隔符
解决:

char str[50];
scanf(“%[^/n]”,str);//将空白符当作 非分隔符处理

(2)格式字符为%c,且无非格式字符时,空白符不会当作分隔符

解决:
方案一:

scanf(“ %c”,&ch);//%c前加空格;将前一次存入stdin的空白符,当成分隔符处理`

方案二:

getchar();//空白符因取出而被清除

方案三:

fflush(stdin);//清除stdin缓存,即清除遗留的空白符  <fflush函数详见文末>

为什么在%c后加空格不行?(以下测试环境为Ubuntu的Linux系统)
判断并输出当前输入的字符类型
两次测试结果
问题
1.第一次需要“按键1+空白符+按键2+enter”:

(1)按键后,还差一个空白符才符合“%c ”,等待用户输入空白符(此次测试输入的空白符是enter)
(2)键入空白符,而空白符写在格式控制字符串中,意味着分隔符,即在分隔符的后面还有一位数据,继续等待用户输入
(3)再次按键,就完全符合了格式字符串的要求,此时等待用户按enter键
(4)键入enter,将键盘缓冲区,和enter键一起存入stdin标准输入缓冲区,并清空键盘缓冲区

2.本该判断前输入的字符类型,却成了判断上次输入字符的类型(第一次除外):
<以下图为例>
部分结果示例
Ps:规则:两个缓冲区,均是每操作完某数据,就清除该数据;
操作步骤与内存

fflush

  1. 作用:冲洗流中的信息
  2. 用处:通常用于磁盘处理文件
  3. 位置:stdio.h
  4. 原型:int fflush(FILE *stream)
  5. 返回值:成功刷新,指定的流没有缓冲区,只读打开,均返回0
    写错误丢失,返回EOF
  6. 注意:fflush是C/C++标准的扩展,∴只是部分编译器具有支持此功能
  7. 用法
fflush(stdin);//清空标准输入缓冲区
fflush(stdout);//stdout标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上
  • 用途:连续使用多个printf函数时,在每一个printf后加上fflush(stdout);
  • 原因:上一批存入stdout的数据还未输出完,下一批可能就存入stdout而覆盖掉了上一批数据,∴fflush(stdout);强制马上输出
### C语言 `scanf_s` 函数使用方法 #### 函数原型 `scanf_s` 的函数原型定义为: ```c int scanf_s(const char *format, ...); ``` 此函数用于安全地从标准输入读取数据并存储到变量中[^1]。 #### 安全特性 为了提高安全性,`scanf_s` 要求对于某些类型的参数提供额外的大小信息。这有助于防止缓冲区溢出和其他潜在的安全风险。例如,在处理字符串时,除了目标数组外还需要指明其最大长度[^4]。 #### 参数说明 - `const char *format`: 格式控制字符串,指示如何解析输入的数据。 - 后续参数按照格式串中的转换说明依次给出对应的地址或值。 #### 返回值 成功返回已赋值项的数量;遇到文件结束符或读错误则提前终止,并返回实际赋值数目;如果没有任何字段被分配,则返回EOF[^2]。 #### 使用实例 下面展示了一个简单的例子来演示如何利用 `scanf_s` 来读入两个固定长度不超过7字符(加上结尾'\0'共8字节空间)的字符串: ```c #include <stdio.h> int main(void){ char buf1[8], buf2[8]; printf("Enter two words separated by space:\n"); // 每次读取前先清空缓存区 fflush(stdin); // 正确的方式:指定每一块缓冲区的最大尺寸减一作为宽度限定符, // 并传递该整数常量紧跟在相应的指向接收位置之后 if (scanf_s("%7s %7s", &buf1, sizeof(buf1)-1, &buf2, sizeof(buf2)-1) != 2) { fprintf(stderr,"Input error\n"); return -1; } printf("You entered: \"%s\" and \"%s\"\n", buf1,buf2); } ``` 上述程序展示了当需要一次性读取多个项目时应怎样调用 `scanf_s` 。注意这里不仅限于字符串类型,其他基本数值型也可以采用相似方式操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值