I am trying to make a small rudimentary phonebook program in C++.
The function to add a new contact is as follows:
#define length 30;
class contact
{
char name[length];
char number[length];
public:
void newcontact (void);
void updatecontact (void);
void searchphone (void);
void searchname (void);
void deletecontact (void);
void display (void);
};
void contact :: newcontact(void)
{
contact c;
int m = 0;
cout << "Enter name: ";
cin.ignore (1, '\n');
cin.getline (name, length);
/*
while (1)
{
file.seekg (m * sizeof (contact), ios :: beg);
file.read ((char *) & c, sizeof (c));
if (file.eof() == 1)
break;
if (strcmp (c.name, name) == 0)
{
cout << "\nContact already exists.\nChoose another name or use the \"update contact\" option\n";
return;
}
m++;
}*/
strcpy (c.name, name);
cout << "Enter phone: ";
cin >> c.number;
file.seekg(0, ios::end);
file.write ((char *) & c, sizeof (c));
cout << "\nContact added\n";
}
See the while loop inside /* multiline comment /. This while loop is meant to make sure that two contacts do not have the same name. The program works well when the / multiline comment */ are in place and the while loop is not part of the program.
However, if I remove the /* */ and bring the while loop into the program and try to add a new contact, the output is
Contact added
However, the contact does not actually get added.
What is the cause of this glitch?
The complete program is as follows:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <cstring>
#define length 30
using namespace std;
fstream file, file_temp;
char * cistrstr (char *, char *);
class contact
{
char name[length];
char number[length];
public:
void newcontact (void);
void updatecontact (void);
void searchphone (void);
void searchname (void);
void deletecontact (void);
void display (void);
};
void contact :: newcontact(void)
{
contact c;
int m = 0;
cout << "Enter name: ";
cin.ignore (1, '\n');
cin.getline (name, length);
/*
while (1)
{
file.seekg (m * sizeof (contact), ios :: beg);
file.read ((char *) & c, sizeof (c));
if (file.eof() == 1)
break;
if (strcmp (c.name, name) == 0)
{
cout << "\nContact already exists.\nChoose another name or use the \"update contact\" option\n";
return;
}
m++;
}*/
strcpy (c.name, name);
cout << "Enter phone: ";
cin >> c.number;
file.seekg(0, ios::end);
file.write ((char *) & c, sizeof (c));
cout << "\nContact added\n";
}
void contact :: updatecontact(void)
{
int update_choice, m = 0;
contact c;
cout << "\nEnter 1 to update name, enter 2 to update contact number\n";
cin >> update_choice;
file.seekg(0, ios :: beg);
if (update_choice == 1)
{
cout << "\nEnter phone number: ";
cin >> number;
cout << "Enter new name: ";
cin.ignore (1, '\n');
cin.getline (name, length);
}
else if (update_choice == 2)
{
cout << "\nEnter name: ";
cin.ignore (1, '\n');
cin.getline (name, length);
cout << "Enter new phone number: ";
cin >> number;
}
else
cout << "\nInvalid option\n";
while (1)
{
file.seekg (m * sizeof (contact), ios :: beg);
file.read ((char *) & c, sizeof (c));
if ((update_choice == 1 && strcmp (c.number, number) == 0) || (update_choice == 2 && strcmp (c.name, name) == 0))
{
strcpy (c.name, name);
strcpy (c.number, number);
file.seekg (m * sizeof (contact), ios :: beg);
file.write ((char *) & c, sizeof (c));
cout << "\nContact updated\n";
break;
}
if (file.eof() == 1)
{
cout << "\nContact not found\n";
break;
}
m++;
}
}
void contact :: searchphone(void)
{
contact c;
int m = 0, found = 0;
file.seekg(0, ios ::beg);
cout << "\nEnter name: ";
cin >> name;
while (1)
{
file.seekg (m * sizeof (contact), ios :: beg);
file. read ((char *) & c, sizeof (c));
if (file.eof() == 1)
break;
if (cistrstr(c.name, name) != 0)
{
cout << setw(30) << left << c.name << setw(10) << c.number << endl;
found = 1;
}
m++;
}
if (found == 0)
cout << "\nContact not found\n";
}
void contact :: searchname(void)
{
contact c;
int m = 0, found = 0;
file.seekg(0, ios :: beg);
cout << "\nEnter number: ";
cin >> number;
while (1)
{
file.seekg (m * sizeof (contact), ios :: beg);
file.read ((char *) & c, sizeof (c));
if (file.eof() == 1)
break;
if (cistrstr(c.number, number) != NULL)
{
cout << setw(30) << left << c.name << setw(10) << c.number << endl;
found = 1;
}
m++;
}
if (found == 0)
cout << "\nContact not found\n";
}
void contact :: deletecontact (void)
{
contact c;
int i = 0;
cout << "\nEnter name of contact to be deleted: ";
cin >> name;
file_temp.open("data_temp", ios ::app);
file_temp.close();
file_temp.open ("data_temp", ios :: in | ios :: out);
while (1)
{
file.read ((char *) &c, sizeof (contact));
if (file.eof () == 1)
break;
if (strcmp (c.name, name) != 0)
file_temp.write ((char *) &c, sizeof (contact));
else
{
cout << "Contact deleted";
i = 1;
}
}
if (i == 0)
cout << "Contact not found";
file.close();
file_temp.close();
remove ("data");
rename ("data_temp", "data");
}
void contact :: display (void)
{
char c;
file.seekg (0, ios::end);
int end = file.tellg(), m = 0;
file.seekg (0, ios::beg);
while (1)
{
contact c;
file.read ((char *) & c, sizeof (c));
cout << setw(30) << left << c.name << setw(10) << c.number << endl;
if (file.tellg() == -1 ||file.tellg() == end)
break;
m++;
}
}
int main()
{
char another = 'Y';
int choice, update_return;
contact c;
file.open("data", ios ::app);
file.close();
while (another == 'Y' || another == 'y')
{
file.open("data", ios ::in | ios ::out);
cout << "\033[2J\033[1;1H";
cout << "\n\nMAKE A CHOICE...\n\n";
cout << "1. Add a new contact\n";
cout << "2. Update a contact\n";
cout << "3. Search a phone number (using name)\n";
cout << "4. Search a name (using phone number)\n";
cout << "5. Delete a contact\n";
cout << "6. Display entire list\n\n";
cin >> choice;
switch (choice)
{
case 1:
c.newcontact();
break;
case 2:
c.updatecontact();
break;
case 3:
c.searchphone();
break;
case 4:
c.searchname();
break;
case 5:
c.deletecontact();
break;
case 6:
c.display();
break;
default:
cout << "\nInvalid option\n";
}
file.close();
cout << "\nWant to try again? (Y/N)...\n";
cin >> another;
}
return 0;
}
char * cistrstr (char *string, char *substring)
{
int i, j, l_string, l_sub;
l_string = strlen (string);
l_sub = strlen (substring);
char *p, *a, *b;
a = (char *) malloc (l_string + 1);
b = (char *) malloc (l_sub + 1);
for (i = 0; string[i] != '\0'; i++)
{
if (string[i] > 96 && string[i] < 123)
a[i] = string[i] - 32;
else
a[i] = string [i];
}
a[i] = '\0';
for (i = 0; substring[i] != '\0'; i++)
{
if (substring[i] > 96 && substring[i] < 123)
b[i] = substring[i] - 32;
else
b[i] = substring[i];
}
b[i] = '\0';
for (i = 0; a[i] != '\0'; i++)
{
if (a[i] == b[0])
{
p = &string[i];
for (j = 0; b[j] != '\0'; j++)
{
if (b[j] != a[i + j])
break;
}
if (b[j] == '\0')
{
free (a);
free (b);
return p;
}
}
}
free (a);
free (b);
return NULL;
}
The error is caused by the fact that if you read the file to the end of file (as you do in the while loop) this causes the file to be in an error state. This means that the subsequent write fails.
The answer is to clear the error state before you do the write, like this
if (file.eof() == 1)
{
file.clear();
break;
}
Having said that you really should take the advice in the comment. Read the file into a vector at the beginning of the program. Manipulate the data in the vector. Write the vector out to the file when you exit the program. There should be no file operations except at the start and end of the program