fscanf(scanf)|fgets(fgetchar)函数对于空格和回车的不同处理重 fgets和fscanf
#include <stdio.h>
main()
{int i,flag;
char str[80],c;
FILE *fp;
fp=fopen("text","w");
flag=1;
while(flag==1)
{printf("nInput string:n");
gets(str);
fprintf(fp,"%s",str);
printf("nContinue?");
c=getchar();
if((c=='N')||(c=='n'))
flag=0;
getchar(); (接收回车)
}
fclose(fp);
fp=fopen("text","r");
while(fscanf(fp,"%s",str)!=EOF)
{for(i=0;str[i]!=' ';i++)
if((str[i]>='a')&&(str[i]<='z'))
str[i]-=32;
printf("n%sn",str);
}
fclose(fp);
}
运行程序时,如果输入“ABC”回车,再输入“DEF”回车,会显示结果“ABCDEF”,但是如果输入的字符串中包含空格,比如输入I AM A STUDENT,结果会将"I" "AM" "A" "STUDENT"这4个字符串分别输出4行上.
要弄清楚这个问题,首先要对fscanf和fgets这两个文件函数的概念有深入的了解,对于字符串输入而言这两个函数有一个典型的区别是:
fscanf读到空格或者回车时会结束并返回,字符串自动加‘ ’,但是而fgets函数则把空格作为字符接收。
有这样一个例子:
char str[13];
scanf("%s",str);
如果输入以下12个字符How are you?回车
实际上并不是把这12个字符加上 送到数组str中,而只将空格前的“How”送到str中,由于把“How”作为一个字符串处理,因此在其后加 。
当你敲回车时,实际输入了两个字符,回车(13)和换行(10),scanf遇到回车就返回,结果把一个换行符丢在了键盘缓冲里,而getchar偏偏见了换行符就直接返回,所以没有别的办法,在getchar前面先把输入缓冲清掉,即fflush(stdin),&<60; 如果对输入流内的数据需要保留也可在scanf后面加一句getchar把换行符先读掉,具体情况具体处理。
getchar,gets,见了换行符才返回,所以缓冲区没有回车或者换行这样的字符存在了,因此gets后面的getchar能得到正确的字符,实际上SCANF的这种设计是存在一些问题的,所以才导致这些问题的出现。
我们可以将gets改为scanf,即:
#include <stdio.h>
main()
{int i,flag;
char str[80],c;
FILE *fp;
fp=fopen("text","w");
flag=1;
while(flag==1)
{printf("nInput string:n");
scanf("%s",str);
fprintf(fp,"%s",str);
printf("nContinue?");
c=getchar();
if((c=='N')||(c=='n'))
flag=0;
getchar();
}
fclose(fp);
fp=fopen("text","r");
while(fscanf(fp,"%s",str)!=EOF)
{for(i=0;str[i]!=' ';i++)
if((str[i]>='a')&&(str[i]<='z'))
str[i]-=32;
printf("n%sn",str);
}
fclose(fp);
}
这时候我们会发现,即便我们输入n,程序依然会进行下去,原因就是scanf遇到回车符返回了,留有换行符,而第一个getchar遇到换行符返回,读入的数据实际上被第二个getchar所接收了,因此无法结束。
补充一个问题,如果想让"I" "AM" "A" "STUDENT"输出在同一行上程序应该怎么改?
答案就是:fscanf换成fgets(fp, str) 。
再举一例getchar()函数对空格以及回车的处理:
#include<stdio.h>
#define MAX 1000
main()
{int c,i,flag,flag1;
char t[MAX];
i=0;
flag=0;
flag1=1;
printf("nPlease input a hexadecimal number:");
while((c=getchar())!=' '&&i<MAX&&flag1)
{if(c>='0'&&c<='9'||c>='a'&&c<='f'||c>='A'&&c<='F')
{flag=1;
t[i++]=c;
}
else if(flag)
{t[i]=' ';
printf("n decimal number :%dn",htoi(t));
printf("continue? (Y/N):");
c=getchar();
if(c=='N'||c=='n')flag1=0;
else
{flag=0;
i=0;
printf("nPlease input a hexadecimal number:");
}
}
}
}
htoi(s)
char s[];
{int i,n;
n=0;
for(i=0;s[i]!=' ';i++)
{if(s[i]>='0'&&s[i]<='9')n=n*16+s[i]-'0';
if(s[i]>='a'&&s[i]<='f')n=n*16+s[i]-'a'+10;
if(s[i]>='A'&&s[i]<='F')n=n*16+s[i]-'A'+10;
}
return(n);
这道编程表面上看起来没什么,实际有一些玄妙:
第一次运行:Please input a hexadecimal number:
输入:12 回车
decimal number :18
continue? (Y/N):y
Please input a hexadecimal number:
这时如果输入:AC空格 回车
会出现这样的结果:
decimal number:172
continue? (Y/N):
Please input a hexadecimal number:
也就是直接跳过continue? (Y/N):的条件判断了,这不得不让人很是奇怪,怎么会不让我输入“Y”或“N”来判断呢?那么我上面输入:12 回车,怎么就需要判断了呢?
其实这个问题也和上面的类似,输入AC+空格后,getchar函数已经得到了空格,并且这个空格在随后的语句中没有得到处理,不同于AC已经在if语句中被处理t[i++]=c;那么在continue? (Y/N):这个条件判断中,内存中还保留有空格,所以不进行输入(Y/N)判断而直接继续后面的语句。
同样你输入ACZ这样的字符串也不会进行判断,这时内存中存储的是Z,这里以回车和空格举例只是为了说明两者之间的区别。
更多阅读
白葡萄酒和红葡萄酒的区别及功效 白葡萄酒和香槟的区别
1、葡萄酒的营养作用葡萄酒是具有多种营养成分的高级饮料。适度饮用葡萄酒能直接对人体的神经系统产生作用,提高肌肉的张度。除此之外,葡萄酒中含有的多种氨基酸、矿物质和维生素等,能直接被人体吸收。因此葡萄酒能对维持和调节人体的
长方体和正方体的表面积教学反思 体积和容积的意义反思
《长方体和正方体的表面积》是在学生认识并掌握了长方体、正方体特征的基础上教学的,也是学生学习几何知识由平面计算扩展到立体计算的开始,是本单元的重要内容。学生对旧知识已经有了一定的积累,但空间思维还没有真正形成。为了使学生
美国人请客聚会和中国人的不同之处图 中国人为什么喜欢请客
美国人请客的不同之处(图)东京人怎么生活(图)" TARGET="_blank" HREF="http://blog.sina.com.cn/s/blog_5042c53101017f7r.html">实拍:核辐射笼罩下东京人怎么生活在瑞士吃到的古怪食物(图)美国人给孩子多少零用钱(图)文/散粉思考者中国和美
对《芦花荡》中“老头子过于自信和自尊”的质疑 老头子过于自信和自尊
“好坏都别叫出声来”——对《芦花荡》中“老头子过于自信和自尊”的质疑人教版八年级上册第二课《芦花荡》是一篇非常诗意的小说,是孙犁为首的“荷花淀派”小说的代表作之一。文中第六自然段首句“老头子过于自信和自尊”,很多人觉
李白和他的山水诗 山水诗和田园诗的区别
李白和他的山水诗郭 宇(人文学院 B06中文1班学号:060701150)【摘要】李白,盛唐最杰出的诗人,也是我国文学史上继屈原之后又一伟大的浪漫主义诗人,素有“诗仙”之称。他经历坎坷,思想复杂,既是一个天才的诗人,又兼