索引:

1、scanf函数的一般形式
2、附加格式说明字符表修饰符说明 
3、问题一:scanf()函数不能正确接受有空格的字符串?
4、scanf()函数如何结束数据的输入
5、问题二:键盘缓冲区残余信息问题
6、问题三: 如何处理scanf()函数误输入造成程序死锁或出错?
7、%[ ] 的用法

===========================================================================

http://hdongq.blog.163.com/blog/static/169402621201021011158231/

scanf函数的一般形式  scanf(格式控制,地址表列)
  int scanf(char *format[,argument,...]);
  “格式控制”的含义同printf函数;“地址表列”是由若干个地址组成的表列,可以是变量的地址,或字符串首地址。
  scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。
  例:使用scanf函数输入数据。
  #include<stdio.h>
  void main()
  {
  int a,b,c;
  printf("input a,b,c\n");
  scanf("%d%d%d",&a,&b,&c);
  printf("a=%d,b=%d,c=%d",a,b,c);
  }

格式字符说明  %a,%A 读入一个浮点值(仅C99有效) 
  %c 读入一个字符
  %d 读入十进制整数
  %i 读入十进制,八进制,十六进制整数
  %o 读入八进制整数
  %x,%X 读入十六进制整数
  %c 读入一个字符
  %s 读入一个字符串,遇空格、制表符或换行符结束。
  %f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入。
  %p 读入一个指针
  %u 读入一个无符号十进制整数
  %n 至此已读入值的等价字符数
  %[] 扫描字符集合
  %% 读%符号
  
  附加格式说明字符表修饰符说明
 
  L/l 长度修饰符 输入"长"数据
  h 长度修饰符 输入"短"数据
  W 整型常数 指定输入数据所占宽度
  * 表示本输入项在读入后不赋值给相应的变量

scanf的返回值  scanf的返回值有后面的参数决定

scanf("%d%d", &a, &b);
  如果a和b都被成功读入,那么scanf的返回值就是2
  如果只有a被成功读入,返回值为1
  如果a和b都未被成功读入,返回值为0
  如果遇到错误或遇到end of file,返回值为EOF。
  且返回值为int型

使用scanf函数时应该注意的问题

1、sacnf()中的变量必须使用地址。 
  2、scanf()的格式控制串可以使用其它非空白字符,但在输入时必须输入这些字符。
  3、在用"%c"输入时,空格和“转义字符”均作为有效字符。
  问题一:scanf()函数不能正确接受有空格的字符串?如: I love you!
  #include <stdio.h>
  int main()
  {
  char str[80];
  scanf("%s",str);
  printf("%s",str); 
  return 0;
  }
  输入:I love you!
  输出:

scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。
  ① 遇空格、“回车”、“跳格”键。
  ② 遇宽度结束。
  ③ 遇非法输入。

  所以,上述程序并不能达到预期目的,scanf()扫描到"I"后面的空格就认为对str的赋值结束,并忽略后面的"love you!".这里要注意是"loveyou!"还在键盘缓冲区(关于这个问题,网上我所见的说法都是如此,但是,我经过调试发现,其实这时缓冲区字符串首尾指针已经相等了,也就是说缓冲区清空了,scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中)。我们改动一下上面的程序来验证一下:
  #include <stdio.h>
  #include<windows.h>
  int main()
  {
  char str[80];
  char str1[80];
  char str2[80];
  scanf("%s",str);/*此处输入:I love you! */
  printf("%s",str);
  Sleep(5000);/*这里等待5秒,告诉你程序运行到什么地方*/     /*不是sleep(5) 1,函数名是Sleep不是sleep。2,C/C++中,unsigned Sleep(unsigned)应该是毫秒ms.
  scanf("%s",str1);/*这两句无需你再输入,是对键盘盘缓冲区再扫描 */
  scanf("%s",str2);/*这两句无需你再输入,是对键盘盘缓冲区再扫描 */
  printf("\n%s",str1);
  printf("\n%s",str2);
  return 0;
  }
  输入:I love you!
  输出:
  I
  love
  you!
  好了,原因知道了,那么scanf()函数能不能完成这个任务?回答是:能!别忘了scanf()函数还有一个 %[] 格式控制符(如果对%[]不了解的请查看本文的上篇),请看下面的程序:
  #include "stdio.h"
  int main()
  {
  char string[50];/*scanf("%s",string);不能接收空格符*/
  scanf("%[^\n]",string);
  printf("%s\n",string);
  return 0;
  }
  问题二:键盘缓冲区残余信息问题
  #include <stdio.h>
  int main()
  {
  int a;
  char c; do
  {
  scanf("%d",&a);
  scanf("%c",&c);
  printf("a=%d c=%c\n",a,c);/*printf("c=%d\n",c);*/
  }while(c!='N');
  } 
  scanf("%c",&c);这句不能正常接收字符,什么原因呢?我们用printf("c=%d\n",c);将C用int表示出来,启用printf("c=%d\n",c);这一句,看看scanf()函数赋给C到底是什么,结果是c=10,ASCII值为10是什么?换行即\n.对了,我们每击打一下"Enter"键,向键盘缓冲区发去一个“回车”(\r),一个“换行"(\n),在这里\r被scanf()函数处理掉了(姑且这么认为吧^_^),而\n被scanf()函数“错误”地赋给了c.解决办法:可以在两个scanf()函数之后加个fflush(stdin);,还有加getch() , getchar()也可以,但是要视具体scanf()语句加那个,这里就不分析了,读者自己去摸索吧。但是加fflush(stdin);不管什么情况都可行。
  (
  函数名: fflush 
  功 能: 清除一个流
  用 法: int fflush(FILE *stream);
  )
  #include <stdio.h>
  int main()
  {
  int a;
  char c; do
  {
  scanf("%d",&a);
  fflush(stdin);
  scanf("%c",&c);
  fflush(stdin);
  printf("a=%d c=%c\n",a,c); }while(c!='N');
  } 
  这里再给一个用“空格符”来处理缓冲区残余信息的示例:运行出错的程序:
  #include <stdio.h>
  int main()
  {
  int i;
  char j;
  for(i = 0;i < 10;i++)
  {
  scanf("%c",&j);/*这里%前没有空格*/
  }
  }
  使用了空格控制符后:
  #include <stdio.h>
  int main()
  {
  int i;
  char j;
  for(i = 0;i < 10;i++)
  {
  scanf(" %c",&j);/*注意这里%前有个空格*/
  }
  } 
  可以运行看看两个程序有什么不同。
  问题三: 如何处理scanf()函数误输入造成程序死锁或出错?
  #include <stdio.h>
  int main()
  {
  int a,b,c; /*计算a+b*/
  scanf("%d,%d",&a,&b);
  c=a+b;
  printf("%d+%d=%d",a,b,c);
  }
  如上程序,如果正确输入a,b的值,那么没什么问题,但是,你不能保证使用者每一次都能正确输入,一旦输入了错误的类型,你的程序不是死锁,就是得到一个错误的结果,呵呵,这可能所有人都遇到过的问题吧?解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,它就返回几。但这里还要注意另一个问题,如果输入了非法数据,键盘缓冲区就可能还个有残余信息问题。正确的例程:
  #include <stdio.h>
  int main()
  {
  int a,b,c; /*计算a+b*/
  while(scanf("%d,%d",&a,&b)!=2)fflush(stdin);
  c=a+b;
  printf("%d+%d=%d",a,b,c);
  }
  补充: fflush(stdin)这个方法在GCC下不可用。(在VC6.0下可以)
  以下是 C99 对 fflush 函数的定义:
  int fflush(FILE *stream);
  如果stream指向输出流或者更新流(update stream),并且这个更新流
  最近执行的操作不是输入,那么fflush函数将把任何未被写入的数据写入stream
  指向的文件(如标准输出文件stdout)。否则,fflush函数的行为是不确定的。
  fflush(NULL)清空所有输出流和上面提到的更新流。如果发生写错误,fflush
  函数会给那些流打上错误标记,并且返回EOF,否则返回0。
  由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。故而使用
  fflush(stdin) 是不正确的,至少是移植性不好的。

  可采用如下方法:
  /* 此函数可以和scanf函数一起使用,但使用%c输入时要注意,即此函数只能用于缓冲区非空的情况 */
  void flush() 
  {
  char c;
  while ((c=getchar()) != '\n'&&c!=EOF) ;
  }
  #include <stdio.h>
  int main()
  {
  int a,b,c; /*计算a+b*/
  while(scanf("%d,%d",&a,&b)!=2) flush();
  c=a+b;
  printf("%d+%d=%d",a,b,c);
  }

