C++基础--标准输入流相关

本文介绍如何在C++中处理特殊格式的数据输入,包括使用getline和stringstream处理以逗号分隔的数组,以及如何读取不确定长度的数字数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开头是一个悲伤的故事。

要求:输入为两行,第一行为一个数字,第二行为用逗号分隔的数组,表示一个树的广度优先遍历。如下所示。

10

1,2,3,4,5

然后在上面实现要求,要求先不表。因为我连在C++中要怎么读入这样的数据都不会,都不会呀!还实现个毛毛!!!

两个问题:

1. 怎么判断到第二行没?

    答:第一行为一个数,直接用cin读入赋值就好。

2. 数组里有几个数母鸡呀?

    答:读入一行数,使用vector,把每个数分别存入。那么问题来了,C++里只能读入一行字符串呀,不过有stringstream类型可以将用空格分隔的数分别取出来。那么对读入的这一行用‘,’分隔的字符串,首先要做的就是把','替换为空格,然后转换为stringstream类型处理。

代码如下:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;
int main()
{
    int num;
    string line;
    vector<int> tree;
    cin >> num;
    //用cin.get()处理,才不影响接下来的对一行的操作
    cin.get();
    getline(cin,line); //将一行数据赋给字符串line
    replace(line.begin(), line.end(), ',', ' '); //将,替换为空格
    stringstream stream(line); //将line转换为stringstream类型stream
    while(stream>>num) //取出所有的整数存入vector。此处整数可以换为浮点数等其他类型
        tree.push_back(num);
    //输出验证
    cout << num <<endl;
    for(vector<int>::iterator iter=tree.begin();iter!=tree.end();++iter)
            cout<<*iter<<" ";
        cout << endl;
}

为什么不用如下的这段代码处理第二行数组中的数据呢?

<pre name="code" class="cpp">    int a;
    while(cin >> a) {
        tree.push_back(a);
        cin.get();
    }
 因为cin在读入特定类型时会忽略空格,回车,制表符等分隔符,用cin.get()吃掉数字之后的符号,不论用什么分隔符,都可以成功将数字存入vector,但由于最后的结束符被忽略,无法判断输入是否结束,只能使用 ctrl+Z 强制结束。 

因此,使用getline读入一行字符串可以很好地解决这个问题,不用判断一行到底什么时候结束,而是将这一行直接取出。

getline可以跟第三个参数表示以该参数结尾。

如getline(cin, line, '\')表示以\结尾。

replace()函数包含在<algorithm>头文件中,给定起始结束位置,被替换和替换符号,即可实现替换。

line转换为stringstream类型也可由如下代码实现:

stringstream stream;
stream << line;

stringstream可以忽略像空格,制表符这样的分隔符,取出特定类型的数。如解决下面的问题:

一行double带小数点的数字,不定项数量,每个数字之间用不定项个空格隔开,以回车结束输入,放进一个vector里。

int main(){
    string input;
    vector<double> v;
    getline(cin, input);
    stringstream str(input);
    double num;
    while (str >> num) {
        v.push_back(num);
    }
    //输出验证
    cout << v.size() << endl;
    for(vector<double>::iterator iter=v.begin();iter!=v.end();++iter)
            cout<<*iter<<" ";
}

而使用如下的方法就要用ctrl+Z强制结束

int main(){
    vector<double> v;
    for (double d; cin >> d; v.push_back(d)){}
    cout << v.size() << endl;
}

可以stringstream的这一特性进行数据类型的转换

int i;
string str;
//注意:如果做多次数据转换;必须调用clear()来设置转换模式
ss_stream << "456"; 
ss_stream >> i;   // 首先将字符串转换为int
ss_stream.clear();
ss_stream << true;
ss_stream >> i;   // 然后将bool型转换为int;假如之前没有做clear,那么i会出错
可以将字符串转换为int型456,将bool型装换为int型1


同样,使用getline还可以方便解决如下问题:

标准输入读入,每行加行号输出

int main(){
    int line = 1;
    string str;
    while(getline(cin, str)) {
        cout << line++ << " " << str << endl;
    }
    return 0;
}

Oh!多么好用的getline()和stringstream呀!可惜只是简单地学会用这一点点~



参考:

http://10741357.blog.51cto.com/10731357/1703983 

https://segmentfault.com/q/1010000004357985

https://blog.yangl1996.com/?p=226

http://www.programgo.com/article/41762737095/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值