Splitting string from getline

Background: I have a file with first name, last name, pay rate, hours worked, overtime rate, tax rate, and other deductions. Basicaly I am needing to produce a standard paystub. My problem is that when I read the file in some of the lines do not have all of the information and when I split my string up and assign the variables I can not get it to stop when there is no more information in the line (as in only f name, l name, pay rate, and hours worked). In that specific example the value in hours worked is also placed in all the other variables.

I have initialized the double variables = 0, and at the end of my loop I reset them to 0.

I have used cout << to make sure that my string is being read correctly which it is. This is an example of my code to read one of the lines (I have a loop also that works perfectly).

getline(infile, mystring);

len = mystring.find(" ");
firstName = mystring.substr(0, len);
mystring = mystring.erase(0, len + 1);

len = mystring.find(" ");
lastName = mystring.substr(0, len);
mystring = mystring.erase(0, len + 1);

etc...with the variable changing as appropriate.

I am not looking for a cheat to this problem but have about broken my brain trying to figure this out. If anyone has a good idea how to get it to stop assigning values to the variables that do not have info I would greatly appreciate it.
post your code and your input file.

without seeing that I"m guessing but since the names will be different lengths, you may be able to use size to find out the length of each line, subtract size() firstName, lastName and so on until the size is 0. then go to the next line, or place 0 in the fields for the missing variables.

There are probably easier ways, just first thing that popped in my head.
Such as if your input file has comma's or something else between the spaces.

http://www.cplusplus.com/reference/string/string/size/
this is my code and the file I am reading from (not sure if I can attach it so I will copy and paste it here. It is named EmployeeInfo.txt in the code if you copy and save it on your CP). Also there is an outfile but I am not using it yet, just cout to print to console until I can get the desired results.

Mickey Mouse 5.75 50
Donald Duck 12.50 23 2.0 .15 100
Daphy Duck 40 40 1.5 .12 400
Dudly Dooright 25.00 45 2.0 .15 0
Foghorn Leghorn 25.00 50 2.5 .15
Fat Albert 25.50 55 2.0 .12 200
Elroy Jetson 8.15 40
Elmer Fudd

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>

using namespace std;	// Declare namespace

void output(string, string, double, double, double, double, double, double);
double netPay(double, double, double, double, double);

void main()
{
	// Declare variables
	string firstName;
	string lastName;
	double basicRate = 0;
	double hoursWorked = 0;
	double overtimeRate = 0;
	double taxRate = 0;
	double otherDeductions = 0;
	double net;
	int len = 0;

	// Declare variables
	ifstream infile;
	string mystring;
	ofstream outfile;


	infile.open("EmployeeInfo.txt");
	outfile.open("PayStub.txt");

	if (!infile)
	{
		cout << "Cannot open input file. Please check file." << endl;
	}

	getline(infile, mystring);

	len = mystring.find(" ");
	firstName = mystring.substr(0, len);
	mystring = mystring.erase(0, len + 1);
	
	len = mystring.find(" ");
	lastName = mystring.substr(0, len);
	mystring = mystring.erase(0, len + 1);
	
	len = mystring.find(" ");
	basicRate = atof(mystring.substr(0, len).c_str());
	mystring = mystring.erase(0, len +1);
	
	len = mystring.find(" ");
	hoursWorked = atof(mystring.substr(0, len).c_str());
	mystring = mystring.erase(0, len + 1);
	
	net = netPay(basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions);
	output(firstName, lastName, basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions, net);

	while (!infile.eof())
	{			
		getline(infile, mystring);

		len = mystring.find(" ");
		firstName = mystring.substr(0, len);
		mystring = mystring.erase(0, len + 1);
		
		len = mystring.find(" ");
		lastName = mystring.substr(0, len);
		mystring = mystring.erase(0, len + 1);

		len = mystring.find(" ");
		basicRate = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

		len = mystring.find(" ");
		hoursWorked = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

		len = mystring.find(" " );
		overtimeRate = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

		len = mystring.find(" ");
		taxRate = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);
		
		len = mystring.find(" ");
		otherDeductions = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

		net = netPay(basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions);
		output(firstName, lastName, basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions, net);

		double basicRate = 0;
		double hoursWorked = 0;
		double overtimeRate = 0;
		double taxRate = 0;
		double otherDeductions = 0;
	}

	infile.close();
	outfile.close();
}

double netPay(double basicRate, double hoursWorked, double overtimeRate, double taxRate, double otherDeductions)
{
	double gross;

	if (hoursWorked <= 40)
	{
		gross = basicRate * hoursWorked;
		
		double net = gross - (gross * taxRate) - otherDeductions;
		return net;
	}
	else
	{
		gross = (basicRate * 40) + ((hoursWorked - 40) * (overtimeRate * basicRate));
		double net = gross - (gross * taxRate) - otherDeductions;
		return net;
	}
}

void output(string firstName, string lastName, double basicRate, double hoursWorked, double overtimeRate, 
	double taxRate, double otherDeductions, double net)
{
	cout << fixed << showpoint << setprecision(2);
	cout << "___________________________" << endl;
	cout << "|" << setw(12) << left << " First Name" << "| " << setw(11) << firstName << "|" << endl;
	cout << "___________________________" << endl;
	cout << "|" << setw(12) << left <<  " Last Name" << "| " << setw(11) << left << lastName << "| " << endl;
	cout << "__________________________________________________________________" << endl;
	cout << "|" << setw(12) << left << " Basic Rate" << "|" << setw(12) << " Hours" << "|" << setw(12) << " O/T Rate" <<
		"|" << setw(12) << " Tax Rate" << "|" << setw(12) << " Other" << "|" << endl;
	cout << "__________________________________________________________________" << endl;
	cout << "| " <<setw(11) << left << basicRate << "| " << setw(10) << hoursWorked << " " << "| " << setw(11) << overtimeRate <<
		"| " << setw(11) << taxRate << "| " << setw(11) << otherDeductions << "|" << endl;
	cout << "__________________________________________________________________" << endl;
	cout << "| " <<setw(50) << left << "Net Pay:" << "| " << setw(11) << net << "|" << endl;
	cout << "__________________________________________________________________" << endl << endl << endl;
}
Last edited on
Don't have time to provide a fix but I can assist with the problem determination. Run this and you'll see what/where the problem is.

*EDIT*
updated to show
size len --test- mystring.

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>

using namespace std;	// Declare namespace

void output(string, string, double, double, double, double, double, double);
double netPay(double, double, double, double, double);

int main()
{
	// Declare variables
	string firstName;
	string lastName;
	double basicRate = 0;
	double hoursWorked = 0;
	double overtimeRate = 0;
	double taxRate = 0;
	double otherDeductions = 0;
	double net;
	int len = 0;

	// Declare variables
	ifstream infile;
	string mystring;
	ofstream outfile;


	infile.open("out1.txt");
	outfile.open("out2.txt");

	if (!infile)
	{
		cout << "Cannot open input file. Please check file." << endl;
	}

	getline(infile, mystring);

	len = mystring.find(" ");
	firstName = mystring.substr(0, len);
	mystring = mystring.erase(0, len + 1);
	
	len = mystring.find(" ");
	lastName = mystring.substr(0, len);
	mystring = mystring.erase(0, len + 1);
	
	len = mystring.find(" ");
	basicRate = atof(mystring.substr(0, len).c_str());
	mystring = mystring.erase(0, len +1);
	
	len = mystring.find(" ");
	hoursWorked = atof(mystring.substr(0, len).c_str());
	mystring = mystring.erase(0, len + 1);
	
	net = netPay(basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions);
	output(firstName, lastName, basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions, net);

	while (!infile.eof())
	{			
		getline(infile, mystring);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" ");
		firstName = mystring.substr(0, len);
		mystring = mystring.erase(0, len + 1);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" ");
		lastName = mystring.substr(0, len);
		mystring = mystring.erase(0, len + 1);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" ");
		basicRate = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" ");
		hoursWorked = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" " );
		overtimeRate = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" ");
		taxRate = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

        cout << mystring.size() << " " << len << " --Test-- "  << mystring << endl;// Test
		len = mystring.find(" ");
		otherDeductions = atof(mystring.substr(0, len).c_str());
		mystring = mystring.erase(0, len + 1);

		net = netPay(basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions);
		output(firstName, lastName, basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions, net);

		double basicRate = 0;
		double hoursWorked = 0;
		double overtimeRate = 0;
		double taxRate = 0;
		double otherDeductions = 0;
	}

	infile.close();
	outfile.close();
}

double netPay(double basicRate, double hoursWorked, double overtimeRate, double taxRate, double otherDeductions)
{
	double gross;

	if (hoursWorked <= 40)
	{
		gross = basicRate * hoursWorked;
		
		double net = gross - (gross * taxRate) - otherDeductions;
		return net;
	}
	else
	{
		gross = (basicRate * 40) + ((hoursWorked - 40) * (overtimeRate * basicRate));
		double net = gross - (gross * taxRate) - otherDeductions;
		return net;
	}
}

