C格式化输入scanf()、sscanf()和fscanf()

经常遇到文件、控制台和字符串为缓冲区的格式化输入输出,所以很有必要总结一下,争取毕其功于一役,以后遇到此类问题不再到处查阅。

 

C语言中的几种输入方式:

scanf()   从控制台键盘输入;

sscanf()  从字符串缓冲区输入与指定格式相符的数据;

fscanf()   从文件输入;

平时使用中遇到的最大问题就是这几个函数的参数弄不明白彻底;其实想搞明白这一点需要了解一下正则表达式。

这里有篇正则表达式的教程可以参考一下:http://www.runoob.com/regexp/regexp-tutorial.html

 

http://www.cplusplus.com/reference/上找到三个函数的函数原型:

int scanf ( const char * format, ... );

int sscanf ( const char * s, const char * format, ...);

int fscanf ( FILE * stream, const char * format, ... );

 

  三个函数的共有参数:   const char * format,      

 

三个函数有相同的参数const char * format;

       1.1   该参数可以是一个或多个 {%[*] [width] [{h | I | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号}

1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)

       %*d:匹配到的整数被过滤掉

       %*s:匹配到的字符串被过滤掉

       %*[a] :匹配到的a字符均被过滤掉

2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。(没明白怎么用,可以给讲讲)

3、width表示读取宽度。

          %6c :读取匹配到的6个字符

4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。                      (没明白怎么用,可以给讲讲)

5、type :这就很多了,就是%s,%d之类。

6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值失败返回0 ,否则返回格式化的参数个数

              %*8c :过滤掉匹配到的8个字符

7、如果读取的字符串,不是以空格来分隔的话,就可以使用%[]。

      经常读取的字符串中有分隔符可以使用 %*[分隔符] 将分隔符过滤掉。            

      

1.2 集合操作

%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配),

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

%[aB'] 匹配a、B、'三者中一员,贪婪性

%[^a] 匹配非a的任意字符,一旦遇到a停止读入,贪婪性。其中‘^’后面可以带更多的字符。

综上,%[ ] 表示要读入一个字符集合如果'['后面第一个字符是“^”,则表示相反的意思,[ ]内的字符为1个或者更多字符组成的,各个字符之间是并列关系。

 

1.3 sscanf()格式代码示例:

#include <stdlib.h>
#include <ctype.h>
#include <iostream>
 
using namespace std;
 
#define  BUFSIZE 128
 
int main()
{
 
	//注意:什么位置的空格才可以被自动略过
	double x = 0.0, y = 0.0, z=0.0;
	char * text1 = "ENU:37.69129,  110.97952    ,2583.369";
	int num = sscanf(text1, "%*[A-Z]%*[:]%lf,%lf%*[ ],%lf", &x, &y, &z);
	printf("x:%lf, y:%lf, z:%lf\n", x, y, z);       //x:37.691290, y:110.979520, z:2583.369000
 
 
	x = 0.0, y = 0.0, z = 0.0;
	 num = sscanf(text1, "%*4c%lf,%lf%*[ ],%lf", &x, &y, &z);
	printf("x:%lf, y:%lf, z:%lf\n", x, y, z);  //x:37.691290, y:110.979520, z:2583.369000
	  

	char * des = (char*)malloc(BUFSIZE);
	char * des0 = (char*)malloc(BUFSIZE);
 
	char buffer[BUFSIZE] = "  38.259  , 5896 DEVOTIOON";
	char buf[BUFSIZE] = "38.259  , 5896 stay foolish";
	
	
	//1.一般用法
	sscanf(buffer, "%s", des);
	printf("%s \n", des);
 
	//2.取指定长度的字符串,取最大长度为4的字符串
	memset(des, '\0', BUFSIZE);
	sscanf(buffer, "%4s", des);
	printf("%s \n", des);     //38.2
 
	//3.取到指定字符为止的字符串, 如取遇到空格为止的字符串
	memset(des, '\0', BUFSIZE);
	sscanf(buf, "%[^ ]",des);
	printf("%s  \n", des);            //38.259
 
	//4.取仅包含指定字符集的字符串: 取包含1-9和小写字母的字符串
	memset(des, '\0', BUFSIZE);
	sscanf(buffer, "%[1-9 ,.]",des);       //"%[1-9 ,.]"含有空格
	printf("%s \n", des);                   //  38.259  , 5896
 
	//取到指定字符集为止的字符串。 取遇到大写字母为止的字符串
	memset(des, '\0', BUFSIZE);
	sscanf(buffer, "%[^A-Z]", des);
	printf("%s \n", des);             //  38.259  , 5896    
 
 
	//给定一个字符串itertor/54367#,获取 / 和 # 之间的字符串,
	//%*[^/]过滤掉非'/'的字符,'/'字符存在,%[^#]读取非'#'的字符,遇到'#'停止,将读取的非"#"字符传到des
	memset(des, '\0', BUFSIZE);
	sscanf("itertor/54367#", "%*[^/]/%[^#]", des);      
	printf("%s\n", des);              //54367
 
 
	//scanf() 的两个小例子
	//输入一个字符串,这个祖父穿只含有小写字符,遇到第一个不是小写字符时停止
	char * str = (char*)malloc(BUFSIZE);
	printf("Please input lowercase characters:");
	scanf("%[a-z]", str);
	printf("received lowercase characters%s \n", str);
 
	输入一个字符串,遇到字符"."停止。
	memset(str, '\0', BUFSIZE);
	printf("Please input lowercase string(quit with signal ';' ouccrring):");
	scanf("%[^;]", str);
	printf("received lowercase characters%s \n", str);
 
 
	free(des);
	free(des0);
	return 0;
}
 
 

1.4.scanf() 

https://blog.csdn.net/21aspnet/article/details/174326 这篇博文讲解的scanf很详细,见过最好的。

https://www.cnblogs.com/mylinux/p/4635510.html

 

 

 

参考: https://www.jb51.net/article/138506.htm

            http://www.runoob.com/regexp/regexp-tutorial.html

            scanf()常犯错误 (讲解scanf非常详细)

           

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值