Parsing a file

Hey all, I have this file:
Fred,Karl,Technician,2010--Karl,Cathy,VP,2009--Cathy,NULL,CEO,2007
That is suppose to be structured, via a program im currently writing, like this:
1
2
3
4
5
Cathy (CEO) 2007

-Karl (VP) 2009

--Fred (Technician) 2010

I have everything token-ized, but I have no clue how to go about organizing the tokens in that way. I feel as if im making this so much more difficult than needs be. That was only part of the file btw, it gets a lot bigger.
Can you post your code?
I finished, but if you want to look it over here it is. Any advice is appreciated :)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//cCase.h

#ifndef CLASS_CASE_H
#define CLASS_CASE_H

#include <vector>
#include <iterator>
#include <iostream>

#include "cPerson.h"

using std::vector;
using std::iterator;
using std::ostream;
using std::endl;

typedef vector<cPerson>::iterator pit;

class cCase
{
private:
	vector<cPerson> mPeople;

public:
	void Add(cPerson in_Person);

	bool IsValid(pit in_Iterator);

	pit Find(string in_Name);

	void Sort();

	friend ostream& operator<<(ostream &output, cCase& in_Case);

};


#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//cCase.cpp

#include "cCase.h"

void cCase::Add(cPerson in_Person)
{
	mPeople.push_back(in_Person);
}

pit cCase::Find(string in_Name) 
{
	for (pit it = mPeople.begin(); it != mPeople.end(); it++)
		if (it->GetName() == in_Name) return it;
	return mPeople.end();
}

bool cCase::IsValid(pit in_Iterator)
{
	if (in_Iterator == mPeople.end())
		return false;
	return true;
}

void cCase::Sort()
{

	for (pit i = mPeople.begin(); i != mPeople.end(); i++) //Put in decending order according to rank
	{
		for (pit j = i + 1; j != mPeople.end(); j++)
		{
			if (i->GetRanking() < j->GetRanking())
				iter_swap(i, j);
		}
	} 

	pit it = mPeople.begin();
	while (it != mPeople.end()) //Add to respective bosses' employees vector & remove from cases' people vector
	{
		if (it->GetBoss() != "NULL")
		{
			pit tBoss = Find(it->GetBoss());
			if (IsValid(tBoss))
			{
				tBoss->Hire(*it);
				mPeople.erase(it);
				it = mPeople.begin();
				continue;
			}
		}
		it++;
	}

	it = mPeople.begin(); //Get top (and only) person in people vector

	it->SortEmployees();
}