void output(string firstName, string lastName, double basicRate, double hoursWorked, double overtimeRate, 
	double taxRate, double otherDeductions, double net)
{
	cout << fixed << showpoint << setprecision(2);
	cout << "___________________________" << endl;
	cout << "|" << setw(12) << left << " First Name" << "| " << setw(11) << firstName << "|" << endl;
	cout << "___________________________" << endl;
	cout << "|" << setw(12) << left <<  " Last Name" << "| " << setw(11) << left << lastName << "| " << endl;
	cout << "__________________________________________________________________" << endl;
	cout << "|" << setw(12) << left << " Basic Rate" << "|" << setw(12) << " Hours" << "|" << setw(12) << " O/T Rate" <<
		"|" << setw(12) << " Tax Rate" << "|" << setw(12) << " Other" << "|" << endl;
	cout << "__________________________________________________________________" << endl;
	cout << "| " <<setw(11) << left << basicRate << "| " << setw(10) << hoursWorked << " " << "| " << setw(11) << overtimeRate <<
		"| " << setw(11) << taxRate << "| " << setw(11) << otherDeductions << "|" << endl;
	cout << "__________________________________________________________________" << endl;
	cout << "| " <<setw(50) << left << "Net Pay:" << "| " << setw(11) << net << "|" << endl;
	cout << "__________________________________________________________________" << endl << endl << endl;
}

Last edited on
Yeah the Mickey Mouse one works because I did that outside the loop to ensure the program runs at least once, and I only was grabbing the first four since I knew that line was only four. I will modify it as needed for all lines after I get the others working correctly.

The line for Foghorn Leghorn (no otherDeductions) and for Elroy Jetson (no overtimeRate, taxRate or otherDeductions) are the ones that populate those variables with what ever the last one before it had. I need it to only populate the variable with info from the file or else it should remain a 0 as it is initialized.

Thanks for your help, I have been killing my brain trying what seems like a thousand different ways to get it working.
*EDIT*
updated my above post to show
size len --test- mystring.

added len...

The problem is it's not clearing the "len" of mystring if that is the last value because it appears to be -1.

The problem doesn't appear when reading for Elmer Fudd because Fudd does not work for a double but the problem is still present.

I'm sure there are several ways to fix.
Read in the data differently.
measure the string size or value.
or maybe change the behavior if "len = -1"


I have not seen this line before
mystring = mystring.erase(0, len + 1);

If you can explain how it works that might save me time from figuring it out.
I understand all of it but the "len+1"

I see len = mystring.find(" "); above. I'm guessing that is some built in function to get length, like how size works.

Last edited on
There was a lot of redundancy in that program, here's how it can be done using the more natural approaches:

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
int main()
{
    ifstream infile("EmployeeInfo.txt");
    if (!infile)
    {
        cout << "Cannot open input file. Please check file.\n";
        return 1;
    }
    string mystring;
    while( getline(infile, mystring) )
    {
        istringstream buf(mystring);
        string firstName;
        string lastName;
        double basicRate = 0;
        double hoursWorked = 0;
        double overtimeRate = 0;
        double taxRate = 0;
        double otherDeductions = 0;
        buf >> firstName >> lastName >> basicRate
            >> hoursWorked >> overtimeRate
            >> taxRate >> otherDeductions;

        double net = netPay(basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions);
        output(firstName, lastName, basicRate, hoursWorked, overtimeRate, taxRate, otherDeductions, net);
    }
}
Last edited on
@Sam

The line mystring = mystring.erase(0, len +1); is changing the mystring variable to equal mystring where I erase for "index" 0 to len +1. I added the + 1 to erase the trailing space so that when it next tries to fine the space it will not just find the one right after the len. If I don't add the +1 it will erase the first name from the string but the remaining string will then start with a space and therefore when I do the mystring.find(" ") it will always find the space at the begining of the line. I guess I could do something like mystring.find(1, " ") so that it will skip the first space, but will then add that space to the part I cut off and assign to the variable.

And the len = (mystring.find(" ") is just searching for the next space and will then assign that number of characters to the len value.

@Cubbi
I have not used the istringstream buf() method before, but will give it a try. It looks a whole lot better and more concise than what I have.

I just tried it out...very nice. It got exactly what I was looking for. I had tried something similar where I used infile >> firstName>>lastName etc... and it didn't work out right. I will do some research on the buf function.

Thanks a bunch for the info!!!
Glad to hear you got it working.
Topic archived. No new replies allowed.