曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5611|回复: 0
打印 上一主题 下一主题

scanf,fscanf,sscanf

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-2-11 18:10:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
scanf 函数家族和 printf 函数家族工作相似,除了这些函数是从一个流里读条目并把值放进变量中,而在函数中是传进变量的地址。它们使用同样的格式字符串控制输入转换。

用法
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *s, const char *format, ...);

用来保存扫描进来的值(由scanf 函数扫描进来)的变量类型正确并精确匹配格式字符串非常重要。如果不是,那内存可能会被破坏并且程序会死掉。这在编译上没什么错误,如果比较幸运,那么可能会看到一个警告信息。

例如
int num;
scanf(“Hello %d”, &num);

scanf 以及其家族成员函数中的格式字符串含有普通字符和转换说明符。注意,如上例中,在输入时,普通字符也要被输入,即要输入 Hello 10 这样的形式,那么 10 才会被赋值到 num 变量中。这里的输入,允许 Hello 和 10 之间有空格,因为其间的所有空格(空格,tabs,form feeds(换页),新行(newline) )都要被忽略掉。另外,这样的输入 Hello1234 也可以接受,即是1234自动会被赋值给 num。
像 Hello1d3 这样的形式,num 中只会读取到 1 ,因为 1 后面的 d 是字符,所以其后的所有内容都会被忽略掉。对于不符合格式要求的输入,转换就会失败,scanf 就返回了。


转换说明符:
%d : 扫描一个十进制整数
%o,%x : 扫描一个八进制,十六进制整数
%f,%e,%g : 扫描浮点数
%c : 扫描一个字符(不跳过空白符)
%s : 扫描一个字符串
%[] : 扫描一套字符
%% : 扫描一个 % 符号

像 printf 一样,scanf 也可以在转换说明符里限制输入的长度,如 %hd 表示 short int 限制;%ld 表示 long int 限制; %lg 表示双精度浮点型数。

%c 读入单个字符,不会跳过初始化的空白符。

%s 扫描字符串,会跳过引导的空白符,但会停在第一个空白符处;所以,最好用这来读单词(words)而不是通常的字符串。如果没有
    域宽度说明符,也没有限制可能读到的字串长度,那么接收串空间需要足够长度来容纳最长输入流中字符串。最好还是使用一个域说明符,或者结合 fgets 和 sscanf 一起使用,然后再读进输入的一行,接着再去扫描它。这样一来,就可以阻止恶意用户利用缓冲区溢出。

使用 %[] 说明符读取一个由一打字符组成的字符串。如格式为 %[A-Z] 的就会读取大写字母,如果前面加个 ^ (%[^])字符,则反过来就不会去读取 A-Z 中任一个字符。所以,读取一个含有空格的字符串,但需要停在第一个逗号处,则可以使用 %[^,] 。



测试代码
#include <stdio.h>

main()
{
        char s[256];
        int n;
        float f;
        char c;
        int scanf_count;

scanf_count = scanf("Hello, %d, %g, %c, %[^\n]",&n,&f,&c,s);

        printf("%d\n",n);
        printf("%g\n",f);
        printf("%c\n",c);
        printf("%s\n",s);
        printf("scanf scaned result: %d\n", scanf_count);

        return 0;
}

输入内容及输出结果
[root@localhost ~]# ./scanf.exe
Hello, 1234, 5.678, X, string to the end of the line  #输入内容
1234
5.678
X
string to the end of the line
scanf scaned result: 4

分析:
scanf 函数返回成功读取后所读取到的条目,这里就是 4 条。

如果读取第一个条目失败了就会返回 0 ,如以下的随意输入:
[root@localhost ~]# ./scanf.exe
dfa  #输入内容
0
0


scanf scaned result: 0

如果在第一个条目匹配之前就到达输入末尾,则 EOF 返回。

如果在读取时发生错误,则流错误标志被置位,并且可以通过 error 看到错误类型。

通常,scanf 及其“朋友函数”(和 scanf 类似的,如fscanf,sscanf 等,我自己说的) 并不会得到特别的青睐,原因有三:

1、习惯上,函数执行完成时常常表现出存在这样那样等问题;
2、使用起来灵活性不够;
3、导致难以解读代码。

一个可以代替的方法是,尝试使用起他的函数,如 fread 或者 fgets,用她们来读取输入行,然后根据需要用字符串函数去把这些船分成更小的条目。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-7 07:38 , Processed in 0.113529 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表