C语言 gets()和scanf()函数的区别

scanf()、getch()、getchar()、getc()、gets()、cin、cin.get()、cin.getline()、getline()

(2011-11-08 20:18:05)

 

目录

一、scanf() 1

二、清除一个流... 4

三、getch() 5

四、getchar() 6

五、getc() 6

六、gets(). 6

七、ungetc() 7

八、cin. 8

九、cin.get() 9

十、cin.getline() 10

十一、getline() 12

  

一、scanf()

头文件<stdio.h>

例子:

int a;

scanf(“%d”,&a); //输入取地址,即变量地址

printf(“%d ”,a);      //输出指定对象,即变量名

scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。

   遇空格、回车跳格键。

   遇宽度结束。

遇非法输入。

----------个人理解:scanf()函数工作的机理就是:在输入流中取所需要的数据,在输入流stdin中个数据是按照空格(含一个或多个)隔开的,如果输入流中已经取完了数据,则要求再次往输入流中输入数据。

注意的是:只有字符char在输入流中的获取会承认空格或回车中的换行符为所要取的值,别的如字符串或int类型均不认为空格或回车中的换行符为其值。

看下面:

#include "stdafx.h"

#include <stdio.h>

#include<windows.h>

int main()

{

char str[80];

char str1[80];

char str2[80];

scanf("%s",&str); //不妨输入 I love you!

printf("%s ",str);

Sleep(3000);

printf("over! ");

scanf("%s",str1);

scanf("%s",str2);

printf("%s ",str1);

printf("%s ",str2);

return 0;

}

输入I love you!便回车,结果系统直接运行到结束,不会再提示你输入 str1,str2,因为scanf()函数实质就是从标准输入stdin中取数据,而是不从键盘取数据,只有标准输入区中无数据才会提示从键盘输入数据(其实质为向标准输入区中输入数据)。

对于scanf("%s",&str);这句由于刚开始标准输入缓冲区中无数据,故需要提示从键盘中输入数据,但你输入的为”I love you!”,实际上在标准输入缓冲中按照输入的”I love you!”进行暂时存储,标准输入缓冲区中数据以空格为间隔,故此时str实际对应的为”I”。

         对于scanf("%s",str1);  scanf("%s",str2);这两句,由于scanf()从标准输入缓冲区中取值,现在标准输入缓冲区中还剩余” love you!”,注意love前有空格,但字符数组或字符串不承认空格,故str1对应love,str2对应you!。

如下面程序:

#include "stdafx.h"

#include <stdio.h>

#include<windows.h>

int main()

{

char str[80];

char str1[80];

char str2[80];

int a;

int b;

scanf("%s",&str);

printf("%s ",str);

Sleep(3000);

printf("over! ");

//scanf("%s",str2);

scanf("%d",&a);

printf("%d ",a);

scanf("%d",&b);

printf("%d ",b);

 return 0;

}

若输入”fhdsia  12    34”,说明一下12前以及34前有很多空格,这样程序会直接运行结束,中途不会再提示输入数据。

开始标准输入缓冲区中没有数据,故scanf("%s",&str);系统会提示输入数据,若输入为”fhdsia  12    34”,则str对应”fhdsia”。

对应scanf("%d",&a);

printf("%d ",a);

scanf("%d",&b);

由于现在标准输入中已经有数据,故不会再提示输入数据,int类型不承认空格,故a对应12,b对应34。

若输入”fhdsia  12  “,这样系统还会提示你再输入一次数据,对应语句为scanf("%d",&b);

#include "stdafx.h"

#include <stdio.h>

#include<windows.h>

int main()

{

char str[80];

char str1[80];

char str2[80];

char a;

char b;

scanf("%s",&str);

printf("%s ",str);

Sleep(3000);

printf("over! ");

//scanf("%s",str2);

scanf("%c",&a);

printf("%c ",a);

scanf("%c",&b);

printf("%c ",b);

 return 0;

}

