2 issues I cannot figure out

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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <algorithm>
using namespace std;

// global constants
const int MAX_CUSTOMERS = 1000;
unsigned int maxStringSize = 8;
unsigned int maxTempSize = 3;
const int NOT_FOUND = -1;

// function prototypes
bool OpenAndValidateInputFile (ifstream& textIn);
void ReadAndStoreInputFile (ifstream& textIn, string Customer[], double Charge[], int& counter);
void SelectionSort (string Customer[], double Charge [], int counter);
bool OpenAndValidateOutputFile (ofstream& textOut);
void WriteToOutputFile (ofstream& textOut, string Customer [], double Charge [], int counter);
bool GetUserInput (string &userCustomerCode, int counter, string Customer []);
string ValidateCustomerCode (string& userCustomerCode, int counter, string Customer []);
void BinarySearchForCustomerCode (string userCustomerCode, int counter, string Customer [], double Charge []);

int main()
{
	// local variables
	ifstream textIn;														// input file stream variable
	ofstream textOut;
	string Customer [MAX_CUSTOMERS];
	double Charge [MAX_CUSTOMERS];
	int counter = 0;
	string userCustomerCode;

	if (OpenAndValidateInputFile (textIn))
	{
		ReadAndStoreInputFile (textIn, Customer, Charge, counter);

		SelectionSort (Customer, Charge, counter);

		if (OpenAndValidateOutputFile (textOut))
		{
			WriteToOutputFile (textOut, Customer, Charge, counter);
		}
		else
		{
			return 1;
		}
		
		while (GetUserInput (userCustomerCode, counter, Customer))
		{
			ValidateCustomerCode (userCustomerCode, counter, Customer);

			BinarySearchForCustomerCode (userCustomerCode, counter, Customer, Charge);
		}

		system ("PAUSE");
		return 0;
	}
	else
	{
		return 1;
	}

	// CLOSE FILE!!!!!!
}

bool OpenAndValidateInputFile (ifstream& textIn)
{
    // open input file
    textIn.open ("CUSTOMERS.TXT");

	// check if file opens successfully
	// if not, print a warning and exit program from main with a return code 1
	if (!textIn.is_open ())
	{
		return false;
	}
	else
	{
		return true;
	}
}// end OpenAndValidateInputFile

void ReadAndStoreInputFile (ifstream& textIn, string Customer[], double Charge[], int& counter)
{
	string customerCode;													// customer ID code - unique 4 capital letters followed by 4 digits
	double utilityCharge = 0;												// utility charge per unit

	// while file is still readable, and peek does not find end-of-file
	while (textIn.good () && textIn.peek () != EOF)
	{
		// read in data from CUSTOMERS.TXT
		textIn >> customerCode;
		textIn >> utilityCharge;

		// if the file contains too many lines of data, stop reading data and issue warning
		if (counter >= MAX_CUSTOMERS)
		{
			cout << "Error: file contains too many lines of data" << endl;
		}
		else
		{
			Customer [counter] = customerCode;

			Charge [counter] = utilityCharge;

			counter++;
		}
			
		// read newline
		textIn.get ();
	}
}// end ReadAndStoreInputFile

void SelectionSort (string Customer [], double Charge [], int counter)
{
	// local variables
	int i;																	// integer place holder i
	int j;																	// integer place holder j
	int max;																// place holder for highest letter found for sort

	// setting parameter for i
	for (i = 0; i < counter - 1; i++)
	{
		max = i;

		// setting parameter for j
		for (j = i + 1; j < counter; j++)
		{
			// searching through array, and replacing lower value higher value if found
			if (Customer [j] > Customer [max])
			{
				max = j;
			}
		}

		if ( max != i ) 
		{	
			string tempString = Customer[i];
			Customer[i] = Customer[max];
			Customer[max] = tempString;

			// aligning Charge [] with Customer []
			double tempDouble = Charge[i];
			Charge[i] = Charge[max];
			Charge[max] = tempDouble;
		}
	}
} // end SelectionSort

