1

I'm trying to read a CSV file using 2d array but there's a problem with the reading. The first cell of the file is skipped and then continues read all. I don't understand why it doesn't read the first cell.

#include<iostream>
#include<fstream>
#include<cstring>
#include<string>
#include<sstream>
using namespace std;

int main()
{
  string arrival,job[3][4];
  ifstream jobfile("myfile.csv");
  std::string fileCommand;

  if(jobfile.is_open())
  {
      cout << "Successfully open file"<<endl;

      while(getline(jobfile,arrival,','))
      {
        for(int i=1;i < 4;i++) //i = no. of job
        {
            for(int j=0; j<4; j++) // j = no. of processes
            {
                getline(jobfile,job[i][j],',');
                cout << "Job[" << i << "]P[" << j << "]: "<< job[i][j]<< endl;
            }

        }//end for
      }//end while
  }//end if for jobfile open
  jobfile.close();    
}
jww
  • 97,681
  • 90
  • 411
  • 885
Beginner
  • 27
  • 10
  • 5
    Are you sure you want `i` to start at 1 ? – Botje Dec 05 '18 at 09:23
  • 1
    why you start `i` index from 1?? – Alexanov Dec 05 '18 at 09:28
  • 1
    Possible duplicate of [How can I read and parse CSV files in C++?](https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c) – Marek R Dec 05 '18 at 09:48
  • Try changing `for(int i=1;i < 4;i++)` to `for(int i=0;i < 3;i++)` and see what happens. You are accessing the array `job[3][4]` out of bounds. Also, `jobfile.close();` isn't needed, the `ifstream` object has a destructor. – Bob__ Dec 05 '18 at 10:00

1 Answers1

1

Change this:

for(int i=1;i < 3;i++)

to this:

for(int i=0;i < 3;i++)

Also, remove this getline(jobfile,job[i][j],',');, since you skip a line that way. When you called getline in the condition of the while loop, it already read a line (as a result, now, you have to store that line. Then, when the condition of the while loop is evaluated again, the next line will be read).


However, it gets much more complicated than this, since you arrival will hold one token at a time, until it meets the last token of the current line. In that case, arrival will be this: "currentLineLastToken\nnextLineFirstToken".

For that reason, you need to specially handle the case that arrival contains a newline, use string::find for this.

When a newline is found, you should split that string to that newline, in order to extract the two tokens involved. Use string::substr for this.

Moreover, you shouldn't loop inside the while loop with a double for to store the token, you just read. Use a double for loop, when it is time to print job, only after exiting the while loop that read the file.

Putting everything together, we get this:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
  string arrival,job[3][4];
  ifstream jobfile("myfile.csv");
  std::string fileCommand;

  if(jobfile.is_open())
  {
      cout << "Successfully open file"<<endl;

      int i = 0, j = 0;
      while(getline(jobfile,arrival,','))
      {
        //cout << "|" << arrival << "|" << endl;
        size_t found = arrival.find("\n");
        if (found != std::string::npos) // if newline was found
        {
                string lastToken = arrival.substr(0, found);
                string nextLineFirstTOken = arrival.substr(found + 1);
                job[i++][j] = lastToken;
                j = 0;
                if(nextLineFirstTOken != "\n") // when you read the last token of the last line
                        job[i][j++] = nextLineFirstTOken;
        }
        else
        {
                job[i][j++] = arrival;
        }

      }//end while

      for(int i = 0; i < 3; ++i)
      {
        for(int j = 0; j < 4; ++j)
        {
                cout << job[i][j] << " ";
        }
        cout << endl;
      }

  }//end if for jobfile open
  jobfile.close();
}

Output (for my custom input):

Successfully open file
aa bb cc dd 
bla blu blo ble 
qq ww ee rr
gsamaras
  • 71,951
  • 46
  • 188
  • 305