您的位置:首页 > 其它

转载加自己的见解getch(),getche(),getchar(),gets(),scanf()的区别,综合很多博客的文章。

2012-10-21 14:26 417 查看
getch(),getche(),getchar(),gets(),scanf()的区别,综合很多博客的文章。

getch()和getchar()

getchar()是C的标准库函数,包含在头文件<stdio.h>中,而getch()和getche()需要的头文件是<conio.h>。conio.h不是C标准库中的头文件。conio是Console Input/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作

getchar

This is a standard function that gets a character from the stdin.

getch

This is a nonstandard function that gets a character from keyboard, does not echo to screen.

getche

This is a nonstandard function that gets a character from the keyboard, echoes to screen.

Use getchar if you want it to work on all compilers. Use getch or getche on a system that supports it when you want keyboard input without pressing [Enter].And note that the return value of all three is int! You need this to properly check for EOF.

int getch( void ); Get a character from the console without echo

int getchar ( void ); Get character from stdin, Returns the next character from the standard input (stdin).It is equivalent to getc with stdin as its argument

可以看到,两个函数都没有参数,都是读入一个字符,返回值都是int型。但是注意getch()是从console读取,而getchar()是从stdin,一般是指键盘。要试验两者的区别,你可以写一个getch()看看不从键盘输入,比如直接用鼠标复制一段字符粘贴到console上,你会看到getch()会立即返回,但getchar一直等待,直到遇到 ENTER 键

getch()读到一个字符就返回,不管是什么字符,所以,在TC时代经常被放在程序最后面,达到“按任意键退出”的效果。而getchar()直到遇见ENTER 键才返回,返回值是第一个字符,但是后面的字符也不会被丢弃,而是保存在一个缓冲区内。



[cpp]
view plaincopyprint?

#include <stdio.h>
#include <conio.h>
int main()
{
int ch, cha;
ch = getch();
cha = getchar();
printf("ch=%d, cha=%d/n",ch,cha);
getch();
return 0;
}

[cpp]
view plaincopyprint?

#include<stdio.h>
#include<conio.h>
void main()
{
char ch;
for(int i=0;i<5;i++)
{
ch=getch();
printf("%c",ch);
}
}

#include<stdio.h>
#include<conio.h>
void main()
{
char ch;
for(int i=0;i<5;i++)
{
ch=getch();
printf("%c",ch);
}
}


  首先这是个连续5次的循环来实现5次停顿,等待我们输入,我们编译并运行这个程序,假设我们分别输入abcde,屏幕上显示的结果是abcde,这个abcde并不是在ch=getch();中输出的,我们把printf("%c",ch);这行语句去掉,就会发现我们按5次任意键程序就结束了,但屏幕上什么都没有显示。

然后我们在把代码中的getch()换成getche()看看有什么不同,我们还是分别输入abcde,这时屏幕上显示的结果是aabbccddee,我们把printf("%c",ch);这行语句再去掉看看,显示的结果就是abcde了,说明程序在执行ch=getche();这条语句的时候就把我们输入的键返回显示在屏幕上,有无回显就是getch()和getche()的唯一区别

[cpp]
view plaincopyprint?

void main()
{
char c, ch;
c=getch(); /*从键盘上读入一个字符不回显送给字符变量c*/
putchar(c); /*输出该字符*/
ch=getche(); /*从键盘上带回显的读入一个字符送给字符变量ch*/
putchar(ch);
printf("/n/n");
}

[cpp]
view plaincopyprint?

#include<stdio.h>
#include<conio.h>
void main()
{
char ch='*';
while(ch=='*')
{
printf("/n按 * 继续循环,按其他键退出!");
ch=getch();
}
printf("/n退出程序!");
}

#include<stdio.h>
#include<conio.h>
void main()
{
char ch='*';
while(ch=='*')
{
printf("/n按 * 继续循环,按其他键退出!");
ch=getch();
}
printf("/n退出程序!");
}


  我们可以在这个循环体中添加我们想要的功能,程序中按*继续循环,其他任意键退出,而且利用getch()无回显的特性,我们不管按什么,都不会在屏幕上留下痕迹,使我们的界面达到美观效果。

getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了。而getch()和getche()是conio.h中的库函数,它的作用是从键盘接收字符。getchar带有显示。

与前面两个函数的区别在于: getchar()函数等待输入直到按回车才结束(前提是缓冲区没有数据),回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。



