分享

C语言 认识转换符 fscanf()用法

 gxr003 2017-08-18

1 原型

int    fscanf(FILE *stream,  const  char* format, …)

功能:    从stream流中连续读取能够匹配format格式的字符到参数列表中对应的变量里。

参数:    “stream”是FILE指针类型变量,它指向一个真实的流对象。

“format”是C字符串,由“空格”、“非空格”及“转换符”组成。具体格式为%[*][width][modifiers]type。见2.1与format参数相关的概念

“…”是与“format”中“转换符”对应变量地址的列表,两地址间用逗号隔开。

返回值:成功时返回从流中读取成功的数据的个数。失败时返回-1(Debian Linux)。

头文件


2 使用fscanf()

2.1与format参数相关的概念

fscanf()的format参数允许的格式为:“%[*][width][modifiers]type”。[]中的内容根据需要供选,可缺省,%type必须要有,不可省。


%:是format参数的起始符号,不可缺少。


%[modifiers]type:表一种类型转换符,如%hd表示short int类型转换符。它是format的核心。转换符的作用是将“数据”转换为转换符代表的数据类型,这里提到的数据必须能够转换为转换符代表的数据类型,fscanf读取数据时也只匹配这样的数据。如pF指向一文件,其中只包含数据[123 [空格] 456],用“fscanf(pF, “%d”, &m);”语句是将123这个数据转换为转换符”%d”所代表的数据类型即整型后保存到&m地址中去。


%*[modifiers]type: 表示跳过stream流中能够被转换为[modifiers]type所代表数据类型的数据不读,如在以上的文件中,用“fscanf(pF, “%*d%d”, &m);”就可以跳过对123的读取,而将456转换为整型后保存到&m地址中。%*m[modifiers]type表跳过stream流中能够被转换为[modifiers]type所代表数据类型的m个“字符”不读。如“fscanf(pF,“%*1d%d”, &m);”是将23转换为整型后保存到&m地址中去。


%width[modifiers]type:表示从stream流中读取width长度的“字符”来转换为[modifiers]type对应数据类型的数据。如“fscanf(pF, “%1d”, &m);”是将1转换为整型后保存到&m地址中去。

2.2 fscanf()例子

fscanf()可以用于读取文件流中的数据。现设有一个文件内容如下,


Figure1:ffReadFile.dat文件

拥有3个数字行的最后一个数字决定拥有两个数字的行数。用fscanf()函数读取其内的内容以笔记到fscanf()函数的用法。


2.2.1 fscanf()对空格的处理

用fopen成功打开ffReadFile.dat文件后,单用以下语句读取文件的第一行内容:

re = fscanf(pF, '%d%d%d', &oLine.p, &oLine.l, &oLine.x);if( 3 == re){ //Print on stdout printf('%d\t%d\t%d\n', oLine.p, oLine.l, oLine.x);}

此时,可以正确的打印第一行内容到屏幕之上。fscanf()函数读取第一行三个数据的过程如下:



Figure2:fscanf()函数读取数据过程

文件指针最开始指向ffReadFile.dat的第一个字符(即1)处,然后fscanf()根据“format”中的第一个“转换符”读取文件中的内容直到不符合当前“转换符”能够转换的字符为止,如果不符合“转换符”的数据为空格或者tab则舍掉空格或者tab使文件指针指向下一个数据。然后fscanf()继续在文件中匹配下一个“转换符”的数据。直到为所有的“转换符”匹配完数据为止。


2.2.2 fscanf()对不符合“特定格式”数据的处理

当不符合“特定格式”所要求的数据且不为空格和tab时,fscanf()将匹配到符合“特定格式”的数据赋给地址后不再往下读。如现将ffReadFile.dat中的内容修改如下:


Figure3:ffReadFile.dat修改

再用以下代码读取第一行数据,

re = fscanf(pF, '%d%d%d', &oLine.p, &oLine.l, &oLine.x);if( 3 == re){ //Print on stdout printf('%d\t%d\t%d\n', oLine.p, oLine.l, oLine.x);}else{ switch(re){ case 1: printf('oLine.p: %d\n', oLine.p); break; case 2: printf('oLine.p: %d, oLine.l: %d\n', oLine.p, oLine.l); break; default: printf('fscanf() read TypeLine error,re: %d\n', re); break;}
re的值将是1,从而输出读取成功的oLine.p的值。对于此时的情况,只为&oLine.p成功获取了数据,另外两个地址的数据都获取失败。


2.2.3 fscanf()“跳读符:*”

使用‘*’可以跳过文件中的部分内容,比如还是图2中的内容,利用以下的语句替换上个程序的fscanf()语句来读取第一行数据:

re = fscanf(pF, '%d%*3c%d%d', &oLine.p, &oLine.l, &oLine.x);

那么程序的输出结果为:100       3       2

%*3c表示跳过3个字符内容。结合2.1程序就得到了如期的输出结果。


2.2.4 fscanf()与输入模式相同的读取

如果ffReadFile.dat文件中的内容如下,


Figure4:ffReadFile.dat

那么如果要读取文件中的第一行内容,书写以下语句即可:

fscanf(pF, '%d,%d,%d', &oLine.p, &oLine.l, &oLine.x);
以上提到的逗号甚至可以换成’a’这样的字符,但不可以为字符串(Debian Linux 下验证)。


2.2.5 fscanf()读取指定长度的数据

针对上图的文件,可以使用以下语句

fscanf(pF, '%3d,%d,%d', &oLine.p, &oLine.l, &oLine.x);
为&oLine.p读取只有3位长的数据,但因为此时文件指针指向10000中最后的那个0使文件中内容与fscanf()“format”不再匹配,后两个地址不能够正确的获取数据。


2.2.6 fscanf()的“format”中的[modifiers]type

以上各个小例子已经笔记了fscanf的一些特性,它读数据成功与否是看文件中的数据是否与format的转换符相匹配。type就是C语言中的c(字符转换符), d(整型转换符符), e、E、f、g、 G(浮点型转换符), o(八进制类型转换符), s(字符串类型转换符), u(无符号整型转换符), x、X(16进制数转换符)转换符。个人对转换符的理解是这样的:将内存中的二进制转换为某种类型,如%d是将存储到内存中的一段二进制转换为整型数据。


modifiers是用来为某些数据提供进一步类型转换用的,比如%d表示将匹配到的数据转换为整型。但在C语言的数据类型中还分整型和短整(short int),如果想要将读取到的数据转换为短整型就需要使用modifiers(‘h’)来进一步表示将匹配到的数据转换为短整型。同理,对于其它可以有进一步分类的数据类型也一样,modifiers提供相应的符号来供数据的进一步转换。Modifiers符号有:

  • h,加在d, i, n整数类型转换符前面,整体表示short  int类型转换符。加在o, u,x整型转换符前,整体表示unsigned short  int类型转换符。
  • l,加在d, I, n整数类型转换符前,整体表示long int类型转换符。加在o, u, x整型类型转换符前,整体表示unsigned  long int类型转换符。加在e, f,g浮点数转换符前,整体表示double类型转换符。
  • L,加在e, f, g浮点数类型转换符前,整体表示long double类型转换符。

3 使用fscanf()注意的地方

确保检查返回值,以确定找到了期待的值。而使用%s 格式的时候,一定要小心缓冲区溢出。


CNote Over.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多