http://blog.csdn.net/lbird/archive/2007/08/03/1724429.aspx

sscanf/scanf特殊用法  
%[ ] 的用法:%[ ]表示要读入一个字符集合, 如果[ 后面第一个字符是”^”,则表示反意思。

[ ]内的字符串可以是1或更多字符组成。空字符集(%[])是违反规定的,可

导致不可预知的结果。%[^]也是违反规定的。

%[a-z] 读取在 a-z 之间的字符串,如果不在此之前则停止,如

char s[]="hello, my friend” ;         // 注意: ,逗号在不 a-z之间

sscanf( s, “%[a-z]”, string ) ; // string=hello

%[^a-z] 读取不在 a-z 之间的字符串,如果碰到a-z之间的字符则停止,如

char s[]="HELLOkitty” ;         // 注意: ,逗号在不 a-z之间

sscanf( s, “%[^a-z]”, string ) ; // string=HELLO

%*[^=]    前面带 * 号表示不保存变量。跳过符合条件的字符串。

char s[]="notepad=1.0.0.1001" ;

char szfilename [32] = "" ;

int i = sscanf( s,"%*[^=]", szfilename ) ; // szfilename=NULL,因为没保存

int i = sscanf( s, "%*[^=]=%s", szfilename ) ; //szfilename=1.0.0.1001

%40c      读取40个字符

The run-time

library does not automatically append a null terminator

to the string, nor does reading 40 characters

automatically terminate the scanf() function. Because the

library uses buffered input, you must press the ENTER key

to terminate the string scan. If you press the ENTER before

the scanf() reads 40characters, it is displayed normally,

and the library continues toprompt for additional input

until it reads 40 characters

%[^=]     读取字符串直到碰到’=’号,’^’后面可以带更多字符,如:

char s[]="notepad=1.0.0.1001" ;

char szfilename [32] = "" ;

int i = sscanf( s, "%[^=]",szfilename ) ; // szfilename=notepad

如果参数格式是:%[^=:] ,那么也可以从 notepad:1.0.0.1001读取notepad

使用例子:

chars[]="notepad=1.0.0.1001" ;

char szname [32] = "" ;

char szver [32] = “” ;

sscanf( s, "%[^=]=%s", szname , szver ) ; // szname=notepad, szver=1.0.0.1001

总结:%[]有很大的功能,但是并不是很常用到,主要因为:

1、许多系统的 scanf 函数都有漏洞. (典型的就是 TC 在输入浮点型时有时会出错).

2、用法复杂, 容易出错.

3、编译器作语法分析时会很困难, 从而影响目标代码的质量和执行效率.

个人觉得第3点最致命,越复杂的功能往往执行效率越低下。而一些简单的字符串分析我们可以自已处理。

scanf的用法大全相关推荐

  1. printf用法大全,C语言printf格式控制符一览表printf用法大全,C语言printf格式控制符一览表

    输入输出函数(printf 和 scanf)是C语言中非常重要的两个函数,也是学习C语言必学的两个函数.在C语言程序中,几乎没有一个程序不需要这两个函数,尤其是输出函数(printf),所以这两个函数 ...

  2. C# MessageBox 用法大全(转)

    C# MessageBox 用法大全 http://www.cnblogs.com/Tammie/archive/2011/08/05/2128623.html 我们在程序中经常会用到MessageB ...

  3. python代码大全表解释-python中的字典用法大全的代码

    如下代码是关于python中的字典用法大全的代码. #!/usr/bin/env python # # [SNIPPET_NAME: Dictionaries 101] # [SNIPPET_CATE ...

  4. pythonurllib模块-Python3中核心模块urllib的用法大全

    Python的urllib模块提供了一个高级的Web通信库,支持基本的协议,如HTTP.FTP和Gopher,同时也支持对本地文件的访问.在Python3中,urllib.urlparse.urlli ...

  5. MVC中HtmlHelper用法大全

    MVC中HtmlHelper用法大全参考 解析MVC中HtmlHelper控件7个大类中各个控件的主要使用方法(1) 2012-02-27 16:25 HtmlHelper类在命令System.Web ...

  6. c3p0 参数 模糊查询_MySQL模糊查询用法大全(正则、通配符、内置函数等)

    文章来源:MySQL模糊查询用法大全(正则.通配符.内置函数等) 原文作者:陈哈哈 来源平台:CSDN SELECT * from table where username like '%陈哈哈%' ...

  7. C# ASP.NET MVC HtmlHelper用法大全

    C# ASP.NET MVC HtmlHelper用法大全 (原文) HTML扩展类的所有方法都有2个参数: 以textbox为例子 public static string TextBox( thi ...

  8. [Delphi]ListView基本用法大全

    Delphi ListView基本用法大全 //增加项或列(字段) ListView1.Clear; ListView1.Columns.Clear; ListView1.Columns.Add; L ...

  9. Python:print用法大全

    参考链接: Python中print用法大全(打印字符串,整形和浮点型)

  10. CString的成员函数用法大全

    CString的成员函数用法大全(转) PS:来自 https://www.cnblogs.com/Caiqinghua/archive/2009/02/16/1391190.html 写的很好! C ...

最新文章

  1. Java爬取解析去哪儿景点信息
  2. PyTorch 1.6、TensorFlow 2.3、Pandas 1.1同日发布!都有哪些新特性?
  3. jxl解析excel
  4. matlab循环前后变量定义,Matlab for 多个变量循环能不能这样啊 ,求教高手!!!!...
  5. 如何将windows10的显示字体调大
  6. 解读多云跨云下的容器治理与实践
  7. 【英语学习】【Level 07】U06 First Time L1 My very first trip
  8. CodeForces Round #280 (Div.2)
  9. Windows10更改电脑用户名
  10. Oracle中connect by...start with...的使用
  11. Pytorch——常用的神经网络层、激活函数
  12. Amoeba:开源的分布式数据库Porxy解决方案
  13. kafka 可以脱离 zookeeper 单独使用吗
  14. leeCode350_两个数组的交集
  15. WARNING: Ignoring invalid distribution -ip 解决方案
  16. sql注入基础(一)
  17. SOLIDWORKS Simulation带接触的装配体分析方法
  18. MySQL大in查询技术如何优化?
  19. sys/types.h
  20. 2022春 计算机系统大作业 程序人生-Hello’s P2P

热门文章

  1. linux usb摄像头UVC usb3300 stm32F4
  2. 2017java考证_Sun认证Java程序员考试试题
  3. linux下ASM配置
  4. 人脸对齐—级联回归模型和深度学习模型
  5. 【统计学知识案例实践】—数据分析实战案例
  6. k均值算法原理及matlab实现
  7. 项目工作说明书(SOW)
  8. 马尔可夫链模型--通俗
  9. php php拼接字符串函数_PHP_PHP开发中常用的字符串操作函数,1,拼接字符串 拼接字符串是最 - phpStudy...
  10. 只会纯硬件,让我有点慌