主要是网上一些帖子的整理与自己做题的感触。
<1>主要的输入函数
1、cin
2、cin.get()
3、cin.getline()
4、getline()
5、gets()
6、getchar()
7、scanf()
<2>下面详细介绍
ps:cin.ignore();cin.get()//跳过一个字符,例如不想要的回车,空格等字符
1 cin>>
程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入,这就是例子中为什么会出现输入语句失效的原因!
cin提供了很多可用的成员函数和重载的操作符,如:cin<<, cin.get(), cin.getline()等。
用法1:最基本,也是最常用的用法,输入一个数字:
#include <iostream>
using namespace std;
main ()
{
int a,b;
cin>>a>>b;
cout<<a+b<<endl;
}
输入:2[回车]3[回车]
输出:5
注意:>> 是会过滤掉不可见字符(如 空格 回车,TAB 等)
cin>>noskipws>>input[j];//不想略过空白字符,那就使用 noskipws 流控制
用法2:接受一个字符串,遇“空格”、“TAB”、“回车”都结束
#include <iostream>
using namespace std;
main () {
char a[20];
cin>>a;
cout<<a<<endl;
}
输入:jkljkljkl
输出:jkljkljkl
输入:jkljkl jkljkl //遇空格结束
输出:jkljkl
2 cin.get() 可以接受空格
该函数有三种格式:无参,一参数,二参数
即cin.get(), cin.get(char ch), cin.get(array_name, Arsize)
读取字符的情况:
输入结束条件:Enter键
对结束符处理:不丢弃缓冲区中的Enter
cin.get() 与 cin.get(char ch)用于读取字符,他们的使用是相似的,
即:ch=cin.get() 与 cin.get(ch)是等价的。
读取字符串的情况:
cin.get(array_name, Arsize)是用来读取字符串的,可以接受空格字符,遇到Enter结束输入,按照长度(Arsize)读取字符, 会丢弃最后的Enter字符。
1.用法1: cin.get(字符变量名)可以用来接收字符
#include <iostream>
using namespace std;
int main (){
char ch;
ch=cin.get(); //或者cin.get(ch);
cout<<ch<<endl;
}
输入:jljkljkl
输出:j
2.用法2:cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格
#include <iostream>
using namespace std;
main () {
char a[20];
cin.get(a,20);
cout<<a<<endl;
}
输入:jkl jkl jkl
输出:jkl jkl jkl
输入:abcdeabcdeabcdeabcdeabcde (输入25个字符)
输出:abcdeabcdeabcdeabcd (接收19个字符+1个'\0')
若输入超长,则按需要的长度取数据。
#include <iostream>
using namespace std;
int main (){
char ch, a[20];
cin.get(a, 5);
cin>>ch;
cout<<a<<endl;
cout<<(int)ch<<endl;
return 0;
}
测试一输入:
12345[Enter]
输出:
1234
53
【分析】第一次输入超长,字符串按长度取了"1234",而'5'仍残留在缓冲区中,所以第二次输入字符没有从键盘读入,而是直接取了'5',所以打印的ASCII值是53('5'的ASCII值)。
3.用法3:cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符,或者舍弃回车,弥补cin.get(字符数组名,接收字符数目)的不足.
3 cin.getline() // 接受一个字符串,可以接收空格并输出
#include <iostream>
using namespace std;
main ()
{
char m[20];
cin.getline(m,5);
cout<<m<<endl;
}
输入:jkljkljkl
输出:jklj
接受5个字符到m中,其中最后一个为'\0',所以只看到4个字符输出;
如果把5改成20:
输入:jklf fjlsjf fjsdklf
输出:jklf fjlsjf fjsdklf
//延伸:
1.cin.getline()实际上有三个参数,cin.getline(接受字符串的看哦那间m,接受个数5,结束字符)
当第三个参数省略时,系统默认为'\0'
当用在多维数组中的时候,也可以用cin.getline(m[i],20)之类的用法:
#include<iostream>
#include<string>
using namespace std;
main () {
char m[3][20];
for(int i=0;i<3;i++)
{
cout<<"\n请输入第"<<i+1<<"个字符串:"<<endl;
cin.getline(m[i],20);
}
cout<<endl;
for(int j=0;j<3;j++)
cout<<"输出m["<<j<<"]的值:"<<m[j]<<endl;
}
请输入第1个字符串:
kskr1
请输入第2个字符串:
kskr2
输入第3个字符串:
kskr3
输出m[0]的值:kskr1
输出m[1]的值:kskr2
输出m[2]的值:kskr3
2.cin.getline() 与 cin.get(array_name, Arsize)的读取方式差不多,以Enter结束,可以接受空格字符。按照长度(Arsize)读取字符, 会丢弃最后的Enter字符。
但是这两个函数是有区别的:
cin.get(array_name, Arsize)当输入的字符串超长时,不会引起cin函数的错误,后面的cin操作会继续执行,只是直接从缓冲区中取数据。但是cin.getline()当输入超长时,会引起cin函数的错误,后面的cin操作将不再执行。
#include <iostream>
using namespace std;
int main ()
{
char ch, a[20];
cin.getline(a, 5);
cin>>ch;
cout<<a<<endl;
cout<<(int)ch<<endl;
return 0;
}
测试输入:
12345[Enter]
输出:
1234
-52
【分析】与cin.get(array_name, Arsize)的例程比较会发现,这里的ch并没有读取缓冲区中的5,而是返回了-52,这里其实cin>>ch语句没有执行,是因为cin出错了!
4 getline(cin,line);
将输入流的一行数据输入到字符串变量line中。(即从输入流接收字符串,可接受空格)
getline不是C库函数,而是gcc的扩展定义或者C++库函数。它会生成一个包含一串从输入流读入的字符的字符串,直到以下情况发生会导致生成的此字符串结束:
1)到文件结束,2)遇到函数的定界符,3)输入达到最大限度。
1.C 有 fgets(), gets() 函数,gcc编译器扩展定义了getline()函数.用于读取一行字符直到换行符,包括换行符
#define _GNU_SOURCE
#include <stdio.h>
将字符串存入string时需包含#include<string>
函数声明:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
成功:返回读取的字节数。
失败:返回-1。
参数:
lineptr:指向存放该行字符的指针,如果是NULL,则有系统帮助malloc,请在使用完成后free释放。
n:如果是由系统malloc的指针,请填0
stream:文件描述符
示例:
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/motd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1){
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
2.C++特性
char c[10]={'\0'};
cin.getline(c,10,'#');//将getline换成get试试,情况就大不相同了
PS:getline函数和cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数
例如下面的程序,输入是什么输出也是什么:
#include<iostream>
#include<string>
using namespace std;
main ()
{
string str;
getline(cin,str);
cout<<str<<endl;
}
输入:jkljkljkl
输出:jkljkljkl
3.getline(char*array,int count,char delim)与get(char*array,int count,char delim)的不同点:
1.当输入的字符数小于count时遇到字符delim,get函数不会读取delim这个字符,而getline函数将读取这个字符但是不存进array当中去,而是将其丢弃,当然,两者都会在读取的字符串后面自动加上'\0'(teminator character)
2.当输入的字符数大于count时,则get函数只读取count-1个字符,而其余的字符仍然保存在缓冲区中,还可再对其进行读取;但是函数getline则不然。
如果输入行包含的字符数比指定要读取的字符多,那么get()和getline()读取指定数目的字符后,将把余下的字符留在输入队列中。对get()而言,我们可以用另一条读取函数来读取留在输入队列中的数据,你也可以写一段代码将余下的字符清除。不同的是getline()会设置失效位(faibit),并且关闭后面的输入,这个时候用ch=cin.get();是读取不到留在输入队列中的字符的。你可以用下面的命令来恢复输入:
cin.clear();
因为clear()会重置失效位,打开输入。这个时候ch=cin.get();就可以读取留在输入队列中的字符。
4.ignore用法举例一则:
cin.ignore( 5, 'c' );//忽略前5个字符除非遇到字符'c',而停止忽略字符
//ignore的函数原型为:basic_istream& ignore(streamsize _Count = 1,int_type _Delim = traits_type::eof( ));
cin >> chararray;
5 scanf使用
scanf()函数取数据是遇到回车、空格、TAB就会停止
#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;
}
如例上面的例子,第一个scanf()会取出"Hello",而"world!"还在缓冲区中,这样第二个scanf会直接取出这些数据,而不会等待从终端输入。所以测试结果如下
测试一输入:
Hello world!
输出:
Hello
world!
为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)。
方法2:自己取出缓冲区里的残留数据。
scanf("%[^\n]",string);
PS:scanf与cin及相应输出的区别
1.scanf不安全,因为输入已经溢出,但是还能够给出正确结果且没有提示。而cout,cin会给出结果
2.cin慢是有原因的,其实默认的时候,cin与stdin总是保持同步的,也就是说这两种方法可以混用,而不必担心文件指针混乱,同时cout和stdout也一样,两者混用不会输出顺序错乱。
详细原因
scanf是格式化输入,printf是格式化输出。格式化输出效率比较高,但是写代码麻烦。
因为scanf是用指针操作的,没有类型安全机制,比如一个char类型数据你就可以用%f获得输入,而不会报错,但在运行时会出现异常。
cin是输入流,cout是输出流。效率稍低,但书写简便。流输出操作效率稍低,但书写简便。
先把要输出的东西存入缓冲区,再输出,导致效率降低,cin是自动判断你的变量类型,比如一个char数据只能用默认的char方法取数据。
3.一次输入过程是这样的:当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。
10恰好是回车符,这是因为scanf()和getchar()函数是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,所以第一次接受输入时取走字符后会留下字符\n,这样第二次的读入函数直接从缓冲区中把\n取走了,显然读取成功了,所以不会再从终端读取!这就是为什么这个程序只执行了一次输入操作就结束的原因!
4.理论上来说cout,cin要比scanf等要慢,不过在最新的G++中,据说cin已经比scanf快了,ACM如果scanf超时的话可以用G++提交一下
刷acm的话最好使用scanf等函数,或者输出时尽量使用cout,输入时尽量使用scanf
6 getchar函数,输入单个字符
char c;
c=getch();
putchar(c);
注意连续两个getchar函数之间需要加fflush来将缓存中的换行给清除,不然会出错,如
ch1 = getchar();
fflush(stdin);
ch2 = getchar();
7 fflush(stdout);//强制刷新缓存,输出显示
fflush()会强迫将缓冲区内的数据写回参数stream 指定的文件中. 如果参数stream 为NULL,fflush()会将所有打开的文件数据更新
fflush用于清空缓冲流,虽然一般感觉不到,但是默认printf是缓冲输出的。
fflush(stdout),使stdout清空,就会立刻输出所有在缓冲区的内容。
fflush(stdout)这个例子可能不太明显,但对stdin很明显。
如下语句:
int a,c;
scanf("%d",&a);
getchar();
输入:
12(回车)
那么 a=12 ,c= '\n'
而:
int a,c;
scanf("%d",&a);
fflush(stdin);
getchar();
输入:
12(回车)
那么a=12, c暂时未得到输入值,还需要再输入c,因为getchar也是缓冲输入,'\n'本还在缓冲区,但是被清空了。
另外fflush不能作用于重定向输入流。