ostream& operator<<(ostream &output, cCase& in_Case)
{
	pit it = in_Case.mPeople.begin();
	output << it->GetName() << " (" << it->GetJob() << ") " << it->GetYear() << endl; //Print top person out

	output << it->PrintEmployees(1);

	return output;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//cPerson.cpp

#include "cPerson.h"



cPerson::cPerson(const string in_Name, const string in_Boss, const string in_Job, const int in_Year) : mName(in_Name), mBoss(in_Boss), mJob(in_Job), mYear(in_Year) 
{
	if (mJob == "CEO") mRanking = 1;
	else if (mJob == "VP") mRanking = 2;
	else if (mJob == "Director") mRanking = 3;
	else if (mJob == "Manager") mRanking = 4;
	else mRanking = 5;
}

void cPerson::Hire(cPerson in_Person)
{
	mEmployees.push_back(in_Person);
}

bool cPerson::operator<(const cPerson& rhs) const //used for sort
{
	for (int i = 0; i < this->GetName().size(); i++) //increment letter to check, start with first letter
	{
		if (this->GetName()[i] == rhs.GetName()[i]) //if letters are the same
			continue;

		if (this->GetName()[i] < rhs.GetName()[i]) //if this' ith letter of their name comes before rhs' ith letter of their name
			return true;
		else
			return false;
	}
}

void cPerson::SortEmployees()
{
	sort(mEmployees.begin(), mEmployees.end()); //alphabetize 

	for (pit it = mEmployees.begin(); it != mEmployees.end(); it++)
		it->SortEmployees(); 
}

string cPerson::PrintEmployees(int in_Level)
{
	string output;

	for (pit it = mEmployees.begin(); it != mEmployees.end(); it++)
	{
		for (int i = 0; i < in_Level; i++)
			output += "-";

		stringstream ss;
		ss << it->GetYear();
		output += it->GetName() + " (" + it->GetJob() + ") " + ss.str() + "\n";

		output += it->PrintEmployees(in_Level + 1);
	}
	return output;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//cPerson.h

#ifndef CLASS_PERSON_H
#define CLASS_PERSON_H

#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <sstream>

using std::string;
using std::vector;
using std::iterator;
using std::sort;
using std::stringstream;


class cPerson
{
	typedef vector<cPerson>::iterator pit;
public:
	cPerson(const string in_Name, const string in_Boss, const string in_Job, const int in_Year);

	void Hire(cPerson in_Person);

	string GetName() const { return mName; }
	string GetBoss() const { return mBoss; }
	string GetJob() const { return mJob; }
	int GetYear() const { return mYear; }
	int GetRanking() const { return mRanking; }

	bool operator<(const cPerson& rhs) const;

	void SortEmployees();

	string PrintEmployees(int in_Level);

private:
	string mName, mBoss, mJob;

	int mYear, mRanking;

	vector<cPerson> mEmployees;

};

#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//cTokenizer.cpp

#include "cTokenizer.h"

const char* const DELIMITERS = " ,-";
const int MAX_CHARS_PER_LINE = 5120;
const int MAX_TOKENS_PER_LINE = 200;


cTokenizer::cTokenizer(string in_Filename, string out_Filename, int in_Cases) : mInFile(in_Filename), mOutFile(out_Filename), mCaseNum(in_Cases)
{
	mCases = new cCase[in_Cases];
}

cTokenizer::~cTokenizer()
{
	delete[] mCases;
}

bool cTokenizer::Tokenize()
{
	ifstream tFile(mInFile.c_str());

	if (!tFile.good()) return false;

	string trash;

	getline(tFile, trash); //remove case number

	for (int i = 0; i < mCaseNum; i++)
	{
		if (!tFile.eof())
		{
			int n = 0;

			char buf[MAX_CHARS_PER_LINE] = {};
			tFile.getline(buf, MAX_CHARS_PER_LINE); //get case

			char* tTokens[MAX_TOKENS_PER_LINE] = {};

			tTokens[0] = strtok(buf, DELIMITERS); //get first token

			if (tTokens[0]) // zero if line is blank
			{

				for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
				{
					tTokens[n] = strtok(0, DELIMITERS); // subsequent tokens from same case
					if (!tTokens[n]) break; // no more tokens
				}
			}

			for (int j = 0; j < n; j += 4) //0 name, 1 boss, 2 job, 3 year
				mCases[i].Add(cPerson(tTokens[j], tTokens[j + 1], tTokens[j + 2], atoi(tTokens[j + 3])));

		}
	}
	tFile.close();
	return true;
}


bool cTokenizer::Write()
{
	ofstream tFile(mOutFile);

	if (!tFile.good())
		return false;

	for (int i = 0; i < mCaseNum; i++)
	{
		mCases[i].Sort();

		tFile << "Case #" << i + 1 << endl;

		tFile << mCases[i];
	}
	tFile.close();

	return true;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//cTokenizer.h

#ifndef CLASS_TOKENIZER_H
#define CLASS_TOKENIZER_H

#include <fstream>

#include "cCase.h"
#include "cPerson.h"

using std::ifstream;
using std::ofstream;

class cTokenizer
{
public:
	cTokenizer(string in_Filename, string out_Filename, int in_Cases);
	~cTokenizer();

	bool Tokenize();

	bool Write();


private:
	string mInFile, mOutFile;
	cCase* mCases;
	int mCaseNum;

};

#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <fstream>
#include <iostream>
#include <string>

#include "cTokenizer.h"

using namespace std;

const char* const IN_FILE_NAME = "org_chart.in";
const char* const OUT_FILE_NAME = "org_chart.out";

int main()
{

	ifstream qFile(IN_FILE_NAME);
	ofstream outputWriter(OUT_FILE_NAME);
	string qLine;
	int num_cases;
	
	// make sure we can read file
	if (!qFile.good())
	{
		cout << "File failed to open" << endl;
		return 1; // exit if file not found
	}
		
	// read first line to get number of test cases
	getline(qFile, qLine);

	// convert string to int and set to variable num_cases
    num_cases = atoi(qLine.c_str());

	qFile.close();

	cTokenizer Tokenizer(IN_FILE_NAME, OUT_FILE_NAME, num_cases);
	Tokenizer.Tokenize();

	Tokenizer.Write();


	return 0;
}
Here's the file that is supposed to be parsed along with the correct file
1
2
3
4
3
Fred,Karl,Technician,2010--Karl,Cathy,VP,2009--Cathy,NULL,CEO,2007
Adam,Karl,Technician,2010--Bob,Karl,Technician,2012--Cathy,Karl,Technician,2013--Karl,Nancy,Manager,2009--Wendy,Nancy,Technician,2012--Nancy,NULL,CEO,2007
Fred,Cathy,Technician,2010--Nancy,Wendy,Technician,2013--Vince,Karl,VP,2009--Bob,Susan,Manager,2010--Adam,Susan,Technician,2011--Ned,Wendy,Technician,2009--Liam,Wendy,Technician,2007--Dan,Ryan,Director,2008--Carl,Susan,Technician,2010--Ed,Wendy,Technician,2007--Patty,Wendy,Technician,2008--Tom,Susan,Technician,2011--Sam,Susan,Technician,2008--Lilly,Jack,Manager,2007--Amy,Jill,Technician,2012--Wendy,Dan,Manager,2010--Cathy,Vince,Director,2006--Susan,Vince,Director,2009--Betty,Cathy,Manager,2012--Oscar,Betty,Technician,2006--Jill,Dan,Manager,2012--Katie,Jill,Technician,2007--Paul,Bob,Technician,2007--Ryan,Karl,VP,2007--Mary,Lilly,Technician,2013--Matt,Jill,Technician,2007--Karl,NULL,CEO,2005--Jack,Ryan,Director,2009

Solution
Case #1

Cathy (CEO) 2007

-Karl (VP) 2009

--Fred (Technician) 2010

Case #2

Nancy (CEO) 2007

-Karl (Manager) 2009

--Adam (Technician) 2010

--Bob (Technician) 2012

--Cathy (Technician) 2013

-Wendy (Technician) 2012

Case #3

Karl (CEO) 2005

-Ryan (VP) 2007

--Dan (Director) 2008

---Jill (Manager) 2012

----Amy (Technician) 2012

----Katie (Technician) 2007

----Matt (Technician) 2007

---Wendy (Manager) 2010

----Ed (Technician) 2007

----Liam (Technician) 2007

----Nancy (Technician) 2013

----Ned (Technician) 2009

----Patty (Technician) 2008

--Jack (Director) 2009

---Lilly (Manager) 2007

----Mary (Technician) 2013

-Vince (VP) 2009

--Cathy (Director) 2006

---Betty (Manager) 2012

----Oscar (Technician) 2006

---Fred (Technician) 2010

--Susan (Director) 2009

---Adam (Technician) 2011

---Bob (Manager) 2010

----Paul (Technician) 2007

---Carl (Technician) 2010

---Sam (Technician) 2008

---Tom (Technician) 2011
Topic archived. No new replies allowed.