您的位置:首页 > 其它

fscanf(scanf)|fgets(fgetchar)函数对于空格和回车的不同处理

2011-01-10 19:45 691 查看
有一道编程如下:

#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]!='/0';i++)

if((str[i]>='a')&&(str[i]<='z'))

str[i]-=32;

printf("/n%s/n",str);

}

fclose(fp);

}

运行程序时,如果输入“abc”回车,再输入“def”回车,会显示结果“abcdef”,但是如果输入的字符串中包含空格,比如输入i am a student,结果会将"i" "am" "a" "student"这4个字符串分别输出4行上.

要弄清楚这个问题,首先要对fscanf和fgets这两个文件函数的概念有深入的了解,对于字符串输入而言这两个函数有一个典型的区别是:

fscanf读到空格或者回车时会结束并返回,字符串自动加‘/0’,但是而fgets函数则把空格作为字符接收。

有这样一个例子:

char str[13];

scanf("%s",str);

如果输入以下12个字符how are you?回车

实际上并不是把这12个字符加上/0送到数组str中,而只将空格前的“how”送到str中,由于把“how”作为一个字符串处理,因此在其后加/0。

当你敲回车时,实际输入了两个字符,回车(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]!='/0';i++)

if((str[i]>='a')&&(str[i]<='z'))

str[i]-=32;

printf("/n%s/n",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())!='/0'&&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]='/0';

printf("/n decimal number :%d/n",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]!='/0';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,这里以回车和空格举例只是为了说明两者之间的区别。
链接自:http://www.goumeijie.com/go/so/?hm19821008$_$3a5925f353812dc80a46e0c2.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: