Hi,

I have wrote a program which stores values in a .csv file.

He is the how the data is stored in the .csv file:

"Steve","21 Main Street, Nottingham","SW1 1AB","0115 9123456","These are some details. and, so.","112233","1359"
"David Baner","123 Shaw street, Nottingham","NG92HJ","020 123456","ifbiugbuige","112233","1200"

Each line forms a single object.

What I want to do is retrieve the values from the .csv file, so that I can recreate the objects again, but after reading Google, find myself a little lost in how go about this as simply as possible.


So i was thinking of something like this:

cout << "You chose to load from the CSV file" << endl;

ofstream streamname("database.csv");
if(!streamname)
{
	cout << "Cannot open file" << endl;
	return 1;
}
else
{
	cout << "Stream opened successfully" << endl;
}


getline( streamname, storelinevariable, '\n' );////////////////////////////////////////////

What datatype should I use for storing the line? ie: the 'storelinevariable' parameter?

I use the following function for adding the double quotes to the datamember values when constructing an object:

//Virtual function for adding double quotes to strings input by the user for use in the .csv file:
virtual void addDoubleQuotes(string& m_Name,string& m_Address,string& m_PostCode,string& m_TelNo,string& m_Details)
{
	m_Name = '\"' + m_Name + '\"';
	m_Address = '\"' + m_Address + '\"';
	m_PostCode = '\"' + m_PostCode + '\"';
	m_TelNo = '\"' + m_TelNo + '\"';
	m_Details = '\"' + m_Details + '\"';
}

But once a line is retrieved, this is an example of how I would like to construct the object:

Derived *ptr = new Derived(mainname, mainaddress, mainpostcode, maintelno, maindetails, maindate, maintime);
vectorname.push_back( ptr );

So if anyone could point me in the right direction, I'd really appreciate it!

Many thanks!

Edited 7 Years Ago by Carrots: n/a

>>What datatype should I use for storing the line? ie: the 'storelinevariable' parameter?

If you use getline() then it has to be std::string object

What do you want to do with the lines after they are read into memory? Do you need to use individual columns, do you want to put the data into some sort of structure of c++ class then make a vector of them? Or just simply store the entire line into a vector?

Hey guys, thanks for helping.

I've gotten into a right mess with this and seems to be making it far too complicated than it needs to be.

Yes I need to use the individual columns, and add them into corresponding variables.

Here is what I've come up with (but would be MORE than happy to scrap it and use the Standard Library).

void Tokenize(const string& str, vector<string>& tokens, const string& delimiters = " ")
{
	string::size_type lastPos = str.find_first_not_of(delimiters, 0);
	string::size_type pos     = str.find_first_of(delimiters, lastPos);

	while (string::npos != pos || string::npos != lastPos)
	{
		tokens.push_back(str.substr(lastPos, pos - lastPos));
		lastPos = str.find_first_not_of(delimiters, pos);
		pos = str.find_first_of(delimiters, lastPos);
	}
}

(I found that function on the internet)

case 'd':

	{
		//---------------
		//Load from CSV file
		//---------------
		cout << "You chose to load from the CSV file" << endl;
		ifstream file("database.csv");

		
		string completelinefromcsv;
		do
		{
		getline(file,completelinefromcsv);
		vector <string> loadvector;

		int a = 0;

		cout << completelinefromcsv << endl;

		Tokenize(completelinefromcsv, loadvector, ",");//put the separate strings into the vector

		string mainname;
		mainname = loadvector[a];
		//a++;
		//string mainaddress = loadvector[a];
		//a++;
		//string mainpostcode = loadvector[a];
		//a++;
		//string maintelno = loadvector[a];
		//a++;
		//string maindetails = loadvector[a];
		//a++;
		//string maindate = loadvector[a];
		//a++;
		//string maintime = loadvector[a];

		}
		while(getline(file,completelinefromcsv));

		file.close();

		break;
	}

When I run the code, it compiles, then reports saying "vector subscript out of range".

I tried stringstream(), but got it all wrong, so ended up trying the above. :sad:

Like I say, I'm trying to get each column into the variables:

mainname;
mainaddress;
mainpostcode;
maintelno;
maindetails;
maindate;
maintime;

Any help is real appreciated, especially if I can scrap all that cra**y effort and use the standard library.

Edited 7 Years Ago by Carrots: n/a

The only thing that can fix ugly data is ugly code.

Here's some (functional, but ugly) .NET code.

// UnUglyCSV.cpp : main project file.

#include "stdafx.h"

using namespace System;
using namespace System::IO;
using namespace System::Collections::Generic;
using namespace System::Linq;

int main(array<System::String ^> ^args)
{
	StreamReader^ fileIn = gcnew StreamReader("TextFile1.csv");
	array<String^>^ arr_strData = { };
	String^ strData = "";

	while (!fileIn->EndOfStream)
	{
		strData = fileIn->ReadLine()->Trim()
			->Replace("\",\"", "]\t[")
			->Replace("\",", "]\t")
			->Replace("\"", "\t")->Trim();

		arr_strData = strData->Split(String("\t]").ToCharArray(),
			StringSplitOptions::RemoveEmptyEntries);

		List<String^>^ lstStrFinal = gcnew List<String^>();
		for each (String^ str in arr_strData)
		{
			if (str->StartsWith("["))
			{
				lstStrFinal->Add(str->Replace("[", ""));
			}
			else if (str->Contains(","))
			{
			for each (String^ s2 in str->Split(String(",").ToCharArray(),
				StringSplitOptions::RemoveEmptyEntries))
				{
					lstStrFinal->Add(s2);
				}
			}
			else
			{
				lstStrFinal->Add(str);
			}
		}

		String^ strName = lstStrFinal[0];
		String^ strAddress = lstStrFinal[1];
		String^ strPostCode = lstStrFinal[2];
		String^ strTelNo = lstStrFinal[3];
		String^ strDetails = lstStrFinal[4];
	}
	fileIn->Close();

	return 0;
}

Here is another way to do it (standard c++). Create a structure that holds the data for one line, then a vector of those structures.

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

struct data
{
    string name;
    string address;
    string postCode;
    string phone;
    string details;
    string var1;
    string var2;

};

vector<data> dataList;

void parseLine(data& d, string& line)
{
    string n;
    size_t pos = 0;
    int count = 0;
    while( line.size() > 0)
    {
        if( line[0] == '\"' )
        {
            pos = line.find('\"', 1);
            n = line.substr(1,pos);
            while(pos < line.length() && line[pos] != ',' )
                pos++;
            if( pos == line.length())
                line = "";
            else
                line = line.substr(pos+1);
            switch(count)
            {
            case 0: d.name = n; break;
            case 1: d.address = n; break;
            case 2: d.postCode = n; break;
            case 3: d.phone = n; break;
            case 4: d.details = n; break;
            case 5: d.var1 = n; break;
            case 6: d.var2 = n; break;
            }
            ++count;
        }
    }
}

int main(int argc, char* argv[])
{
    data d;
    string line;
    ifstream in("myfile.csv");
    while( getline(in, line) )
    {
        parseLine(d, line);
        dataList.push_back(d);
    }
	return 0;
}
This article has been dead for over six months. Start a new discussion instead.