今天在看同事的代码时遇上下面一行代码:
fscanf(pfile, "WEBSPORT=\"%[^\"]\n", webport);
代码的作用很简单,只是函数中的格式控制符我突然有点感觉陌生了,从学校出来后,就比较少用到scanf函数,因此对它的格式控制符也就渐渐地陌生。既然陌生,就必须要重新熟悉才行,于是上网查找了一下,彻底地弄明白上面的含义,重新熟悉了一下scanf函数的格式控制符。在此备忘个人觉得比较容易忘记的一些格式控制符。
scanf中的完整格式控制字符串序列:
"% * 域宽 l/h d/o/x/c/s/f/e" //无%u格式、%g格式
说明:
-
%后的“*” 附加说明符,用来表示跳过它相应的数据
-
根据格式字符的含义从输入流中取得数据,当输入流中数据类型与格式字符要求不符时,就认为这一项结束
-
隐示分隔符:空格、制表符('\t')、换行符('\n')都是C语言认定的数据分隔符
-
显示分隔符。在scanf函数的两个格式说明项间有一个或多个普通字符,那么在输入数据时,在两个数据之间也必须以这一个或多个字符分隔。如语句:
scanf("a=%d,b=%f,c=%f", &a, &b, &c); //输入数据应该为:a=1234,b=67.8,c=98.123
字符串的输入
-
使用 %s 格式符是可以的,但是%s遇到空白字符(空格、制表符、\r、\n)就结束
-
使用 %[...] 格式模式进行字符串输入的匹配控制,通过示例进行说明:
const char *p="12232114687adeABC12356";scanf("%[123]%[46-8]%[a-zA-Z]%[1-6]", buf1,buf2,buf3,buf4);//上面语句的结果将为:buf1="1223211",buf2="4687"//buf3="adeABC",buf4="12356"
%[pattern]表示从输入源读取字符到变量中,直到读取到的某个字符不属于pattern模式中的字符停止,pattern中的字符不区分先后顺序,以单个字符作为基本单元;pattern支持范围表示,如只读取数字,可以使用%[0-9],只读取字母,使用%[a-zA-Z];如果pattern中的第一个字母是"^",则表示对^符号之后的pattern取反,如%[^A-Za-z]的意思就是取字母之外的所有字符。
-
使用 %[^\n]%*c 读取一行字符,不能使用%s进行读取,表示读到\n为止,%*c的作用就是把\n去掉,否则再次读的时候一直遇到的都是\n。
-
所有对%s起作用的控制,都可以用于%[],比如"%*[^\n]%*c"就表示跳过一行,"%-20[^\n]"就表示读取\n前20个字符。
现在再来看文章开头的那行代码就清楚了:"%[^"]\n,"将双引号进行转义为普通字符,%[^"]表示读取到下一个双引号结束,\n表示在输入源中有一个换行符。实际的文件输入源内容为:
WEBSPORT="80"
文章参考:
补充:
- 今天看到%n格式控制符:%n读取scanf和printf函数在该格式符之前实际已经读取或输出的字符数量,将该数量存储在函数中对应位置的整形变量内(可以不管它),可以用来进行指针的移动和定位。%n格式控制符的使用不影响scanf和printf函数的返回值,以及后续格式符的使用。
- 关于scanf和printf函数的返回值:scanf函数返回的是实际成功匹配和赋值的变量个数,第一个都不匹配时返回0,如果在进行第一个变量转换时到达输入结束则返回EOF;而printf函数返回的是输出的字符数量(不包含字符串结束符)。