Hello pnwadike99,
I hope you did not take what I said the wrong way and think that you have to rewrite the program.
Sometimes just knowing what is wrong or where it is going wrong is the first step to fixing it.
Turns out that the program will work the way that you have written it with a few changes.
Such as:
1 2 3 4 5 6 7 8 9 10
|
// open input file
ifstream fin(usersFile);
//fin.open(usersFile.c_str());
if (!fin)
{
std::cerr << "\n File \"" << usersFile << "\" did not open\n";
return 1;
}
|
Your code:
if (!fin.good()) throw "I/O error";
. It would compile, but crash at runtime. The above code is more often used to achieve the same purpose. Line 2 allows you to define the file stream and open the file at the time the object is constructed. If your compiler is using the 2011, or later, standards a "std::string" will work. It does not need to be converted to a C string unless you are using pre-2011 standards.
While looking into "throw" to figure out what was going wrong I came to this:
https://en.cppreference.com/w/cpp/language/except_spec Under Syntax notice the comments on the right. You will notice that something is used to deal with the exception that is being thrown. and the examples here
https://en.cppreference.com/w/cpp/language/throw all use try/catch to deal with handling the exception.
This code may work for you and you may be including a header file I do not know about.
Jumping ahead a bit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
bool checkDuplicate(string runName, string* tempName, int n)
{
// data
// tempName is the list of non-duplicate names
// n is the size counter of the list
// runName is the name being checked
//check if duplicate name
for (int i = 0; i < n; i = i + 1)
{
if (runName == tempName[i])
{
return true;
}//if
}//for i
return false;
} // checkDuplicate
|
You will notice I did not define the variables the way that you did. They are not really needed. Define "i" in the for loop as it should be and instead of defining and setting "result" just return true or false. Most of the time it is better to use what you have available than to over code what you do not need.
In the for loop in "main" start with
for (int i = 0; i < MAX_RNDNAMES && getline(fin, runName); i++)
This way either side of AND (&&) can cause the for loop to fail. Plus you get the read out of the way before you continue with the for loop.
Inside the for loop:
1 2 3
|
holdName = runName;
changeNow(runName);
|
Now "runName" has a proper value for line 1 and for line 3 there is something to work with.
In the function that is called:
1 2 3 4 5 6 7 8 9 10
|
// convert
void changeNow(string& runName)
{
for (size_t q = 0; q < runName.length(); q++)
{
runName[q] = toupper(runName[q]);
}
//return s; // <--- Not needed now and was never captured when the function returns to "main".
} // convert
|
I changed this to a "void" function because there is no need to return anything. Passing the variable by reference is the better way to pass a "std::string" and any changes made in the function are reflected back in "main".
Although you have the ability to change the variable name in the function parameter. Most times it is best to use the same name the was sent to the function for clarity. Also defining the variable in the functions parameter is the same as defining it after the opening {. It becomes local to the function having function scope until the closing } looses scope and returns scope back to where it was called from.
Now comes the interesting part and a good example of use what you have.
bool result = checkDuplicate(runName, tempName, nrndNames);
. Originally you defined the variable and initialized it to "false", but never changed it anywhere. This way if the function returns "true" the if/else if statements will work properly.
The first if statement is not needed because it is handled in the for condition.
Instead of
if (result = false)
you can write that as
if (!result)
. And if checking for true you can say
if (result)
. Since the if condition is evaluated and converted into a bool type answer using a variable already defined as a "bool" means less work and you are using what you have.
The last
else if (tempName[nrndNames].length() == 0)
Tends to be a duplicate of what is above it and in all my testing I never reached this part. I believe it can be removed and should not cause any problem. At the very least comment it out and see what happens. You may have had an ides for its need that I have not seen yet.
The sort code is about 99% corret. The actual sorting works it is ate for loops that are a problem.
1 2 3 4
|
for (int j = 0; j < nrndNames; j++) //outer loop traverse
{
for (int o = j + 1; o < nrndNames; o++)
{
|
First off "i", "j" and "k" are the most often used variables in for loops. Sometimes you can still give them a better name.
The outer for loop goes from 0 to 9 which is fine, but the inner for loop goes from "j + 1 or 1 to 9. The problem is that when "j + 1" equals 10 the condition would be "o < nrndNames" or 10 < 10. The for loop fails before you check the last name in the array.
The hint here is that "o = J + 1", so "j" can not be greater than 8. This is based on "nrndNames" having a value of 10, but the principal still applies if "nrndNames" is less than 10.
With these changes and the file I used I got this output:
Unsorted List
--------------------
Enrique Thomas
Londyn White
Maverick Chan
Susan Dixon
Ariella Leonard
Zaniyah Shah
Jaylah Nielsen
Rolando Roy
Devyn Cobb
Eliezer Mcpherson
Sorted List
--------------------
Ariella Leonard
Devyn Cobb
Eliezer Mcpherson
Enrique Thomas
Jaylah Nielsen
Londyn White
Maverick Chan
Rolando Roy
Susan Dixon
Zaniyah Shah
|
The name "Susan Dixon" is in the input file 3 times to test for duplicates. Even tried it on a file containing 500 names and it only took the first 10, but there are no duplicates in this file.
I am not sure if I have mentioned this, but if I have not. A good source of reference is
https://en.cppreference.com/w/ At least this is kept up to date where the reference section here is good, but needs updated.
Andy