New Problem, see recent post please!

I'm working on a function to open a file, and mostly it works. This is the code I have based on my example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void open(ifstream& fin, vector<Person>& people)
{
	fin.open("names.txt");
	Person aPerson;
	string tmp;
	stringstream ss;
	
	while(!fin.eof());
	{  
		getline(fin, aPerson.lastName,';');
  
		getline(fin, tmp,';');
		ss << tmp;  
		ss >> aPerson.firstName;
  		ss.str("");
  		ss.clear();
  		
  		getline(fin, tmp); 
  		ss << tmp;
  		ss >> aPerson.age;
  		
  		people.push_back(aPerson);
	}
}

The file loads, but not properly. If I have two names saved in the file like this:

Thornton;Billy;60
Fang;Wild;21

After the file is opened, it will display as:

Thornton Billy 60 21

It completely skips over the entire name of all following name entries and outputs all the ages. Anyone able to see what's wrong? Let me know if you need full code. It's kind of long.
Last edited on
you better declare the stringstream inside your loop to avoid headaches , and dont use eof like that, move ur getline(fin, aPerson.lastName,';') into the while loop like this:
1
2
3
4
5
while(getline(fin, aPerson.lastName,';'))
{

// Other codes here
}
Last edited on
Thanks Baze, I've been instructed by other members on the forum to do it that way. Not sure why my instructor insists on using the eof that way.

Unfortunately, by doing it that way in this circumstance, the display now outputs only one age, no names at all, and some random six digit number.
Ah, I got it. Here is the code I got working:

while(true)
{
getline(fin, aPerson.lastName,';');

getline(fin, aPerson.firstName,';');

getline(fin, tmp);
ss << tmp;
ss >> aPerson.age;

people.push_back(aPerson);

if (fin.eof()) break;
}

Stupid problem, easy solution.
Using .eof() is still wrong.
If you receive an invalid file you will end up with a big mess.
It should look like:
1
2
3
4
while(getline(...) && getline(...) && getline(...)) {
    if(istringstream(tmp)>>aPerson.age)
        people.push_back(aPerson);
}


You can also see it's a lot shorter.
NEVER use eof.

If he insists on using .eof(), kindly ask him to take another job.
This mistake is for beginners, because eof doesn't tell you if you have reached end of file, but if you HIT it.
Which means it is possible you may end up with an incorrect entry near the end of the file.
Last edited on
Thanks S G H, I'll give that a try. My only concern is not using syntax I was instructed to use, which could lead to losing marks.

For now, I have a new issue. Now that my input, save, open, and display functions are working properly, I need to write new ones that allow the user to input a name and have the program inform them whether or not that name is in the file, another to remove an entire entry, and a last to rearrange the entries alphabetically. Basically, I have no idea where to start with any of this. So far everything is a separate member of struct Person. I'm wondering if I have to do something like I did in the open function that loads the file, reconstructs a vector, then searches it to remove/find/sort.
It seems more appropriate to search in the actual vector... loading the file again is an overkill.

Basically...

1
2
3
4
5
6
7
8
9
10
11
Person* find_person_by_firstname(std::vector<Person>& persons, std::string const& name)
{
    for(int i=0; i<persons.size();++i)
    {
        if(persons[i].firstName == name)
            return &persons[i];
// If you want to be able to find "John" while searching "Jo"...
// if(persons[i].firstName.find(name)!=std::string::npos)
    }
    return 0;
}


You can erase an item with .erase(number), and sorting is a bit more difficult, maybe you can use std::sort?
Last edited on
Well I like that code a lot, mostly because it's very simple and easy to understand. My only question is regarding std:: prefixes. We've never used it in my course. I've seen it used quite a bit, but I've never been clear on what it means.
A lot of pre-made, standard code (vector, string, stringstream, cin, cout...) is inside a namespace.
Namespaces contain types, classes, functions, variables...
Namespaces are "separators", as in, things inside them are not publicly available by default.
The C++ standard namespace is called "std".
So, to be able to use vector, inside namespace std, there are multiple ways:
1. The direct: std::vector
2. The wide: using std::vector;
3. The wider: using namespace std;
The last two lines are usually written at the beginning and make "std::vector" available as "vector" as well.
Number 3 leads to namespace bloating, but you probably shouldn't care right now.

Which means, if you use "using namespace std", you can safely trim "std::" off of my stuff.
Side note: you can also create your own namespaces as well.
Thanks again. We do code using namespace std. I should have made that connection.

To follow up on your previous code, how could I go about using that in a switch statement with other statements? Basically what I want is something like:

if (found) cout << "Entry was found at: " << i << "." << endl;
else cout << "Entry not found." << endl;

I'm not sure how to make that work using a data type defined function. I usually use void.
1
2
3
4
5
Person* match = find_person_by_firstname(myvector, "John");
if(!match)
    cout << "No match found";
else
    cout << "Match found: " << match->firstName << ' ' << match->lastName;
Topic archived. No new replies allowed.