Issue with if/ofstream

Hi everyone, I've been working on a project for a class of mine to create an "address book" style program that is able to read and write to files. 90% of it works: it can read from the file, and write from the file. However, I'm encountering a small problem that is throwing me off. When I run my subroutine to "find" a contact name by using a .compare() function, it finds the contact, but will print all the information twice. Also, when I use my subroutine to "display all contacts", it will display all contacts, but it will display the contact that was added to the file last twice. I'll link my code now, if someone could give me insight as to what I'm doing wrong I would be very thankful.

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

class Contacts {
string firstName;
string lastName;
string emailID;
string Number;
string TargetName;


public:
string fileName;
ifstream readFrom;
ofstream writeTo;
Contacts() {
firstName = "";
lastName = "";
emailID = "";
Number = "";
}

void DisplayAllContacts() {

readFrom.open(fileName);
if(readFrom.fail()){
cout << "Cannot open file." << endl;
}

else{
while(!readFrom.eof()){
readFrom >> firstName >> lastName >> emailID >> Number;
cout << firstName << " " << lastName << " " << emailID << " " << Number << endl;
}
readFrom.close();
}
}

void createContact() {

writeTo.open(fileName, ios::app);

if(writeTo.is_open()){
cout << "Enter the first name: " << endl;
cin >> firstName;

cout << "Enter last name: " << endl;
cin >> lastName;

cout << "Enter email ID: " << endl;
cin >> emailID;

cout << "Enter phone number: " << endl;
cin >> Number;

writeTo << firstName << " " << lastName << " " << emailID << " " << Number << "\n";
writeTo.close();

firstName = "";
lastName = "";
emailID = "";
Number = "";
}
else {
cout << "Could not open " << fileName << endl;
}
}

void FindContact(){
readFrom.open(fileName);

if(readFrom.fail()){
cout << "Cannot open file." << endl;
}

else{
cout << "Enter name: " << endl;
cin >> TargetName;
cout << "---------------------------------------" << endl;
while(!readFrom.eof()){
readFrom >> firstName >> lastName >> Number >> emailID;
if(firstName.compare(TargetName)==0){
cout << "Found details about " << TargetName << endl;
cout << firstName << " "<< lastName << " " << Number << " " << emailID << endl;
}
}
readFrom.close();
}
}
};

int main()
{

Contacts ourAddressBook;

cout << "Name your file (must end in .txt): " << endl;
cin >> ourAddressBook.fileName;
ourAddressBook.writeTo.open(ourAddressBook.fileName, ios::app);

cout << "Creating new contact..." << endl;
cout << "-----------------------------------------" << endl;
ourAddressBook.writeTo.close();

while(1) {
cout <<"-----------------------------------------" << endl;
cout << "1: Search for contact." << endl;
cout << "2: Add contact." << endl;
cout << "3: Display all contacts. " << endl;
cout << "4: Exit." << endl;
int choice;
cin >> choice;

switch(choice) {
case 1: ourAddressBook.FindContact();
break;
case 2: ourAddressBook.createContact();
break;
case 3: ourAddressBook.DisplayAllContacts();
break;
case 4: exit;
}
}
cin.get();
cin.get();
cin.get();
cin.get();
return 1;
}
The problems arise because of the sequence in which you read, display and check for end of file.

Look at function FindContact()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void FindContact(){
    readFrom.open(fileName.c_str());

    if(readFrom.fail()){
        cout << "Cannot open file." << endl; 
    }
    
    else{
        cout << "Enter name: " << endl;
        cin >> TargetName;
        cout << "---------------------------------------" << endl;
        while(!readFrom.eof()){
            readFrom >> firstName >>  lastName >>  Number >> emailID;
            if(firstName.compare(TargetName)==0){
                cout << "Found details about " << TargetName << endl;
                cout << firstName << "    "<< lastName << "     " 
                     << Number << "     " << emailID << endl;
            }
        }
        readFrom.close();
    }
}

First time around. Line 12, check eof. Well, the file was only just opened, so its not eof.

Line 13 read the details.
Assume we have a match, lines 15 and 16 display the details.

Around the loop a second time. Check eof, it's still not eof.
line 13, read the details. Now we get end-of-file == true.
but we don't check it.
Instead, proceed to lines 15 and 16 and output the details again.

Around the loop again. This time eof is true.

Also note that when the read file is unsuccessful, the existing values in the various strings remain unaltered. In addition, the fail() flag is set, which persists until it is cleared.
Last edited on
Topic archived. No new replies allowed.