【问题标题】:Facing problem with iterating over vector<vector<string>> and printing data面临迭代 vector<vector<string>> 和打印数据的问题
【发布时间】:2020-02-15 23:36:46
【问题描述】:

我正在读取一个 CSV 文件并将其存储在向量向量字符串中。我想打印数据,为此我使用了两个 for 循环,一个迭代向量的向量,另一个迭代向量字符串。

a1,b1,c1,d1
a1,b1,c4,d3
a1,b2,c2,d2
a2,b3,c3,d4
a2,b4,c3,d4

这是我正在阅读的 CSV 数据。 下面的代码我用来打印到屏幕上

void ReadCSV::printdata(vector<vector<string>> ipd){
    for(auto it1 = ipd.begin();it1 != ipd.end();++it1){
        vector<string> test = *it1;
        for(auto it2 = test.begin();it2 != test.end();++it2){
            string r = "";
            r= *it2;
            cout<<r<<" ";
        }
        cout<<endl;
    }
}

但我得到的输出似乎没有正确迭代:

a1 b1 c1 d1 
a1 b1 c1 d1 a1 b1 c4 d3 
a1 b1 c1 d1 a1 b1 c4 d3 a1 b2 c2 d2 
a1 b1 c1 d1 a1 b1 c4 d3 a1 b2 c2 d2 a2 b3 c3 d4 
a1 b1 c1 d1 a1 b1 c4 d3 a1 b2 c2 d2 a2 b3 c3 d4 a2 b4 c3 d4

我使用下面的代码来读取数据:

vector<vector<string>> ReadCSV:: ReadData(){
    fstream fin(filename);
    vector<string> temp;
    string val1, val2, val3 ,val4;
    if(!fin.is_open()){
        cout<<"ERROR: file open";
    }
    cout<<"FIRST OUTPUT: "<<endl;
    while(fin.good()){
        getline(fin, val1,',');
        //store
        temp.push_back(val1);
        cout<<val1<<" ";
        getline(fin, val2,',');
        temp.push_back(val2);
        cout<<val2<<" ";
        getline(fin, val3,',');
        temp.push_back(val3);
        cout<<val3<<" ";
        getline(fin, val4,'\n');
        temp.push_back(val4);
        cout<<val4<<" ";
        csvdata.push_back(temp);
    }
    cout<<endl;
    return csvdata;
}

谁能告诉我哪里出错了,我面临的另一个问题是当我运行调试器(ECLIPSE IDE)并将鼠标悬停在一个变量上时,它会打开一些弹出窗口但不显示变量的值,例如“字符串r”在这种情况下。 谢谢

【问题讨论】:

  • 您确定错误出在printdata 函数中,而不是您如何读取(或以其他方式处理)数据吗?您是否尝试过在调试器中逐句执行代码,同时监控变量及其值和内容?
  • 同意@Someprogrammerdude 看起来错误最有可能出现在vector&lt;vector&lt;string&gt;&gt;中的读数中
  • 是的,我在阅读部分做了调试,我已经更新了描述中的阅读代码
  • 是时候做一些阅读代码的rubber duck debugging了。当您读取文件的内容时,temp 会发生什么? temp 会被“重置”或清除吗?
  • 您只是每次都将数据附加到 temp 中。您需要在每行之后清除它。

标签: c++ string vector stl eclipse-cdt


【解决方案1】:

您的 CSV 阅读器除了有一些小问题外,还经过硬编码,可以准确读取 4 个逗号分隔的值。这是一个更通用的代码,它可以读取尽可能多的行,并且每行都有可变数量的逗号分隔值。

#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>

template<typename In, typename Out>
void csv2vec(In first, In last, Out& result) {
    std::string temp;
    unsigned i{0};
    while(1) {
        do{
            if(*first == '\n') break;
            temp.push_back(*first);
            ++first;
        }while(*first != ',' && first != last);
        result[i].push_back(temp);
        if(*first == '\n') {
            ++i;
            result.resize(i+1);
        }
        temp.clear();
        if(first == last) break;
        ++first;
    }
}

int main(void) {
    std::vector<std::vector<std::string>> vec(1);
    std::ifstream in("data.txt");
    std::istreambuf_iterator<char> begin(in);
    std::istreambuf_iterator<char> end;
    csv2vec(begin,end,vec);

    for(const auto& vecouter : vec) {
        for(const auto& elem : vecouter){
            std::cout<<elem<<" ";
        }
        std::cout<<"\n";
    }
   return 0;
}

注意:我使用了 istreambuf_iterator,它从不跳过任何字符(包括空格,例如 '\n')。与跳过空格的 istream_iterator 不同,它会抓取流缓冲区中接下来的任何内容。 istream_iterator 在执行格式化输入时也很有用,并且比 istreambuf_iterator 慢。 参考:第 29 条,有效的 STL,Scott Meyers。

【讨论】:

    猜你喜欢
    • 2016-08-27
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 2014-11-08
    相关资源
    最近更新 更多