c-getline-与-get

转自:https://blog.csdn.net/qq_38289815/article/details/86681911

在做一些需要输入大量数据,且数据比较多样化的算法题的时候,需要了解一下这两个函数的用法。

在我们在输入大量数据,从输入流中不断读取数据的时候,一定要建立流的概念,不要出错,比如我们需要输入n行数据的时候,我们首先输入数据n,cin>>n;,这时候一定要注意在流中的第一个字符还是换行符’\n’,这时如果要继续读取数据,我们就需要从输入流中将换行符去除 cin.get(),如果不去除的话,如果我们使用getline或者输入字符串,那么就会出现错误。

#include <iostream>
using namespace std;
 
int main()
{
    const int Asize = 20;
    char name[Asize];
    char dessert[Asize];
 
    cout << "Enter your name:" <<endl;
    cin >> name;
    cout << "Enter your favorite dessert:" <<endl;
    cin >> dessert;
    cout << "I have some delicious " << dessert;
    cout << "for you, " << name << endl;
    return 0;
}

在没有输入你最喜欢的甜点的提示下,程序就把它显示出来了,然后立即显示最后一行。这是因为cin使用空白(空格、制表符和换行符)来确定字符串的结束位置,这意味着cin在获取字符串数组输入时只读取空格前的一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。

为了能读取一行字符串输入,cin提供了一些面向行的类成员函数:getline()和get()。这两个函数都读取一行输入,直到到达换行符。然而,随后个getline()会丢弃换行符,而get()将换行符保留在输入序列中。下面详细介绍它们,首先介绍getline()。

面向行的输入:istream& getline(char *p, int n, char c)

getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。要调用这种方法,可以使用cin.getline()。该函数有两个参数。第一个参数是用来存储输入行的数组的名称,第二个参数是要读取的字符数量。如果参数是20,那么最多可以读取19个字符,余下的空间用于存储自动在结尾处添加的空字符。如果在读取n-1个字符之前遇到终止字符(第三个参数不写,默认为’\n’),则提前结束。getline()成员函数在读取指定数目的字符或遇到换行符时停止读取。

#include <iostream>
using namespace std;
 
int main()
{
    const int Asize = 20;
    char name[Asize];
    char dessert[Asize];
 
    cout << "Enter your name:" <<endl;
    cin.getline(name, Asize);
    cout << "Enter your favorite dessert:" <<endl;
    cin.getline(dessert, Asize);
    cout << "I have some delicious " << dessert;
    cout << "for you, " << name << endl;
    return 0;
}

getline(cin, inputLine),其中cin是正在读取的输入流,而inputLine是接收输入字符串的string变量的名称。需要注意的是,它不是类方法。

#include <iostream>
#include <string> // Header file needed to use string objects
using namespace std;
int main()
{
    string name;
    string city;
    cout << "Please enter your name: ";
    getline(cin, name);
    cout << "Enter the city you live in: ";
    getline(cin, city);
    cout << "Hello, " << name << endl;
    cout << "You live in " << city << endl;
    return 0;
}

面向行的输入:istream& get(char *p, int n, char c)

另一个名为get()的成员函数,该函数有几种变体。其中一种变体的工作方式和getline()类似,它们接受的参数相同,解释参数的方式也相同,并且都读取到行尾。情况1:当输入的字符数小于n时遇到终结符,get()并不再读取并丢弃终结符,而是将其留在输入队列中。而getline函数将读取这个字符但是不存进p所指的数组中,而是将其丢弃。当然,两者都会在读取的字符串后面自动加上’\0’。假设我们连续两次调用get():

cin.get(name, Asize);
cin.get(dessert, Asize);    //dessert没有内容

****由于第一次调用后,换行符将留在输入队列中,因此第二次调用时看到第一个字符便是换行符。因此get()认为已到达行尾,而没有发现任何可读取的内容。****如果不借助于帮助,get()将不能跨过该换行符。这时可以使用get()的另一种变体。使用不带任何参数的cin.get()调用可读取下一个字符(即使是换行符)。

cin.get(name, Asize);
cin.get();
cin.get(dessert, Asize);

另一种使用get()的方式是将两个类成员函数拼接起来:

cin.get(name, Asize).get();

之所以可以这样做,是由于cin.get(name, Asize)返回一个cin对象,该对象随后将被用来调用get()函数。同样,下面的语句将输入中连续的两行分别读入到数组name1和数组name2中,其效果与两次调用cin.getline()相同:

cin.getline(name1, Asize).getline(name2, Asize);
#include <iostream>
using namespace std;
 
int main()
{
    const int Asize = 20;
    char name[Asize];
    char dessert[Asize];
 
    cout << "Enter your name:" <<endl;
    cin.get(name, Asize).get();
    cout << "Enter your favorite dessert:" <<endl;
    cin.get(dessert, Asize).get();
    cout << "I have some delicious " << dessert;
    cout << "for you, " << name << endl;
    return 0;
}

空格行和其他问题

当getline()或get()读取空格时,将发生什么情况?当get()读取空行后将设置失效位。这意味着接下来的输入将被阻断,但可以用下面的命令来恢复输入:cin.clear();

情况2:另一个潜在的问题是,输入字符串可能比分配的空间要长。*如果输入行包含的字符数比指定的多,则getline()和get()将把余下的字符留在输入队列中,对get()而言,可以用另一条读取函数来读取留在输入队列中的数据,也可以写一段代码将余下的字符清除。而getline()还会设置失效位,并关闭后面的输入。同样使用cin.clear()恢复输入。***

#include <iostream>
using namespace std;
 
int main()
{
    cout << "What year was your house built?" <<endl;
    int year;
    cin >> year;
    cout << "What is its street address?" <<endl;
    char address[80];
    cin.getline(address, 80);
    cout << "Year built: " << year <<endl;
    cout << "Address: " << address <<endl;
    cout << "Done!" <<endl;
    return 0;
}

用户根本没有输入地址的机会。问题在于,当cin读取年份,将回车键生成的换行符留在了输入队列中。后面的cin.getline()看到换行符后,将认为是一个空行,并将一个空字符串赋予address数组。解决的方法是,在读取地址之前先读取并丢弃换行符。这可以通过使用没有参数的get()和使用接受一个char参数的get():

cin >>year;
cin.get();   // or cin.get(ch);

也可以利用表达式cin >> year 返回cin对象,将调用拼接起来:

(cin >> year).get();   //  or (cin >> year).get(ch);
#include <iostream>
using namespace std;
 
int main()
{
    cout << "What year was your house built?" <<endl;
    int year;
    (cin >> year).get();
    cout << "What is its street address?\n";
    char address[80];
    cin.getline(address, 80);
    cout << "Year built: " << year <<endl;
    cout << "Address: " << address <<endl;
    cout << "Done!" <<endl;
    return 0;
}

*补充的一点:**C++中 "**\n"* *与 endl 的区别***

“\n” 表示内容为一个回车符的字符串。std::endl 是流操作,输出的作用和输出 “\n” 类似,但略有区别。

*std::endl 输出一个换行符,并立即刷新缓冲区。*

cout << endl;
相当于
std::cout << '\n';
std::fflush(stdout);
由于流操作符 << 的重载,对于 '\n'"\n",输出效果相同。

对于有输出缓冲的流(例如cout、clog),如果不手动进行缓冲区刷新操作,将在缓冲区满后自动刷新输出。不过对于 cout 来说(相对于文件输出流等),缓冲一般体现得并不明显。但是必要情况下使用 endl 代替 "\n"是个好习惯。对于无缓冲的流(例如标准错误输出流cerr),刷新是不必要的,可以直接使用 “\n”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值