bool OpenAndValidateOutputFile (ofstream& textOut)
{
    // open input file
    textOut.open ("SORTED.TXT");

	// check if file opens successfully
	// if not, print a warning and exit program from main with a return code 1
	if (!textOut.is_open ())
	{
		return false;
	}
	else
	{
		return true;
	}
}// end OpenAndValidateOutputFile

void WriteToOutputFile (ofstream& textOut, string Customer [], double Charge [], int counter)
{
	// write each instance to output file for Customer [] and Charge []
	for (int i = 0; i < counter; i++)
	{
		textOut << Customer [i] << showpoint << fixed << setprecision (2) << setw (8) << Charge [i] << endl;
	}
}// end WriteToOutputFile

bool GetUserInput (string &userCustomerCode, int counter, string Customer [])
{
	cout << "CUSTOMER CODES on file are: " << endl << endl;
	
	for (int i = 0, lines = 0; i < counter; ++i)
	{
		cout << setw (11) << Customer [i];

		if (++lines > 5)
		{
			lines = 0;
			cout << endl;
		}
	}

	cout << endl << endl;

	cout << "Enter a customer code (or E to exit): ";

	return (cin >> userCustomerCode && userCustomerCode != "E" && userCustomerCode != "e");
}// end GetUserInput

string ValidateCustomerCode (string& userCustomerCode, int counter, string Customer [])
{
	// local variables
	string tempA;
	string tempB;

	cout << endl;

	tempA = userCustomerCode.substr (0, 4);
	tempB = userCustomerCode.substr (4, 4);

	if (userCustomerCode.length () < maxStringSize)
	{
		cout << "Invalid Entry! Customer code " << userCustomerCode << " is too short." << endl;
		cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
	}
	else if (userCustomerCode.length () > maxStringSize)
	{
		cout << "Invalid Entry! Customer code " << userCustomerCode << " is too long." << endl;
		cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
	}
	else if (!isalpha (tempA [maxTempSize]))
	{
		cout << "Invalid Entry! Customer Code " << userCustomerCode << " is formatted incorrectly." << endl;
		cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
	}
		
	for (unsigned int i = 0; i < tempB.length (); i++)
	{
		if (!isdigit (tempB [i]))
		{
			cout << "Invalid Entry! Customer Code " << userCustomerCode << " is formatted incorrectly." << endl;
			cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
		}
	}

	for (unsigned int i = 0; i < tempA.length (); i++)
	{
		tempA [i] = toupper (tempA [i]);
	}

	return userCustomerCode = tempA + tempB;
}// end ValidateCustomerCode

void BinarySearchForCustomerCode (string userCustomerCode, int counter, string Customer [], double Charge [])
{
	int infoPlace = NOT_FOUND;
	int high;
	int low;
	int middle;

	low = 0;
	high = counter - 1;

	while ((low <= high) && (infoPlace == NOT_FOUND))
	{
		middle = (low + high) / 2;

		if (userCustomerCode > Customer [middle])
		{
			high = middle - 1;
		}
		else if (userCustomerCode < Customer [middle])
		{
			low = middle + 1;
		}
		else 
		{
			infoPlace = middle;
		}
	}

	if (infoPlace >= low)
	{
		cout << "Customer " << Customer [infoPlace] << " was charged $"
			 << Charge [infoPlace] << "." << endl << endl;
	}
	else
	{
		cout << "Customer code " << userCustomerCode << " is not in the database." << endl << endl;
	}
}
This is my entire program. The two issues I am having, that I have not been able to figure out in the past 3 hours are:
1) I cannot get the results from the Binary Search (lines 274 - 279) to appear ONLY when a valid customer code has been entered (i.e. only if the customer code is entered in the correct format. whether it exists or not, should be displayed since that is related to the search, but currently it shows EVERY time a customer code is written, even after an error is displayed for format being incorrect.

2) When I test my "validateCustomerCode", if i enter something in the incorrect format, it shoots out 10 different errors, not just one.
i.e. correct format should be AAAA1111 (four letters followed by four numbers). If i enter a234jj83 it spits out a number of errors, and then prompts the user to try again, rather than just one error...

