-1

Here I have an excel file whose first column has ID's i.e: ID 12 32 45 12 .. There are other columns as well but I only want to read the data present in first column i.e. 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.

  • You should be able to figure out the problem by answering to yourself the following question: after calculating the `rowCount`, can you point your finger at the exact line in the shown code where it is used for its intended purpose, of setting the size of the vector? – Sam Varshavchik Dec 04 '22 at 17:53
  • @SamVarshavchik actually this code is taken from stackoverflow which was marked answered. But when I run it in my computer it shows exception I don't know why? can u please find me the exact mistake? – Rao Hamdullah Dec 04 '22 at 17:57
  • 2
    Please point us at the question you got this from. We can either show you where you went wrong in your adaptation or where it went wrong and (then downvote the snot out of it so future askers are less likely to take advice from it). – user4581301 Dec 04 '22 at 18:00
  • Side note: 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. – user4581301 Dec 04 '22 at 18:04
  • @user4581301 here is the link https://stackoverflow.com/questions/59246006/is-there-any-ways-to-get-specific-column-from-csv-file – Rao Hamdullah Dec 04 '22 at 18:04
  • @user4581301 Can you please correct it and post the answer. I am doing a project with a huge dataset but I am stuck here – Rao Hamdullah Dec 04 '22 at 18:07
  • Note how the source example has an array of `vector data[rowCount];` and you have a `vector` of `vector`s and forgot to set the size of the outer `vector`. The answer is still pretty bad. If you only want one column, there's no point storing all of them. – user4581301 Dec 04 '22 at 18:08
  • @user4581301 Please post a code of alternate I tried what u said but still code throws exception – Rao Hamdullah Dec 04 '22 at 18:12
  • The voting system's not perfect, particularly because people don't like spending reputation downvoting, but if you'd gone with the second answer to the other question you would have been a lot better off. I've voted up the better answer and voted down the selected answer. The asker chose poorly. – user4581301 Dec 04 '22 at 18:36
  • Stackoverflow is not a c++ textbook replacement. Attempting to learn or write c++ code by copying other questions always ends in tears. – Sam Varshavchik Dec 04 '22 at 19:30
  • 1
    @RaoHamdullah You've tried lots of different code, and it all 'throws an exception'. What's really needed here that you give us some understanding of what that really means. Knowing what is the error that you see, is key to progressing this. So can you describe what happens when the code 'throws an exception'. – john Dec 05 '22 at 07:03

2 Answers2

1

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';
john
  • 85,011
  • 4
  • 57
  • 81
  • can u kindly tell me how to display the data on console because I have tried your code it still throws exception? – Rao Hamdullah Dec 04 '22 at 19:21
  • 1
    @RaoHamdullah any exception thrown is useful diagnostic information, if you don't tell us the precise verbatim message we don't have that benefit. It is not even clear whether you are talking about a processor exception or a C++ exception. Also using a debugger will help _you_ track down the issue yourself. – Clifford Dec 04 '22 at 19:28
  • 1
    @RaoHamdullah It's hard to understand how the code above could throw an exception. The only possibility I can think of is memory exhaustion and that seems very unlikely. So can you describe what you see when an exception is thrown. What happens to the program, what error message (if any) do you see, To be blunt it's obvious that your knowledge of C++ is limited, and one possibility is that you are not using correct terminology. So instead of saying that the code throws an exception, can you describe in detail what happens, what you see, when you run this code. Use a screenshot if that helps. – john Dec 05 '22 at 06:57
  • @RaoHamdullah I've updated the question to show how to display the data. I am wondering when you say 'it still throws an exception' whether you are talking about the above code at all. Could it be that the the above code is working but some later problem with your program is what throws the exception? – john Dec 05 '22 at 07:11
  • @john The problem is solved. But what about if I want to access the second coloumn? – Rao Hamdullah Dec 05 '22 at 08:59
  • @RaoHamdullah the second column and only the second column or the first column AND the second column? – user4581301 Dec 05 '22 at 17:54
  • @user4581301 first and second – Rao Hamdullah Dec 06 '22 at 17:11
  • @RaoHamdullah OK. Now you need a 2D array, or 2 1D arrays. `data` should look like `std::vector> data;`, so you're back to where you started, but when reading into it the code looks something like `std::vector row(2); if (std::getline(ss, row[0], ',') && std::getline(ss, row[1], ',')) { data.push_back(row); }` – user4581301 Dec 06 '22 at 17:39
  • @user4581301 what if I have seven columns? For that I have to create a 7D array? I f yes than how? Or 7 1D arrays? If yes then how? Actually I wanted to get a rough idea for having a large data set? – Rao Hamdullah Dec 07 '22 at 10:42
  • @user4581301 Thank you. I figured out actually i have to increase the number of columns – Rao Hamdullah Dec 07 '22 at 10:47
  • @user4581301 I have one another question. Kindly tell me if data in csv file have a comma in between them then how we differentiate it? – Rao Hamdullah Dec 07 '22 at 11:27
  • 1
    @RaoHamdullah Normally any such data would be quoted `"abc,def"`. Rather than trying to write your own code, you might consider getting a third party library to read CSV files. – john Dec 07 '22 at 11:36
  • @john for example? Which library? – Rao Hamdullah Dec 07 '22 at 17:37
  • @RaoHamdullah I've never used a CSV parsing library, so I can't make any recommendations. But if you [google](https://duckduckgo.com/?q=csv+library+c%2B%2B&t=chromentp&atb=v324-1&ia=web) you can find some. One word of caution, writing your own CSV parsing code requires good knowledge of C++ but so does using a 3rd party library, so it's not necessarily a magic bullet, just an alternative to consider. – john Dec 08 '22 at 07:00
0

The problem:

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

Allocates a vector of vectors. 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
}
user4581301
  • 33,082
  • 7
  • 33
  • 54