1

I have to parse several csv files with the same basic structure and I have to save the values in different matrixes. I'd like to save each table in a single matrix but the problem is that I have some issues with the endline character. I tried to use the getlinefunction but I can't terminate the while cycle when the table is parsed.

I use this code:

// MMDS.cpp : definisce il punto di ingresso dell'applicazione console.
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>

using namespace std;

int i = 0, j = 0 , z=0;

int main()
{
    ifstream file("I_30_2_02_02_1.csv"); // declare file stream
    string value;
    string intvalue;
    string check;
    int jobs;
    int machines;
    int resources;
    vector<string> JobTime;
    vector<string> MachineId;
    vector<string> ProcTime; //archiviato come JobId MachineId ProcTime

    //prime tre righe
    getline(file, value, ';'); // #jobs
    getline(file, intvalue, '\n');
    jobs = stoi(intvalue);
    cout << "Jobs: " <<jobs << "\n";

    getline(file, value, ';'); //#machines
    getline(file, intvalue, '\n');
    machines = stoi(intvalue);
    cout << "Machines: " << machines << "\n";

    getline(file, value, ';'); //#resources
    getline(file, intvalue, '\n');
    resources = stoi(intvalue);
    cout << "Resources: " << resources << "\n";

    //scritte inutili
    getline(file, value, ';');
    cout << value << " ";
    getline(file, value, ';');
    cout << value << " ";
    getline(file, value, '\n');
    cout << value << "\n";

    //primo ciclo
    while (getline(file, intvalue)) {

        getline(file, intvalue, ';');
        JobTime.push_back(intvalue);
        getline(file, intvalue, ';');
        MachineId.push_back(intvalue);
        getline(file, intvalue, '\n');
        ProcTime.push_back(intvalue);
        //getline(file, intvalue, '\n');
    }

    for (i = 0; i <= ProcTime.size(); i++)
        cout << JobTime[i] << " " << MachineId[i] << " " << ProcTime[i] <<endl;

    cin >> intvalue;

    return 0;
}

The csv file is :

#Jobs;30
#Machines;2
#Resources;4

JobId;MachineId;PrTime
1;1;12
2;0;97
3;1;54
4;1;83
5;1;56
6;0;5
7;0;18
8;1;17
9;0;15
10;0;83

JobId;DueDate;RelDate;TardPenalty
1;575;4;1
2;563;70;2
3;483;1;8
4;519;68;1
5;540;64;10
6;546;126;8
7;550;2;6

Each table is separated by the others with one blank line. Can someone help me to read each table? Thanks a lot

Danny_ds
  • 11,201
  • 1
  • 24
  • 46
user3836982
  • 148
  • 1
  • 13
  • Possible duplicate of [How can I read and parse CSV files in C++?](http://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c) – Simon Kraemer Jan 20 '16 at 15:27
  • @SimonKraemer posted a good answer. You didn't specify what issue you are having with the endline characters, but maybe [this answer](http://stackoverflow.com/a/15328493/2744444) will help. Or at least get you going. – bratak Jan 20 '16 at 15:35
  • My issue is that when i have read the first table, my program continue to read the second table instead i want only read the first. – user3836982 Jan 20 '16 at 15:41
  • I would think that the link I shared would work then. You said each table is separated by a blank line, then `if (entry == "")` is true, then you could write it to your matrix and then maybe reset the stream? – bratak Jan 20 '16 at 15:47
  • 'entry' is a string? I cant adapt the code to my problem, it continue to read all table. – user3836982 Jan 20 '16 at 15:56

2 Answers2

2

You can use the peek() function.
check for file.peek()!='\n'
The following code should work for you.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>

using namespace std;

int i = 0, j = 0 , z=0;

int main()
{
    ifstream file("I_30_2_02_02_1.csv"); // declare file stream
    if(!file)
        return 0;
    string value;
    string intvalue;
    string check;
    int jobs;
    int machines;
    int resources;
    vector<string> JobTime;
    vector<string> MachineId;
    vector<string> ProcTime; //archiviato come JobId MachineId ProcTime

    //prime tre righe

    getline(file, value, ';'); // #jobs
    getline(file, intvalue, '\n');  
    jobs = stoi(intvalue);
    cout << "Jobs: " <<jobs << "\n";    

    getline(file, value, ';'); //#machines
    getline(file, intvalue, '\n');
    machines = stoi(intvalue);
    cout << "Machines: " << machines << "\n";

    getline(file, value, ';'); //#resources
    getline(file, intvalue, '\n');
    resources = stoi(intvalue);
    cout << "Resources: " << resources << "\n";

    //scritte inutili
    getline(file, value, ';');
    cout << value << " ";
    getline(file, value, ';');
    cout << value << " ";
    getline(file, value, '\n');
    cout << value << "\n";
    //primo ciclo
    while (file.peek()!='\n') 
    {

        getline(file, intvalue, ';');
        JobTime.push_back(intvalue);
        getline(file, intvalue, ';');
        MachineId.push_back(intvalue);
        getline(file, intvalue, '\n');
        ProcTime.push_back(intvalue);
        //getline(file, intvalue, '\n');
    }

    for (i = 0; i < ProcTime.size(); i++)
        cout << JobTime[i] << " " << MachineId[i] << " " << ProcTime[i] <<endl;

    cin >> intvalue;

return 0;
}
novice
  • 545
  • 3
  • 16
1

Maybe try if (entry.empty()), or some condition like that. Also, I think that getline() returns the length of the line (0 being empty, so a blank line will be > 0). So it should be as simple as finding the size of the blank line.

while (getline(file, intvalue)) 
{
    if (intvalue > 0) 
    {
        getline(file, intvalue, ';');
        JobTime.push_back(intvalue);

        getline(file, intvalue, ';');
        MachineId.push_back(intvalue);

        getline(file, intvalue, '\n');
        ProcTime.push_back(intvalue);

    } else {
        break;
    }
}

Or something of the like. If intvalue > 0 doesn't work, then find what the size is of the empty line and use that as the condition.

EDIT: As an alternative, getline() can return a string as well. In my opinion, this has the benefit of being searchable. I wrote a quick example of this below.

size_t pos;
std::string str;
std::string token;
std::vector<std::string> line;

// get the entire line
while ( getline(file, str) )
{
    while ( (pos = str.find(';')) != std::string::npos)
    {
        // get content up to next semicolon     
        token = str.substr(0, pos);
        line.push_back(token);
        str.erase(0, pos + 1);
    }
    // get content to the end
    token = str.substr(0, pos);
    line.push_back(token);
}

The second while loop looks for each semicolon, pushes the content, and then erases it. After the while loop, the push_back() is for the rest of the line from the last semicolon to the end.

bratak
  • 80
  • 13