若输入”afdsf  ”然后回车,注意afsdf后面空格大于2个,则由于char会把标准输入区的空格或回车当做输入值,故输入”afdsf  ”(2个或2个以上的空格)后,程序直接运行结束,

scanf("%c",&a);

printf("%c ",a);

scanf("%c",&b);

a对应标准输入区中的空格,同理b也对应空格。

若输入”afdsf”后直接回车,这样,str对应afdsf,a对应回车(个人认为其为空格),这样还会提示继续输入数据用来对应b。

二、清除一个流

函数名: fflush

  功 能: 清除一个流

fflush(stdin);头文件<stdlib.h>

 C和C++的标准里从来没有定义过 fflush(stdin)。可用getchar();(但并不等价,因为getchar()只相当于从标准输入缓冲区中去读取按顺序对应的一个字符(包含空格或回车),就这样的功能。)代替。

某些编译器(如VC6)支持用 fflush(stdin) 来清空输入缓冲,但是并非所有 编译器都要支持这个功能(linux 下的 gcc 就不支持),因为标准中根本没有定 义 fflush(stdin)。

scanf("%c",&c);我们每击打一下"Enter"键,向键盘缓冲区发去一个“回车”( ),一个“换行"( ),在这里 被scanf()函数处理掉了(姑且这么认为吧^_^),而 被scanf()函数“错误”地赋给了c.

#include "stdafx.h"

#include <stdio.h>

int main()

{

char string[50];

scanf("%[^ ]",string);

printf("%s ",string);

return 0;

}

输入”adasf  fsd  as”, 则输出就是输入。

------ %[] 扫描字符集合,直到回车换行符号为结束。

使用scanf函数进行输入,必须指定输入的数据的类型和格式,不仅繁琐复杂,而且很容易出错.C++保留scanf只是为了和C兼容,以便过去用C语言写的程序可以在C++的环境下运行。C++的编程人员都愿意使用cin进行输入,很少使用scanf。

三、getch()

在windows平台下从控制台无回显地取一个字符,在linux下是有回显的。

-------只能输入一个字符。

#include "stdafx.h"

#include <stdio.h>

#include <conio.h> //window 平台

#include <stdlib.h>

int main(void)

{

char ch;

printf("Input a character:");

ch = getch();

printf(" You input a %c ", ch);

int a;

a = getch();

printf(" You input a %d ", a);

system("pause");

return 0;

}

---输入’d’后直接运行得到You input a d。然后让你继续输入a对应的值,但你只能输入一个字符,比如输入’1’,则输出的结果显示为49,即1的ASCII码。

getch()是非缓冲输入函数,就是不能用getch()来接受缓冲区已存在的字符。就是指用到getch(),每次必须再键盘上输入,不会读取stdin中的数值。

这个函数可以让用户按下任意键而不需要回车就可以接受到用户的输入。可以用来作为“press any key to continue”的实现。

四、getchar()

头文件<stdio.h>

功能

  从stdin流中读字符。

getchar()只相当于从标准输入缓冲区中去读取按顺序对应的一个字符(包含空格或回车),就这样的功能。

----注意针对的是字符。

int a;a=getchar();printf("%d ",a);输入12,则输出为49,即1对应的ASCII码。若为%c,则输出为1,这个1为字符1。

五、getc()

函数名: getc

  功 能: 从流中取字符

 int getc(FILE *stream);//read the next character from stream and return it as an unsigned char cast to a int ,or EOF on end of file or error.

在C语言中,用函数getc(fgetc)从文件读取字符。getc、fgetc用法相同。

----注意针对的是字符。

六、gets()

以回车换行符为结束标志。

函数:gets(字符指针)

头文件:string.h(c中),c++不需包含此头文件

原型:char *gets( char *buffer );

功能:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。

返回值:读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferrorfeof函数检查是发生错误还是遇到EOF。

