简体   繁体   中英

How to read only one column from a csv file in c++?

Here I have an excel file whose first column has ID's ie: ID 12 32 45 12.. There are other columns as well but I only want to read the data present in first column ie ID.

Here is my code which throws exception. I don't know why?

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm> 
#include<string>
#include<cstdlib>
//std::find
#include<cstring>
using namespace std;
int main()
{
   

    ifstream fin("1.csv");
    string line;
    int rowCount = 0;
    int rowIdx = 0; //keep track of inserted rows

    //count the total nb of lines in your file
    while (getline(fin, line)) {
        rowCount++;
    }

    //this will be your table. A row is represented by data[row_number].
    //If you want to access the name of the column #47, you would
    //cout << data[0][46]. 0 being the first row(assuming headers)
    //and 46 is the 47 column.
    //But first you have to input the data. See below.
    std::vector<std::vector<std::string>> data;

    fin.clear(); //remove failbit (ie: continue using fin.)
    fin.seekg(fin.beg); //rewind stream to start

    while (getline(fin, line)) //for every line in input file
    {
        stringstream ss(line);  //copy line to stringstream
       string value;
        
        while (getline(ss, value, ',')) {       //for every value in that stream (ie: every cell on that row)
            data[rowIdx].push_back(value);//add that value at the end of the current row in our table
        }
        rowIdx++;   //increment row number before reading in next line
    }
fin.close();


//Now you can choose to access the data however you like.
//If you want to printout only column 47...

int colNum;
string colName = "ID";

//1.Find the index of column name "computer science" on the first row, using iterator
//note: if "it == data[0].end()", it means that that column name was not found 
vector<string>::iterator it = find(data[0].begin(), data[0].end(), colName);

//calulate its index (ie: column number integer)  
colNum = std::distance(data[0].begin(), it);

//2. Print the column with the header "computer science"
for (int row = 0; row < rowCount; row++)
{
    cout << data[row][colNum] << "\t";  //print every value in column 47 only
}
cout << endl;

return 0;
}


Kindly help me to fix the issue. I want to display only first column which contain ID's.

Here's a simplified version of the above code. It gets rid of the 2D vector, and only reads the first column.

std::vector<std::string> data;
ifstream fin("1.csv");
string line;
while (getline(fin, line)) //for every line in input file
{
    stringstream ss(line);  //copy line to stringstream
    string value;
    if (getline(ss, value, ',')) {
        data.push_back(value);
    }
}

EDIT

How to display the data

for (size_t i = 0; i < data.size(); ++i)
    cout << data[i] << '\n';

The problem:

std::vector<std::vector<std::string>> data;

Allocates a vector of vector s. Both dimensions are currently set to 0.

data[rowIdx].push_back(value);

pushes into and potentially resizes the inner vector , but the outer vector remains size 0. No value of rowIdx is valid. The naive solution is to use rowCount to size the outer vector , but it turns out that's a waste. You can assemble whole rows and then push_back the row into data , but even this is a waste since only one column is needed.

One of the beauties of vector is you don't have to know the number of rows. Your make a row vector, push the columns into it, then push the row into data. when you hit the end of he file, you're done reading. No need to read the file twice, but you probably trade off a bit of wasted storage on data's last self-resize.

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
// reduced includes to minimum needed for this example
// removed using namespace std; to reduce odds of a naming collision
int main() {

    std::ifstream fin("1.csv"); // Relative path, so watch out for problems 
                                // with working directory
    std::string line;
    std::vector<std::string> data; // only need one column? Only need one 
                                   // dimension
    if (fin.is_open())
    {
        while (std::getline(fin, line)) //for every line in input file
        {
            std::stringstream ss(line);
            std::string value;
    
            if (std::getline(ss, value, ',')) 
            {
                 // only take the first column If you need, say, the third 
                 // column read and discard the first two columns 
                 // and store the third
                data.push_back(value); // vector sizes itself with push_back, 
                                       // so there is no need to count the rows
            }
        }
    }
    else
    {
        std::cerr << "Cannot open file\n";
        return -1;
    }
    // use the column of data here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM