0

I'm a beginner in c++ and required to write a c++ program to read and print a csv file like this.

DateTime,value1,value2
12/07/16 13:00,3.60,50000
14/07/16 20:00,4.55,3000

May I know how can I proceed with the programming? I manage to get the date only via a simple multimap code.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111

2 Answers2

1

I spent some time to make almost (read notice at the end) exact solution for you.

I assume that your program is a console application that receives the original csv-file name as a command line argument.

So see the following code and make required changes if you like:

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

std::vector<std::string> getLineFromCSV(std::istream& str, std::map<int, int>& widthMap)
{
    std::vector<std::string> result;
    std::string line;
    std::getline(str, line);

    std::stringstream lineStream(line);
    std::string cell;

    int cellCnt = 0;

    while (std::getline(lineStream, cell, ','))
    {
        result.push_back(cell);
        int width = cell.length();
        if (width > widthMap[cellCnt])
            widthMap[cellCnt] = width;
        cellCnt++;
    }
    return result;
}

int main(int argc, char * argv[]) 
{
    std::vector<std::vector<std::string>> result; // table with data
    std::map<int, int> columnWidths; // map to store maximum length (value) of a string in the column (key)
    std::ifstream inpfile;
    // check file name in the argv[1]
    if (argc > 1)
    {
        inpfile.open(argv[1]);
        if (!inpfile.is_open())
        {
            std::cout << "File " << argv[1] << " cannot be read!" << std::endl;
            return 1;
        }
    }
    else
    {
        std::cout << "Run progran as: " << argv[0] << " input_file.csv" << std::endl;
        return 2;
    }
    // read from file stream line by line
    while (inpfile.good())
    {
        result.push_back(getLineFromCSV(inpfile, columnWidths));
    }
    // close the file
    inpfile.close();
    // output the results
    std::cout << "Content of the file:" << std::endl;
    for (std::vector<std::vector<std::string>>::iterator i = result.begin(); i != result.end(); i++)
    {
        int rawLen = i->size();
        for (int j = 0; j < rawLen; j++)
        {
            std::cout.width(columnWidths[j]);
            std::cout << (*i)[j] << " | ";
        }
        std::cout << std::endl;
    }
    return 0;
}

NOTE: Your task is just to replace a vector of vectors (type std::vector<std::vector<std::string>> that are used for result) to a multimap (I hope you understand what should be a key in your solution)

VolAnd
  • 6,367
  • 3
  • 25
  • 43
  • Hi VolAnd, Thanks for the great help! It was actually a school project and which is a must to use map in the program. – リック エリック Jul 28 '16 at 12:52
  • I assumed it, and because of this add simple `map` to store widths of columns. In any case you are free to use my example for any your solution. – VolAnd Jul 28 '16 at 13:12
0

Of course, there are lots of possible solutions for that task (if you open this question and look through the answers you will understand this).

First of all, I propose to consider the following example and to try make your task in the simplest way:

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;

int main()
{
    string str = "12/07/16 13:00,3.60,50000";
    stringstream ss(str);
    vector<string> singleRow;
    char ch;
    string s = "";
    while (ss >> ch)
    {
        s += ch;
        if (ss.peek() == ',' || ss.peek() == EOF )
        {
            ss.ignore();
            singleRow.push_back(s);
            s.clear();
        }
    }
    for (vector<string>::iterator i = singleRow.begin(); i != singleRow.end(); i++)
        cout << *i << endl;
    return 0;
}

I think it can be useful for you.

Community
  • 1
  • 1
VolAnd
  • 6,367
  • 3
  • 25
  • 43