Столкнувшись с проблемой перебора по векторуи печать данных - PullRequest
0 голосов
/ 19 октября 2019

Я читаю файл 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" в этом случае. спасибо

1 Ответ

0 голосов
/ 01 ноября 2019

Ваш 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, Скотт Мейерс.

...