[cpp]
view plaincopyprint?

#include<stdio.h>
#include<conio.h>
void main()
{
char c;
c=getchar(); /*从键盘读入字符直到回车结束*/
//getchar()在这里它只返回你输入字符串的第一个字符,并把返回值赋值给c

putchar(c); /*显示输入的第一个字符*/
printf("/n/n");
}

[cpp]
view plaincopyprint?

#include<stdio.h>
#include<conio.h>
void main()
{
char c;
while ((c=getchar())!='/n')    /*每个getchar()依次读入一个字符*/
printf("%c",c);        /*按照原样输出*/
printf("/n/n");
}

#include<stdio.h>
#include<conio.h>
void main()
{
char c;
while ((c=getchar())!='/n')    /*每个getchar()依次读入一个字符*/
printf("%c",c);        /*按照原样输出*/
printf("/n/n");
}


自己写了一个程序测试了一下


#include<stdio.h>

#include<conio.h>

void main()

{ int i=0;

char c,d;

while ((c=getchar())!='y')

{i++; /*每个getchar()依次读入一个字符*/

printf("%c,%d",c,i);

} /*按照原样输出*/

printf("\n");

d=getchar();

printf("%c,%c",c,d);

getch();

}

输入 abcyqe

输出 a,1b,2c,3

y,q

  程序运行时,首先停下来,等你输入一串字符串,输入完毕后,它把你输入的整个字符串都输出来了,咦,你不是说getchar()只返回第一个字符么,这里怎么?

因为我们输入的字符串并不是取了第一个字符就把剩下的字符串丢掉了,它还在我们的内存中,就好比,开闸放水,我们把水放到闸里去以后,开一次闸就放掉一点,开一次就放掉一点,直到放光了为止,这里开闸动作就相当于调用一次getchar()。我们输入的字符串也是这么一回事,首先我们输入的字符串是放在内存的缓冲区中的,我们调用一次getchar()就把缓冲区中里出口最近的一个字符输出,也就是最前面的一个字符输出,输出后,就把它释放掉了,但后面还有字符串,所以我们就用循环把最前面的一个字符一个个的在内存中释放掉,直到不满足循环条件退出为止。

例子中循环条件里的'/n'实际上就是你输入字符串后的回车符,所以意思就是说,直到遇到回车符才结束循环,而getchar()函数就是等待输入(或缓冲区中的数据)直到按回车才结束,所以实现了整个字符串的输出。当然,我们也可以把循环条件改一下,比如while ((c=getchar())!='a'),什么意思呢,意思就是遇到字符'a'就停止循环,当然意思是如果你输入“12345a213123/n”那么只会输出到a,结果是12345a。

再次注意:用getchar()它是从“流”中间去读取,所以第一个getchar()接受的是刚刚中断的流队列中即将出列的第一个字符(不限于回车符,上面举过例子了),如果流队列不为空,执行getchar()就继续放水,直到把回车符也放空为止,空了之后再在执行getchar()就停下等待你的输入了;我们用getch()为什么每次都是等待用户的输入呢?因为getch()是从键盘接收,即时的接收,并不是从stdin流中去读取数据。

补充:按键盘上的回车产生了2个字符:回车符('/r')和换行符('/n')。回车符'/r'(CR:carriage return:倒车)使光标回到这行的首部,换行符('/n')(new line)然后再换行。

所以当输入字符'w',并按下回车键以后。首先得到回车符。那个getchar函数结束了。 但是还存在一个换行符。所以如果用getchar()来做判断的时候。最好再写一次getchar()清除缓冲区的'/n'.

如何清空输入缓冲区的内容

如果我想让getchar()每次都能够等待用户输入的话就要清空缓冲区,下面就介绍方法(不同平台)

C标准规定 fflush()函数是用来刷新输出(stdout)缓存的。对于输入(stdin),它是没有定义的。但是有些编译器也定义了 fflush( stdin )的实现,比如微软的VC。其它编译器是否也定义了 fflush( stdin )的实现应当查找它的手册。GCC编译器没有定义它的实现,所以不能使用 fflush( stdin )来刷新输入缓存。

对于没有定义 fflush( stdin )的编译器,可以使用 fgets()函数来代替它(比用 getchar()、scanf()等函数通用性好)。可以这样忽略输入流中留下的回车等其它输入,从而使下一次的输入总保持一个“干净”的状态。(这个是任何平台下都可以的)