Any suggestions?
Would you please provide your CUSTOMERS.TXT?

One suggestion; you can simplify your OpenAndValidateInputFile() to this:
1
2
3
4
5
6
7
8
9
10
// open input file
textIn.open ("CUSTOMERS.TXT");

// check if file opens successfully
// if not, print a warning and exit program from main with a return code 1
if (!textIn) // this is the same as "!textIn.good()". The goodbit symbolizes, that the object has no errors.
             // there is also a failbit, badbit and eofbit. If any of those are set, then the object is not "good" anymore.
    return false;

return true;


Hope that's a nice tip.
My sincerest apologies, I hope you are still able to help! I was not able to get online and have not checked back here until now. I am still in need of assitance for the above two problems.
I am looking over the suggestion you gave me as well, to see if it is any easier.
Here is my CUSTOMERS.TXT file.
GREG2236 333.77
ANGE9271 109.48
TROY6385 178.47
VINC1347 65.02
FRAN5782 312.43
JENN0928 112.98
JIMM1942 98.12
QUIN4398 39.97
LYNS1028 132.77
NORI4389 111.92
I am taking a look at it.
1
2
3
4
5
// global constants
const int MAX_CUSTOMERS = 1000;
unsigned int maxStringSize = 8; // You better const it :>
unsigned int maxTempSize = 3; // And this.
const int NOT_FOUND = -1;


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
string ValidateCustomerCode (string& userCustomerCode, int counter, string Customer [])
// You don't use counter in this function. Just as a note.
{
	// local variables
	string tempA;
	string tempB;

	cout << endl;

	tempA = userCustomerCode.substr (0, 4);
	tempB = userCustomerCode.substr (4, 4);

	if (userCustomerCode.length () < maxStringSize)
	{
		cout << "Invalid Entry! Customer code " << userCustomerCode << " is too short." << endl;
		cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
	}
	else if (userCustomerCode.length () > maxStringSize)
	{
		cout << "Invalid Entry! Customer code " << userCustomerCode << " is too long." << endl;
		cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
	}
	else if (!isalpha (tempA [maxTempSize])) // You only check for the last character, not all 4.
                                             // So 123a1234 is still valid.
	{
		cout << "Invalid Entry! Customer Code " << userCustomerCode << " is formatted incorrectly." << endl;
		cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
	}

	for (unsigned int i = 0; i < tempB.length (); i++)
	{
		if (!isdigit (tempB [i]))
		{
			cout << "Invalid Entry! Customer Code " << userCustomerCode << " is formatted incorrectly." << endl;
			cout << "Must be 4 letters followed by 4 digits. Try again." << endl;
			break; // As soon as the first error is found, break the for-loop,
                   // so you don't output further possible errors.
		}
	}
Last edited on
And for problem one you can define a constant like INVALID_CODE or something and return it in ValidateCustomerCode() if an error has been found. Then, in your main(), you check if the returned string equals INVALID_CODE and if not, call BinarySearchForCustomerCode().

The first member function substr() in ValidateCustomerCode() also throws an out_of_range exception, if you enter less than 4 characters. A solution could be to check if userCustomerCode is even the correct length before you go any further. You can return INVALID_CODE sooner then.

Hope you understand what I mean.
Last edited on
I am working on it now, hopefully, if I have any questions left, I will get them to you soon enough. Thanks for your input!! I will post again soon enough letting you know if i figured it out, or need further assistance!
I am working on figuring out how to fix the error you found in line 23.
However, line 36 - I am NOT allowed to use break to exit a loop. I am only allowed to use the break command to end a switch statement. That's why I am so lost in figuring out how to get those errors to stop...
Ok, I fixed the part at line 23. So now, it checks every letter, not just the last one.

Moving on to your next comment...
So, I have done all that you said to do...and for some reason...IT WORKS PERFECTLY!!! Haha, all issues seem to have been taken care of :) I really do appreciate your help!
I am so glad I could help! :)
Don't forget to mark the thread as "solved" :)
Topic archived. No new replies allowed.