C的输入输出特点
----------------------------------------------------
| 问题描述一:(分析scanf()和getchar()读取字符)
----------------------------------------------------
程序1:
char ch1, ch2;
scanf("%c", &ch1);
scanf("%c", &ch2);
printf("%d %d\n", ch1, ch2);
return 0;
char ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d\n", ch1, ch2);
return 0;
【分析】:
----------------------------------------------------
| 问题描述二:(分析scanf()和gets()读取字符串)
----------------------------------------------------
首先我们看一下scanf()读取字符串的问题:
程序2:
char str1[20], str2[20];
scanf("%s",str1);
printf("%s\n",str1);
scanf("%s",str2);
printf("%s\n",str2);
return 0;
测试一输入:
Hello world!
输出:
Hello
world!
【分析】到此程序执行完毕,不会执行第二次的读取操作!这个问题的原因跟问题一类似,第一次输入Hello world!后,字符串Hello world!都会被读到输入缓冲区中,而scanf()函数取数据是遇到回车、空格、TAB就会停止,也就是第一个scanf()会取出"Hello",而"world!"还在缓冲区中,这样第二个scanf会直接取出这些数据,而不会等待从终端输入。
测试二:
Hello[Enter]
Hello[输出]
world[Enter]
world[输出]
【分析】程序执行了两次从键盘读入字符串,说明第一次输入结束时的回车符被丢弃!即:scanf()读取字符串会舍弃最后的回车符!
我们再看一下gets()读取字符串的情况:
用scanf来读取一个字符串时,字符串中是不可以出现空格的,一旦出现空格,后面的数据就会舍弃残留在缓冲区中。其实有另外一个函数是可以接受空格的,那就是gets(),下面我们看一下这个函数的应用,我们把程序2改动一下:
程序3:
#include <stdio.h>
int main()
{
char str1[20], str2[20];
gets(str1);
printf("%s\n",str1);
gets(str2);
printf("%s\n",str2);
return 0;
}
测试:
Hello world! [输入]
Hello world! [输出]
12345 [输入]
12345 [输出]
【分析】显然与上一个程序的执行情况不同,这次程序执行了两次从键盘的读入,而且第一个字符串取了Hello world! 接受了空格符,而没有像上一个程序那样分成了两个字符串!所以如果要读入一个带空格符的字符串时因该用gets(), 而不宜用scanf()!
--------------------------------------------------------
| 问题描述三:(getchar()暂停程序,查看程序执行结果)|
--------------------------------------------------------
【分析】原因跟上面例子讲的一样,是因为输入缓冲区中还有数据,所以getchar()会成果读到数据,所以就跳出了!
------------------
|
------------------
第一:要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
方法2:自己取出缓冲区里的残留数据。
(说实话这个语句我也没看懂,呵呵!为什么格式控制是这样的!希望高手指点一下!)
|----------- 文章为作者原创,转载请注明出处或作者! ------------ |
getch,getche和getchar区别
你也许会问,为什么我们 在C++中就没有在程序的末尾加上getch(),解释是,软件总是不断更新的,不好的地方当然要进行改正,getch()加在程序末尾,它又不赋值给任 何变量,所以它在这个地方完全是垃圾代码,与程序无关。C++中考虑到这一点,于是在每次程序运行完了并不退出,而是自动把屏幕停下来,并显示 “press any key...”叫你按任意键退出,这就好比C++在它的环境中运行程序,在程序的末尾自动加上了一行getch();语句,并且在这行语句前还添加了一行 输出语句cout<<"press any key...";来提示你程序结束了,按任意键继续。实际上我们编译好的程序在程序结束了本身是不会停下来的,我们可以在编译产生的Debug目录中找到 这个编译好的应用程序(扩展名exe),在文件夹中双击运行它,你会发现屏幕闪了一下MS-DOS窗口就关闭了,因为程序运行完就自动退出了,回到了 windows环境,当然,如果我们在DOS环境中运行这个程序,我们就可以直接在看到DOS屏幕上看到程序运行结果,因为程序运行完后并不清屏。
还有一个语句,和getch()很相似,getche(),它也需要引入头文件conio.h,那它们之间的区别又在哪里呢?不同之处就在于getch()无返回显示,getche()有返回显示。怎么说呢?我举个例子你就明白了。
--------------------------------------
#include <stdio.h>
#include <conio.h>
void main()
{
}
--------------------------------------
a
a
b
b
c
c请按任意键继续. . .
这里“请按任意键继续. . .”就跟c显示在了同一行,可知c后的[Enter]并没有输出,然后就退出了。为了验证这个,我们可以在第一行先输入一个[Enter],可以看到光标 到了第3行,然后我们再输入abcde,回车之后,只输出了abcd,因为这4个,加上前一个[Enter],5个字符已满。)
然后我们在把代码中的getch()换成getche()看看有什么不同,我们还是分别输入abcde,这时屏幕上显示的结果是 aabbccddee,我们把printf("%c",ch);这行语句再去掉看看,显示的结果就是abcde了,说明程序在执行 ch=getche();这条语句的时候就把我们输入的键返回显示在屏幕上,有无回显就是它们的唯一区别。
好了,我们再来说说为什么不用C++函数库的原因。你可以试试把这个程序改成C++的形式(原来程序很乱,我依然用C写的):
我们可以在这个循环体中 添加我们想要的功能,程序中按*继续循环,其他任意键退出,而且利用getch()无回显的特性,我们不管按什么,都不会在屏幕上留下痕迹,使我们的界面 达到美观效果,如果还有更好的办法实现这个功能,我可能就不会在这里提这么多了。如果你真的有更好的办法,请一定告诉我,谢谢!
//例一:这个例子是为了说明getch()和getche()的区别 #include #include
//这里讲个小故事:因为这个代码是在别人网页上的,别人用的C环境,可能是不需要conio.h头文件就可以用getch();(我就不清楚了),也可能是忘了写,网页上的源代码没有#include这一行,
void main()
{
}
--------------------------------------
//例二:这个例子是演示交互输入的过程中完成暂停功能
#include <stdio.h>
#include <conio.h>
void main()
{
}
--------------------------------------
//例三:getchar()函数也是从键盘上读入一个字符,并带回显。它与前面两个函数的区别在于:
#include <stdio.h>
void main()
{
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiazhen198239/archive/2007/11/08/1873473.aspx
getch、getche这两个函数不是C标准库中的函数:
int getch(void) //从标准输入读入一个字符,当你用键盘输入的时候,屏幕不显示你所输入的字符。也就是,不带回显。
int getche(void) //从标准输入读入一个字符,键盘输入的时候,屏幕显示所输入的字符。带回显。
这两个函数包含在头文件conio.h中,需要记住的是conio.h不是C标准库中的头文件。Micorsoft 和 Borland的 C编译器提供了conio.h,用来创建控制台文本用户界面。一般在Windows系统下安装了VS、VC等,就可以包含conio.h头文件。但是一般在Unix、Linux系统中,/usr/include/中都没有这个头文件。
getch和getche在等待用户从键盘输入的时候,用户按下一个键后,不需要按回车,程序自动往下执行。在Linux中,终端输入在缺省情况下是被“一锅端”的,也就是说整行输入是被一起处理的。通常,这是一种人们所希望的方便的办法,但它也意味着在读入数据时必须按一下回车键表示输入行结束后才能得到输入的数据。在游戏中,很多都提供了“老板键”,它的实现,就是利用了这两个函数。
其次,除了getch和getche,其他的都是C标准库中的头文件,包含在头文件stdio.h中。
int fgetc ( FILE * stream ); //从流stream中读一个字符。可以将标准输入stdin作为它的实参,这时候从标准输入读取一个字符。 int getc(FILE * stream); //和fgetc等效,由fgetc通过宏实现。 int getchar ( void ); //从标准输入stdin读入一个字符,程序等待你输入的时候,你可以输入多个字符,回车后程序继续执行。 //但getchar只读入一个字符 说明:getc、getchar都是通过宏定义借助fgetc实现。如getchar的实现为,#define getchar() fgetc(stdin)。main()
{
}
建议不要用getch和getche,因为它们不是C标准库中的函数。用它们写出的程序可移植性差,不同的编译器不保证可以包含conio.h。建议用fgets函数彻底替代gets函数。
另外,绝大多数的这些get函数,都有对应的put版本。
int fputc ( int character, FILE * stream );
int putc ( int character, FILE * stream );
int putchar ( int character ); //通过宏定义实现:#define putchar(c) fputc(c, stdout)
int fputs ( const char * str, FILE * stream );
int puts ( const char * str );
说明:两者之间无宏定义实现关系。puts(const char *str)近似等效于fputs(cosnt char *str, stdout),不同点是前者还输出一个'\n'
最后,关于EOF
EOF是在stdio.h文件中定义的符号常量,值为-1。如,
fputc函数返回一个值:如果输出成功则返回值就是输出的字符;如果输出失败,则返回一个EOF。
fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标记EOF。如果想从一个磁盘文件顺序读入字符并在屏幕上显示,可以:
ch
}
注意,EOF不是可输出字符,因此不能在屏幕上显示。由于ASCII码不可能出现-1,因此EOF定义为-1是合适的。当读入的字符值等于-1(即EOF)时,表示读入的已不是正常的字符,而是文件结束符。但以上只适用于读取文本文件的情况。现在ANSI C 已经允许用缓冲文件系统处理二进制文件,而读入某一个字节中的二进制数据的值有可能是-1,而这又恰好是EOF的值。这就出现了需要读入有用数据,却处理为“文件结束”。feof(fp) 用来测试fp所指向的文件当前状态是否是“文件结束”。如果想顺序读入一个二进制文件数据,可以:
while(!feof(fp)){
}