0

I am trying to parse CSV into Array of structures. Delimiter is ';'. If you look into the code it seems that I filled only first element of the array out of nine that is 9 lines are in my CSV right now. Remaining elements of the array are just 0. Anyone got some advice? Thanks

fileTO.open("imput.csv", ios_base :: app);
fileFROM.open("imput.csv", ios_base :: app);

//IntoCsvThruConsole();

// array of structures from csv

string line;

string sID, stype, scategory, samount, sdate;

int lines = CountExistingLines();

Properties * structure = new Properties[lines];
int counter = 0;
int position = 0;

while (getline(fileFROM, line))
    {
        sID = "";
        samount = "";

     for (int i = 0; i < line.size(); i++)
     {
      if (line[i] == ';')
      {
          position++;
          continue;
      }
      switch (position)
      {
          case 0 : sID = sID + line[i];
          break;

          case 1 : structure[counter].type = structure[counter].type + line[i];
          break;

          case 2 : structure[counter].category = structure[counter].category + line[i];
          break;

          case 3 : samount = samount + line[i];
          break;

          case 4 : structure[counter].date = structure[counter].date + line[i];
          break;
      }
     }
     structure[counter].ID = atoi(sID.c_str());
     structure[counter].amount = atoi(samount.c_str());

    cout << "ID zaznamu: " << structure[counter].ID << endl;
    cout << "Typ: " << structure[counter].type << endl;
    cout << "Kategorie: " << structure[counter].category << endl;
    cout << "Castka: " << structure[counter].amount << endl;
    cout << "Datum: " << structure[counter].date << endl;

    counter++;
    }

delete[] structure;

I have globally initialized struct correctly and also fstreams. Hope it is enough. Thanks

enter image description here

1 Answers1

0

I recommend using Boost.Spirit for such parsing tasks.

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>

struct Date
{
    int day;
    int month;
    int year;
};

std::ostream& operator<<(std::ostream& os, Date const &d)
{
    os << d.day << '/' << d.month << '/' << d.year;
    return os;
}

BOOST_FUSION_ADAPT_STRUCT(
    Date,
    day, month, year)

struct Properties
{
    int ID;
    std::string type;
    std::string category;
    int amount;
    Date date;
};

BOOST_FUSION_ADAPT_STRUCT(
    Properties,
    ID, type, category, amount, date)

std::vector<Properties> parse(std::string const &input)
{
    auto iter = input.begin();

    using namespace boost::spirit::x3;

    auto name = rule<class name, std::string>{}
        = lexeme[alpha >> *alpha];

    auto date = rule<class date, Date>{}
        = int_ > '/' > int_ > '/' > int_;

    std::vector<Properties> result;

    bool r = phrase_parse(iter, input.end(),
                          (int_ > ';' > name > ';' > name > ';' > int_ > ';' > date) % eol,
                          space - eol, result);

    if (!r)
    {
        std::string rest(iter, input.end());
        throw std::invalid_argument("Parsing failed at " + rest);
    }

    return result;
}


int main()
{
    // This could be a file instead with std::ifstream
    std::istringstream input;
    input.str(
        "1;TypeA;CategoryA;10;05/12/2017\n"
        "2;TypeB;CategoryA;21;04/12/2017\n"
        "3;TypeB;CategoryB;19;01/12/2017\n"
        "4;TypeA;CategoryA; 6;20/11/2017\n");

    std::vector<Properties> entry = parse(input.str());

    for (auto e :  entry)
    {
        std::cout << "Found the following entries:\n"
                  << "  ID: " << e.ID << "\n"
                  << "  Type: " << e.type << "\n"
                  << "  Category: " << e.category << "\n"
                  << "  Amount: " << e.amount << "\n"
                  << "  Date: " << e.date << "\n";
    }
}

Live example

Henri Menke
  • 10,705
  • 1
  • 24
  • 42