标题:有关scanf的一些总结,希望对初学C语言的朋友有帮助
只看楼主
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
结帖率:100%
 问题点数:0 回复次数:9 
有关scanf的一些总结,希望对初学C语言的朋友有帮助
这些内容是学C语言的时候在网上或者书看到知识,感觉有用就保留下来了。
不足的地方麻烦补上,错误的地方请指出。

scanf的返回值
    scanf函数返回成功读入的数据项数,读到文件末尾出错时则返回EOF。
    如: scanf("%d %d",&a,&b);
    函数返回值为int型。如果a和b都被成功读入,那么scanf的返回值就是2;
    如果只有a被成功读入,返回值为1;
    如果a和b都未被成功读入,返回值为0;
    如果遇到错误或遇到end of file,返回值为EOF。
    这个经常被作为逻辑判断的条件来使用。
搜索更多相关主题的帖子: C语言 朋友 file 网上 知识 
2016-07-02 14:24
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
得分:0 
先了解一下和scanf有关的一些控制符:

控制字符        说明                          格式说明符  
                       
   %c         一个单一的字符             读入域宽指定的数目个字符组成的字符序列,如果省略宽度则读入单字符。如%c或%1c读入单字符,%2c读入                                        两个字符,以此类推。需要注意的是,输入结束后并不会加上空字节。
   %d         一个十进制整数             读入有符号的十进制整数。

   %i         一个整数             读入有符号整数。会将输入的八进制数,十六进制数自动转换为十进制数。

   %f(%F)     一个浮点数             读入无符号浮点数。(a,e,g和f一样,不再多作介绍,不懂的话上网去查下相关知识)

   %o         一个八进制数             读入无符号八进制整数。

   %s         一个字符串             读入一个以空白字符结束的字符序列,后面会加上空字节。

   %x         一个十六进制数             读入无符号十六进制整数。

   %p         一个指针             读入一个指针值。

   %n         一个等于读取字符数量的整数     不读入任何字符,而是把到该位置已读入的字符数存储到与之对应的int*指向的位置。该转换说明符如果带有*或者带有域宽信息(如:%*n或%3n等),则后果是未定义的。
   %u         一个无符号十进制整数         读入数据,并转换为无符号整型格式。

   %%         一个精度符号            读入% 符号(百分号)。

   %[]         一个字符集             []转换说明符可以通过两种方式产生结果字符集,如果第一个[字符右边没有抑扬符(^),那么处于[]之间的字符就是结果                            字符集,不在其中的可输入字符都作为定界符;如果左边[符号紧靠一个抑扬符(^),那么意义相反,^和]之间的字符是定                            界符,其余可输入字符是结果字符集。

以上这些就是比较容易接触到的控制符。


scanf函数中用到的格式附加字符

1、h         用于输入短整型数据(%hd,%ho,%hx)

2、l         用于输入长整型数据(%ld,%lo,%lx,%lu)以及double型数据(%lf或%le)

3、域宽        指定输入数据所占宽度(列数),域宽应为正整数

4、*        表示本输入项在读入后不赋给相应的变量

还有其它的附加字符,这里不多作介绍,作为一名新人,掌握上面4种就够了,剩下的以后有碰到再去理解就行了。

[此贴子已经被作者于2016-7-2 14:29编辑过]

2016-07-02 14:25
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
得分:0 
回复 2楼 linlulu001
对scanf的一些说明:

(1)   %s 表示读字符串,而 %d 表示读整数。格式串的处理顺序为从左到右,格式说明符逐一与变元表中的变元匹配。为了读取长整数,可以将 l 放在格式说明符的前面;为        了读,取短整数,可以将 h 放在格式说明符的前面。

(2)    默认情况下,a、f、e 和 g 告诉 scanf() 为 float 分配数据。 如果将l放在这些格式说明符的前面,则 scanf() 为 double 分配数据。

(3)    控制串中的空白符使 scanf() 在输入流中跳过一个或多个空白行。空白符可以是空格(space)、制表符(tab)和新行符(newline)。 本质上,控制串中的空白符使 scanf()     在输入流中读,但不保存结果,直到发现非空白字符为止。

(4)    非空白符使 scanf() 在流中读一个匹配的字符并忽略之。例如,"%d,%d" 使 scanf() 先读入一个整数,读入中放弃逗号,然后读另一个整数。如未发现匹配,scanf()     返回。

(5)    scanf() 中用于保存读入值的是指针,即相应的地址。

(6)    在输入流中,数据项由空格、制表符和换行符分割。逗号和分号等不是分隔符,比如以下代码:
    scanf("%d%d",&r,&c);
    输入 10 20  正确。
    输入 10,20  错误。

(7)    百分号(%)与格式符之间的星号(*)表示读指定类型的数据但不保存。例如:
    scanf("%d%*c%d",&x,&y);
    对 10/20 的读入操作中,10 放入变量 x,20 放入 y。

(8)    格式命令可以说明最大域宽。 在百分号(%)与格式码之间的整数用于限制从对应域读入的最大字符数。例如,向str读入不多于 20 个字符时,可以书写成:
    scanf("%20s",str);
    如果输入流的内容多于 20 个字符,则下次 scanf() 从此次停止处开始读入。 若达到最大域宽前已遇到空白符,则对该域的读立即停止;此时,scanf() 跳到下一个域

(9)    虽然空格、制表符和换行符都用做域分割符号,但读单字符操作中却按一般字符处理。例如,输入 "x y"(注意,xy中间有个空格):
    scanf("%c%c%c",&a,&b,&c);
    返回后,x 在变量 a 中,空格在变量 b 中,y 在变量 c 中。
    注意,控制串中的其它字符,包括空格、制表符和换行符,都用于从输入流中匹配并放弃字符,被匹配的字符都放弃。例如,给定输入流 "10t20",调用:
    scanf("%dt%d",&x,&y);
    将把 10 和 20 分别放到 x 和 y 中,t 被放弃,因为 t 在控制串中。
2016-07-02 14:26
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
得分:0 
回复 3楼 linlulu001
使用scanf注意的几点:

(1)     对于字符串数组或字符串指针变量,由于数组名和指针变量名本身就是地址,因此使用scanf()函数时,不需要在它们前面加上"&"操作符。

(2)     可以在格式化字符串中的"%"各格式化规定符之间加入一个整数,表示任何读操作中的最大位数。

(3)     scanf函数中没有类似printf的精度控制。
    如: scanf("%5.2f",&a); 是非法的。不能企图用此语句输入小数为2位的实数。   

(4)    scanf中要求给出变量地址,如给出变量名则会出错
    如 scanf("%d",a);是非法的,应改为scanf("%d",&a);才是合法的。

(5)     在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔,则可用空格,TAB或回车作间隔。
    C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束。

(6)     在输入字符数据(%c)时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。
    例如:
    1、scanf("%c%c%c",&a,&b,&c);
    输入为:d e f
    则把'd'赋予a, ' '(空格)赋予b,'e'赋予c。因为%c 只要求读入一个字符,后面不需要用空格作为两个字符的间隔,因此把' '作为下一个字符送给b。
    只有当输入为:def(字符间无空格) 时,才能把'd'赋于a,'e'赋予b,'f'赋予c。 如果在格式控制中加入空格作为间隔,
    2、scanf("%c %c %c",&a,&b,&c);
    则输入时各数据之间可加空格。

(7)     如果格式控制串中有非格式字符则输入时也要输入该非格式字符。
    1、scanf("%d,%d,%d",&a,&b,&c);
    其中用非格式符“ , ”作间隔符,故输入时应为:5,6,7
    2、scanf("a=%d,b=%d,c=%d",&a,&b,&c);
    则输入应为:a=5,b=6,c=7
    如输入的数据与输出的类型不一致时,虽然编译能够通过,但结果将不正确。
    例如:float a; scanf("%d",&a);

键盘缓冲区残余信息问题

    #include<stdio.h>
    int main(void)
    {
    int a;
    char c;
    while(c!='N')
       {
        canf("%d",&a);
        scanf("%c",&c);
        printf("a=%dc=%c\n",a,c);/*printf("c=%d\n",c);*/
       }
    return 0;
    }

    scanf("%c", &c);这句不能正常接收字符,什么原因呢?用printf("c = %d\n", c);将C用int表示出来,看看scanf()函数赋给C到底是什么,结果是c=10 ,ASCII值为10是        换行即\n。向键盘缓冲区发去一个“回车”(\r),一个“换行"(\n),在这里\r被scanf()函数处理掉了,而\n被scanf()    函数“错误”地赋给了c。(这样理解有助记忆)。
特别说明:\r是回车符,\n是换行符。Unix 系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<回车><换行>”,即“ \r\n”;Mac系统里,每行结尾        是“<回车>”。
解决办法:
    1、可以在两个scanf()函数之后加getch(), getchar(),但是要视具体scanf()语句加那个,这里就不分析,自己去摸索。
    2、可以用scanf("%*[^\n]");来清空缓冲区,这里要注意的是它会保留下“\n”。再加上scanf("%*c");这句,读取保留下来的\n。
    3、也可以使用一些清空输入流的函数来清空缓冲区里的数据,避免这些数据对程序的影响。如:fflush(stdin)
2016-07-02 14:26
低调低调
Rank: 3Rank: 3
来 自:四川省成都市
等 级:论坛游侠
威 望:1
帖 子:66
专家分:103
注 册:2016-6-23
得分:0 
scanf在使用时如果出现内存溢出的问题时可以使用%*来解决;
eg:
int a;
char name;
scanf("%d%*c  %s%*c",&a,&name);
这种使用多用于循环输入时,因为循环输入时往往会造成内存溢出而跳过某一次的输入;

嘿嘿  楼主 我是菜鸟,所以只知道这个,别喷我可以吗?也谢谢你对于scanf使用的这些资料,让我收获很大!
2016-07-02 15:21
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
得分:0 
回复 4楼 linlulu001
对scanf()函数中%[]格式控制符用法进行总结。

此格式控制符的基本格式为:%[scanfset]
scanfset 有两种形式:
一种是以非 “^” 字符开头的 scanset , 表示在读入字符串时将匹配所有在 scanfset 中出现的字符,遇到非scanfset 中的字符时输入就结束;
另外一种形式是以 “^” 字符开头的scanfset ,表示在读入字符串时将匹配所有不在scanfset 中出现的字符,遇到scanfset 中的字符输入就结束。

这两种形式看着是不是很奇怪,实际上说的就是“^”在它左侧有字符和在它右侧有字符所表现的两情况。

为了更快输入,基本上所有的输入都是用中文标点,所以请勿直接复制粘贴测试代码。
测试代码 1 :
#include <stdio.h>
int main()
{
     char str[40] = { 0 } ;     
     scanf( “%[^\n]” , str ) ; //遇到回车键时字符串输入结束,所以加上“*”就相当于fflush(stdin),缺点是它保留回车,优点在于移植性更广。
     printf( “%s\n“ , str ) ;
     return 0 ;
}
输入 :hhhh   &&&ni
Vc6.0的输出结果:hhhh   &&&ni

测试代码 2 :
#include <stdio.h>
int main()
{
    char str[40]={0};
    scanf("%[^abcdefg]",str);//除了abcdefg,其它字符均能读取。
    printf("%s\n",str);
    return 0;
}
输入 :hijk        hi jg     //注意,这里有输入了两次tab和一次空格
Vc6.0的输出结果:hijk        hi j

“-”字符的使用。当“-”出现在scanfset中且两边都有字符时,大多数编译器都如下表述:“-”表示匹配从其左边的字符到右边字符之间所有的字符(按ASCII码排序)。如a-z表示a到z的所有字符,又如0-9表示0到9这十个数字。所以,当scanfset为0-9时表示只匹配数字串,当scanfset为A-Za-z时表示只匹配字符(包括大小写),当scanfset为^0-9时不匹配所有数字。注意,“-”的字符只有在其左右两边都有有效字符时才有这个作用,否则被认为是普通字符,如“ 0-4-6-9”匹配的字符为{0,1,2 ,3,,4, -, 6,7,8,9},这样也为输入“-”字符提供了方法。
注意:并不是所有编译器都支持,所以知道就好,以便看到他人写的代码时知道这是做什么用的。
测试代码 3 :
#include <stdio.h>
int main()
{
    char str[40]={0};
    scanf("%[a-c-2-7-A-Z]",str);//遇到不是方括号中的字符输入就结束,注意字符 “-”
    printf("%s\n",str);
    return 0;
}
输入:b35U-
Vc6.0输出结果:b35U-
输入:aA1abcBBZ
Vc6.0输出结果:aA
      
%[ni hao ma]表示只能读取[]里定的字符,遇到不是[]中的字符读取就结束。   
测试代码 4 :
#include <stdio.h>
int main()
{
      char str[40] = { 0 } ;
      scanf( “%[ni hao ma]” , str ) ;//遇到不是方括号中的字符读取结束
      printf( “%s\n“ , str ) ;
      return 0 ;
}
输入:hao
Vc6.0输出结果: hao
输入:nh akma
Vc6.0输出结果: nh a
2016-08-09 18:07
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1728
专家分:3216
注 册:2015-12-2
得分:0 
版主真博学,收藏了。
2016-08-09 19:29
zq196520
Rank: 1
等 级:新手上路
帖 子:4
专家分:0
注 册:2016-8-9
得分:0 
谢谢老师,第一次知道这个论坛,以后常来学习。
2016-08-09 22:16
苣柒荼
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2016-8-10
得分:0 
回复 2楼 linlulu001
%p 是所指 指针值 还是 指针所指地址。
2016-08-13 12:11



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-466562-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020795 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved