Chinaunix首页 | 论坛 | 博客
  • 博客访问: 153587
  • 博文数量: 15
  • 博客积分: 2146
  • 博客等级: 大尉
  • 技术积分: 370
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-20 21:20
文章分类

全部博文(15)

文章存档

2011年(6)

2008年(9)

我的朋友

分类: C/C++

2008-07-19 20:11:58

                                          C 语言中 scanf()的用法探讨
       scanf()作为 C 语言中的基本输入,曾经带给我们初次编写 C 程序的快乐。但是随着
C 的不断深入,我们却发现:原来最难理解的东西居然是我们自以为很熟悉的东西。
       我们真正了解 scanf()吗?那么看看下面的几个例子吧。
一、关于 scanf()中的格式控制符
       scanf()的格式控制符有多个,但我只想讨论一下%[]这个格式控制符。%[]可以用来进
行多个字符的输入,并对结束符进行自定义。
       ANSI C 标准向 scanf() 增加了一种新特性,称为扫描集(scanset)。 扫描集定义一
个字符集合,可由 scanf() 读入其中允许的字符并赋给对应字符数组。 扫描集合由一对
方括号中的一串字符定义,左方括号前必须缀以百分号。 例如,以下的扫描集使 scanf()
读入字符 A、B 和 C:
%[ABC]
使用扫描集时,scanf() 连续吃进集合中的字符并放入对应的字符数组,直到发现不在集
合中的字符为止(即扫描集仅读匹配的字符)。返回时,数组中放置以 null 结尾、由读入
字符组成的字符串。
对于许多实现来说,用连字符可以说明一个范围。 例如,以下扫描集使 scanf() 接受字
母 A 到 Z:%[A-Z]           重要的是要注意扫描集是区分大小写的。因此,希望扫描大、小写
字符时,应该分别说明大、小写字母。
对于%[]还可以用^+任意字符(包括 eof)来结束字符串的输入。比如%[^EOF]就是直到有
EOF 输入,字符串才中止。
但一定要记住就是 c 语言是缓冲输入,即使你%[^a],再你输入回车之前输入多少的 a 都是
不可能结束的。
如下面的一段程序:
#include
int main()
{
       char string[50];
       /*scanf("%s",string);不能接收空格符*/
       printf("Input [^\\n] string \n");
       scanf(" %[^'\n']",string);
       printf("The s[^\\n] string :%s\n",string);
       fflush(stdin);
       printf("Input [^a] string \n");
       scanf(" %[^a]",string);
       printf("'a' ends input :%s\n",string);
       printf("Input [A-F] string\n");
       scanf(" %[A-F]",string);
       printf("String is: %s\n",string);
       return 0;
}
运行结果:
ghost@ghost-desktop:~/Desktop/testzone/first$ ./t
Input [^\n] string
I love China!
The s[^\n] string :I love China!
Input [^a] string
I love youa
'a' ends input :I love you
Input [A-F] string
String is: I love you
ghost@ghost-desktop:~/Desktop/testzone/first$
通过上述运行结果,可能会感到疑惑,为什么 Input [A-F] string 根本就没有输入,哪来
的输出呀?这个问题就是我们将要讨论的话题。
二、关于 scanf()的异常情况
scanf()会产生什么异常呢?
先来看一段程序:
#include
int main()
{
       int i;
       char ch;
       for(i=0;i<=3;i++)
       {
              printf("%d ---- ",i);
              scanf("%c", &ch);
              printf("\n");
              //scanf("%*c");
              //printf("\n%c\n",ch);
              //getchar();
       }
        return 0;
}
运行结果:
ghost@ghost-desktop:~/Desktop/testzone/first$ ./t
0 ---- a
1 ----
2 ---- b
3 ----
ghost@ghost-desktop:~/Desktop/testzone/first$
产生其原因在于:
因为 scanf %c 只是读入一个字符,而你在输入时实际上输入的是:某个字符
+Enter,Enter 产生的\n 也会停留在输入缓冲区中,下次调用 scanf %c 时就会直接读到
它而不是等待你再次输入!同理,getchar()也有类似的行为。所以我们才不提倡使用
scanf("%c", ...),尤其是把它在循环中。
解决的方法:
(1)、将 scanf("%c", &ch); 修改为:
        scanf(" %c", &ch);   /*在%前加上一个空格*/
(2)、将 scanf("%c", &ch); 修改为:
        scanf("%c%*c", &ch);
(3)、函数名: fflush
功 能: 清除一个流
用 法: int fflush(FILE *stream);
#include
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');
       return 0;
}
(4)、如何处理 scanf()函数误输入造成程序死锁或出错?
#include
int main()
{
      int a,b,c; /*计算 a+b*/scanf("%d,%d",&a,&b);
      c=a+b;
      printf("%d+%d=%d",a,b,c);
      return 0;
}
      如上程序,如果正确输入 a,b 的值,那么没什么问题。但是,不能保证使用者每一
次都能正确输入,一旦输入了错误的类型,你的程序不是死锁,就是得到一个错误的结果,
这可能所有人都遇到过的问题吧?
      解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,即:这个 scanf ()
函数有几个变量,如果 scanf()函数全部正常读取,它就返回几。但这里还要注意另一个
问题,如果输入了非法数据,键盘缓冲区就可能还个有残余信息问题。
正确的例程:
#include
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);
      return 0;
}

阅读(14019) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

2011-08-18 16:19:16

应该是因为在Input [A-F] string 之前输入完后有个回车,在缓冲区里没被接收,下次输入是直接接收回车输入就结束了。可以通过输出最后的string ASC码验证验证。

chhaya2010-05-28 11:24:37

ls的 用fflush(stdin)清缓冲区, 再用gcc编译试试

chinaunix网友2010-04-19 17:21:45

这个就是为了说明上次输入的'a'字符仍然在标准输入的缓冲区中,下载再运行到scanf时,其从缓冲区中抓到a,从而导致下行的打印。对比3种方法,用fflush清空stdin buffer的方式最为安全!

chinaunix网友2009-04-03 17:01:18

为什么 Input [A-F] string 根本就没有输入,哪来 的输出呀? 没理解上去,请指教