注意:本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值,为了避免这种情况,我们可以用gets_s()来替换gets()。这个事实导致gets函数只适用于玩具程序。

gets()函数用来从标准输入设备(键盘)读取字符串直到换行符结束,但换行符会被丢弃,然后在末尾添加''字符。其调用格式为:

  gets(s);

  其中s为字符串变量(字符串数组名或字符串指针)。

  gets(s)函数与scanf("%s:",&s)相似,但不完全相同,使用scanf("%s",&s);函数输入字符串时存在一个问题,就是如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理,但gets()函数将接收输入的整个字符串直到遇到换行为止。

  说明:

  gets(s);函数中的变量s为一字符串。如果为单个字符,编译连接不会有错误,但运行后会出现”Null pointer asignment"的错误。

#include<iostream>

using namespace std;

int main()

{

char str[100];

gets(str);

cout<<str<<endl;

return 0;

}

七、ungetc()

 把一个字符退回到输入流中

用 法

  int ungetc(char c, FILE *stream);

输入参数

  c 要写入的字符,stream 文件流指针

输出参数

  字符c - 操作成功,EOF - 操作失败

#include "stdafx.h"

#include <stdio.h>

#include <ctype.h>

int main()

{

int ch;

printf( "Enter an integer: " );

ch = getchar() ;

printf("%d ",ch);

ungetc( ch, stdin );

int s;

s=getchar();

printf("%d ",s);

return 0;

}

输入12,则会运行结束,不再要求输入数据,输出为49(换行)49

八、cin

C++编程语言互换流中的标准输入流,需要iostream.h支持,及开始的时候,要有#include <iostream.h>读为 "see in",拼音"si yin",

  cin代表标准输入设备,使用提取运算符 ">>" 从设备键盘取得数据,送到输入流对象cin中,然后送到内存。使用cin可以获得多个从键盘的输入值,其具体使用格式如下:

  cin >> 表达式1 >>表达式2 ... >> 表达式n;

-----------cin输入会根据空格、回车、以及要输入的数据类型进行对应数据分配。但你若某一个输入的数据不对应,则下面的要输入的就会分配给错误的信息,不会再提示你输入数据。

如下:

#include "stdafx.h"

#include<iostream.h>

int main()

{

int i,j;

char s;

cin>>i;

cout<<i<<endl;

cin>>j;

cout<<j<<endl;

cin>>s;

cout<<s<<endl;

return 0;

}

--该程序就是让先输入两个int,再输入一个人char,你可以一个一个输入,也可以一起输入,比如输入 12 22 a。也可以先输入 12 22,会再提示输入s对应的值,但如果你输入先输入 a或a 12 b或 a 12等只要有一个不对应,则从那个不对应的开始,数据均错,直接回车,导致程序直接运行结束,不会再提示你输入j的值,s的值。

九、cin.get()

有点类似于getchar(),针对字符,会把空格空格(十进制对应32)、回车中的换行符(十进制对应10)当做正常值。

#include "stdafx.h"

#include<iostream>

#include <string>

using namespace std;

int main()

{

int i,j;

char s;

i=cin.get();

cout<<i<<endl;

j=cin.get();

cout<<j<<endl;

int  str;

str=cin.get();

cout<<str<<endl;

return 0;

}

如果输入1回车,则输出为:

49

10

等待str的输入。

如果输入1 回车,(1后面有一个空格),则输出为:

49

32

10

如果输入1 回车,(1后面有二个空格),则输出为:

49

32

32

十、cin.getline()

此函数是按行读取,其语法为:cin.getline(字符指针,字符个数N,结束符);

功能是:一次读取多个字符(包括空白字符),直到读满N-1个,或者遇到指定的结束符为止(默认的是以' '结束)。

#include<iostream>

#include <string>

using namespace std;

int main()

{

char a[6];

cin.getline(a,6);

cout<<a<<endl;

return 0;

}