[cpp]
view plaincopyprint?

// ...
char sbuf[1024];
// ...
fgets( sbuf, 1024, stdin );
// ...
//在windows 的vc下面就可以这样了:
for(int i=0;i<10;++i)
{
char ch=getchar();
fflush(stdin); //每次都会有等待状态了

}

[cpp]
view plaincopyprint?

#include <stdio.h>
int main()
{
char ch1, ch2;
scanf("%c", &ch1);
scanf("%c", &ch2);
printf("%d  %d/n", ch1, ch2);
return 0;
}

#include <stdio.h>
int main()
{
char ch1, ch2;
scanf("%c", &ch1);
scanf("%c", &ch2);
printf("%d  %d/n", ch1, ch2);
return 0;
}


或者是:

[cpp]
view plaincopyprint?

#include <stdio.h>
int main()
{
char ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d/n", ch1, ch2);
return 0;
}

[cpp]
view plaincopyprint?

#include <stdio.h>
int main()
{
char str1[20], str2[20];
scanf("%s",str1);
printf("%s/n",str1);
scanf("%s",str2);
printf("%s/n",str2);
return 0;
}

#include <stdio.h>
int main()
{
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(),下面我们看一下这个函数的应用:

[cpp]
view plaincopyprint?

#include <stdio.h>
int main()
{
char str1[20], str2[20];
gets(str1);
printf("%s/n",str1);
gets(str2);
printf("%s/n",str2);
return 0;
}

[cpp]
view plaincopyprint?

#include <stdio.h>
#include <conio.h>
//#include <iostream>
//using namespace std;
int main()
{
char tmp[20];
for ( int i=0 ; i<20; i++ )
{
tmp[i] = getch() ;
//tmp[i]=getchar();
// putchar ( '*' ) ;
printf ( "%d=[%c]/n",i,tmp [i] ) ;
//cout<<i<<"=["<<tmp [i]<<"]"<<endl;

if ( tmp[i] == '/r' )
{
tmp [i] = '/0' ;
break ;
}
}
}

#include <stdio.h>
#include <conio.h>
//#include <iostream>
//using namespace std;
int main()
{
char tmp[20];
for ( int i=0 ; i<20; i++ )
{
tmp[i] = getch() ;
//tmp[i]=getchar();
// putchar ( '*' ) ;
printf ( "%d=[%c]/n",i,tmp [i] ) ;
//cout<<i<<"=["<<tmp [i]<<"]"<<endl;
if ( tmp[i] == '/r' )
{
tmp [i] = '/0' ;
break ;
}
}
}


上面这段代码,实现一个最多为20位的密码输入功能,既然是密码我们当然不希望他显示原字符,像linux用户验证那样什么也不显示,但有的时候为了直观一点,我们可以加入putchar(‘*’)语句,就像QQ密码在你每输入一个字符时,他就回显一个“*”号。

实例中的for循环了20次,但我们在输入的时候可以输入30,50个字符,对系统来说反正是放入缓冲区,放多少都是放,只不过在读取的时候只循环了20次,所以只能多20个字符,剩下的就被抛弃了。但是如果我们只想输入10个字符,那么你就得摁剩下的10个回车键,因为getchar()输入的字符被存放在键盘缓冲区中.直到用户输入足够的次数(20次)按回车后才返回。因为在20次前,回车也是当做一个普通字符存入缓存区的。

也就是说,如果你的按键超过20次getch()自动结束,而getchar()没有任何提示,但在下次调用时只取前20个有效字符。如果你的按键不足20次,getch()遇到回车就退出,但是getchar()你必须按足20次后遇回车才结束,

细心的朋友会发现,调用getchar()时真正输入的字符只有19个,因为系统默认把第一个字符设为‘/0’??这个我没发现!!

输入123回车

用getch时候输出为:

0=[0]

1=[1]

2=[2]

3=[3]

]=[

请按任意键继续. . .

关于]=[这一行,回车转为了/r/n按照转义字符处理了!用cout一样的结果!

getchar时候输出为:

123

0=[1]

1=[2]

2=[3]

3=[

]

456

4=[4]

5=[5]

6=[6]

7=[

]

关于3=[

] 看出直接转为了回车输出!

并没有结束,等到20次循环结束后才退出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: