欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

读懂C语言中的scanf函数:格式控制全解析

最编程 2024-08-08 15:09:16
...

今天在看同事的代码时遇上下面一行代码:

<!-- lang: cpp -->
 fscanf(pfile, "WEBSPORT=\"%[^\"]\n", webport);

代码的作用很简单,只是函数中的格式控制符我突然有点感觉陌生了,从学校出来后,就比较少用到scanf函数,因此对它的格式控制符也就渐渐地陌生。既然陌生,就必须要重新熟悉才行,于是上网查找了一下,彻底地弄明白上面的含义,重新熟悉了一下scanf函数的格式控制符。在此备忘个人觉得比较容易忘记的一些格式控制符。

scanf中的完整格式控制字符串序列:

<!-- lang: cpp -->
"%  *  域宽  l/h  d/o/x/c/s/f/e"   //无%u格式、%g格式

说明:

  1. %后的“*” 附加说明符,用来表示跳过它相应的数据

  2. 根据格式字符的含义从输入流中取得数据,当输入流中数据类型与格式字符要求不符时,就认为这一项结束

  3. 隐示分隔符:空格、制表符('\t')、换行符('\n')都是C语言认定的数据分隔符

  4. 显示分隔符。在scanf函数的两个格式说明项间有一个或多个普通字符,那么在输入数据时,在两个数据之间也必须以这一个或多个字符分隔。如语句:

    <!-- lang: cpp -->
    scanf("a=%d,b=%f,c=%f", &a, &b, &c); //输入数据应该为:a=1234,b=67.8,c=98.123
    

字符串的输入

  1. 使用 %s 格式符是可以的,但是%s遇到空白字符(空格、制表符、\r、\n)就结束

  2. 使用 %[...] 格式模式进行字符串输入的匹配控制,通过示例进行说明:

    <!-- lang: cpp -->
    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]的意思就是取字母之外的所有字符。

  1. 使用 %[^\n]%*c 读取一行字符,不能使用%s进行读取,表示读到\n为止,%*c的作用就是把\n去掉,否则再次读的时候一直遇到的都是\n。

  2. 所有对%s起作用的控制,都可以用于%[],比如"%*[^\n]%*c"就表示跳过一行,"%-20[^\n]"就表示读取\n前20个字符。

现在再来看文章开头的那行代码就清楚了:"%[^"]\n,"将双引号进行转义为普通字符,%[^"]表示读取到下一个双引号结束,\n表示在输入源中有一个换行符。实际的文件输入源内容为:

<!-- lang: cpp -->
WEBSPORT="80"

文章参考:http://www.cnblogs.com/huzhongzhong/archive/2011/07/15/2107216.html


补充:

  1. 今天看到%n格式控制符:%n读取scanf和printf函数在该格式符之前实际已经读取或输出的字符数量,将该数量存储在函数中对应位置的整形变量内(可以不管它),可以用来进行指针的移动和定位。%n格式控制符的使用不影响scanf和printf函数的返回值,以及后续格式符的使用。
  2. 关于scanf和printf函数的返回值:scanf函数返回的是实际成功匹配和赋值的变量个数,第一个都不匹配时返回0,如果在进行第一个变量转换时到达输入结束则返回EOF;而printf函数返回的是输出的字符数量(不包含字符串结束符)。