比如输入:abc回车,则a为”abc”,因为cin.getline()以回车符为结束标志,读取N-1个字符。对于char a[6];

cin.getline(a,N);中的N最大为7。如果大于7,对于a[6]来说没有意义,因为a[6]数组到元素a[5]有意义,a[6]就没有意义(从0开始的)。cin.getline(a,5,'a');则a数组最多取输入的前5个字符,但遇到字符’a’结束,且遇到字符’a’结束优先取最多5个字符。

cin.getline();一次输入对应一条该语句,若cin.getline(a,5)即使你在控制台输入再多,也之最多取前4个字符。以回车换行符为结束标志。

但是,对于下面类似的:

#include<iostream>

#include <string>

using namespace std;

int main()

{

char a[6];

cin.getline(a,6);

cout<<a<<endl;

cin.getline(a,6);

cout<<a<<endl;

return 0;

}

如果输入为:abcdef(反正只要大于5(包括空格),第一个a会取前5个字符,但第二个则为空)

可用cin.clear();来更正。

#include "stdafx.h"

#include<iostream>

#include <string>

#include <stdlib.h>

using namespace std;

int main()

{

char a[4];

char b[4];

cin.getline(a,5);

cin.clear(); //更正输入

cout<<a<<endl;

cin.getline(b,5);

cout<<b<<endl;

return 0;

}

若输入abcdegfgaa,则前四个字符abcd为a,egfg对应b;

若输入ab egfgaa,则前四个字符ab e为a,egfg对应b;

----也就是当第一个输入不满足小于cin.getline(,N,)中N个字符,则cin.clear();起到一次校正作用,只一次。

如:

#include "stdafx.h"

#include<iostream>

#include <string>

#include <stdlib.h>

using namespace std;

int main()

{

char a[4];

char b[4];

cin.getline(a,5);

cin.clear(); //更正输入

cout<<a<<endl;

cin.getline(b,5);

cout<<b<<endl;

cin.getline(b,5);

cout<<b<<endl;

return 0;

}

若输入:abcdqqqqww,大于8,则第三个cin.getline()则为空格。

十一、getline()

getline(cin,str);的getline是string类对象的成员函数,即string::getline,使用时需头文件#include <string>,注意不是cstring

原型

  istream& getline ( istream& is, string& str, char delim );

  istream& getline ( istream& is, string& str );

参数

  is 进行读入操作的输入流

  str 存储读入的内容

  delim 终结符

返回值

  与参数is是一样的

功能

  将输入流is中读到的字符存入str中,直到遇到终结符delim才结束。对于第一个函数delim是可以由用户自己定义的终结符;对于第二个函数delim默认为 ' '(换行符)。

  函数在输入流is中遇到文件结束符(EOF)或者在读入字符的过程中遇到错误都会结束。

  在遇到终结符delim后,delim会被丢弃,不存入str中。在下次读入操作时,将在delim的下个字符开始读入。

微软VC++6.0的一个bug,在别的地方已更正。

在VC++6.0下,使用getline函数时,当输入一个字符串时,要敲两下回车,这个语句才结束,而用cin.getline则不用。(linux中不存在此现象)

当运行这个程序时: #include <iostream> #include <string> using namespace std; int main () {     string name;      getline (cin, name);     cout <<name;

return 0; } 要想执行cout这个语句时,要敲两次回车才可以,当我输入one sentence[ENTER]时,它并不运行cout这个语句,而是光标还在编绎窗口上闪动,要再按一下[ENTER]才会运行cout这个语句, 而下面这个用cin.getline函数就不用, #include <iostream> #include <string> using namespace std; int main () {

char name[100];

cin.getline (name , 100);

cout <<name;

return 0; }

该问题已在 Microsoft Visual C++.NET 中修正.

原文地址:https://www.cnblogs.com/gaoxianzhi/p/7080178.html