-2

Hi all, im just start to learn how to do the csv file management using c++, currently this code works. it can print out the 'math' column.

but that is only if when i assigned every column using the getline(ss,#any column variable#, ',') then i print out the column that i want. but if im using this for a big list, lets say a csv file that have about 100 column. then, how can i simplified it? or is there any ways for me to only get specific column only without assigning/parsing each column to each variable? lets say from 100 column, i only want the column 47 with any possible names? or maybe i could get the column by its name?

Thanks.

acraig5075
  • 10,588
  • 3
  • 31
  • 50
  • 9
    Please don't show images of text, least of all code. Copy-paste the text *as text* into the question instead. – Some programmer dude Dec 09 '19 at 09:35
  • 1
    Anything is possible if you write code for it. Read each line into a `std::vector`, then you can index on it. If you then also read the first line into a `std::map` you could grab columns by name. – Botje Dec 09 '19 at 09:36
  • As for your problem, I recommend that you study *structures* and *classes*, and the standard containers (like [`std::vector`](https://en.cppreference.com/w/cpp/container/vector)). And remember that you can have a vector inside a structure (for e.g. data fields). – Some programmer dude Dec 09 '19 at 09:37
  • Yes, vector of strings is your best bet. Then you can just choose the element with index 46. If you attach the csv i can take a look at it – lenz Dec 09 '19 at 09:41
  • @Someprogrammerdude alright sir. next time i will do it properly. thank you for your advice and sorry for my mistakes. Hehe – SectumSempra Dec 09 '19 at 10:26
  • alright guys. im going to read about vector now. thanks :D – SectumSempra Dec 09 '19 at 23:30

2 Answers2

1

or is there any ways for me to only get specific column only without assigning/parsing each column to each variable?

It's not really practical with the CSV format to avoid reading every column, so really what you want to do is basically just discard the columns you do not want, much like you are already doing.

To make it work with an unknown number of columns, you can read into a std::vector, which is basically a dynamically sized array, so really useful for cases like this.

std::vector<std::string> read_csv_line(const std::string &line)
{
    std::vector<std::string> ret;
    std::string val;
    std::stringstream ss(line);
    while (std::getline(ss, val, ','))
        ret.push_back(std::move(val));
    return ret;
}

...
std::getline(is, line);
auto row = read_csv_line(line);
if (row.size() > 10) // Check each row is expected size!
  std::cout << row[0] << ", " << row[10] << std::endl;
else std::cerr << "Row too short" << std::endl;

You can then access the specific columns you want.

or maybe i could get the column by its name?

Assuming your CSV file has a header line, you can read that into say a std::unordered_map<std::string, size_t> where the value is the column index. Alternatively something like a std::vector with std::find.


Note that handling of quoted values, and some other possible CSV features can't be done with a single std::getline.

Fire Lancer
  • 29,364
  • 31
  • 116
  • 182
0

Here's a quick [working] example.

  • The 1st part reads in the table.
  • The 2nd part (after fin.close()) lets you choose what you want to print out (or whatever you choose to do with it).
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>  //std::find
using namespace std;
int main(int argc, char** argv)
{
   ifstream fin("filename");
   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.
   vector<string> data[rowCount];

   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=47;  //set this number to the column you want to printout

   for(int row=0; row<rowCount; row++)
   {
      cout << data[row][colNum] << "\t";  //print every value in column 47 only
   }
   cout << endl


   return 0;
}

EDIT: Adding this for a more complete answer.

To search a column by name, replace the last for loop with this snippet


   //if you want to look up a column by name, instead of by column number...
   //Use find on that row to get its column number.
   //Than you can printout just that column.
   int colNum;
   string colName = "computer science";

   //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;
}


lenz
  • 2,193
  • 17
  • 31
  • 1
    thank you, this example and your explanation is very helpful. this one could do what i want, now im trying to study the other solution given by others also. hehe. – SectumSempra Dec 09 '19 at 23:28
  • That's great! Glad I can help. Check out my edit too, I added some code to look column by name specifically. – lenz Dec 10 '19 at 00:15
  • sorry. for that searching from column name didnt work, it gave me no matching function for call to find vector..... – SectumSempra Dec 11 '19 at 07:49
  • oops add this in your includes `#include ` Sorry about that – lenz Dec 11 '19 at 09:25
  • Let me know if you have any other issue with this – lenz Dec 11 '19 at 09:35
  • ya, can you help me with this one? it is integrated from this question. but almost the same, it is just that i used different IDE. https://stackoverflow.com/questions/59349006/this-code-gives-me-errors-when-compiled-using-visual-studio-2012-but-with-codeb – SectumSempra Dec 15 '19 at 23:45
  • hi @calvinBroadus this one works just fine but i found something, if the column that i am searching for is the last column, so it could get that column, since the last column in csv dont have the comma(,). how can i fix this? – SectumSempra Jan 01 '20 at 07:06