-2

I'm stuck on a problem while doing oop project by c++. I've mentioned the code below. What I'm getting the bad result is:

  • If I list the existing file where I've added some of the contacts, it will list all the contents of file properly. But if I try to add a new contact by signing in as an admin(pass=12345,if you need only) and now, if I try to open the file where I've added new contacts also. The problem arise here.
  • name should've listed as Name: Samir Chapagain
  • address should've listed as Adress: Nepal
    and so on but it skips the line and shows name in the place of address as Adress: Samir Chapagain

How to get over of it?? Take me out. I'm a beginner in coding.
Thanks in advance!!.

SOURCE CODE

#include <cstring>
#include <fstream>
#include <iostream>
using namespace std;
class Contact
{
public:
    string details[5] = {"Name", "Phone(Mobile)", "Address", "Email", ""};
    void adding()
    {
        ofstream fout;
        fout.open("ContactBook.txt", ios::app);
        char inpt[30];
        fout << "\n";
        for (int i = 0; i < 4; i++)
        {
            cin.getline(inpt, 30);
            cout << details[i] << ": ";
            fout << inpt << "\n";
        }
        cin.getline(inpt, 30);
        fout << inpt;
    }
    void listing()
    {
        ifstream fin;
        fin.open("ContactBook.txt", ios::in);
        char inpt[30];
        int i = 0;
        while (fin)
        {
            fin.getline(inpt, 30);
            if (i != 4)
                cout << details[i] << " : " << inpt << endl;
            else
                cout << details[i] << inpt << endl;
            i++;
            if (i == 5)
                i = 0;
        }
    }
    void searching()
    {
        string name;
        cout << "Enter name whose contact is to be searched: ";
        getline(cin >> ws, name);
        ifstream fin;
        fin.open("ContactBook.txt", ios::in);
        string inpt;
        int c = 0;
        while (fin)
        {
            getline(fin >> ws, inpt);
            if (inpt == name)
            {
                c++;
                for (int i = 0; i < 4; i++)
                {
                    cout << details[i] << ": " << inpt << endl;
                    getline(fin >> ws, inpt);
                }
            }
            if (c > 0)
                break;
        }
    }
    void editing()
    {
        string name;
        cout << "Enter name whose contact is to be Edited: ";
        getline(cin >> ws, name);
        ifstream fin;
        ofstream fout;
        fin.open("ContactBook.txt", ios::in);
        fout.open("ContactBookTemporary.txt", ios::out | ios::trunc);
        string inpt;
        int b = 0;
        int c = 0;
        while (!fin.eof())
        {
            getline(fin >> ws, inpt);
            b++;
            if (inpt == name)
            {
                c++;
                cout << "Enter new details: \n";
                for (int i = 0; i < 4; i++)
                {
                    string newdetail;
                    cout << "New " << details[i] << ": ";
                    getline(cin >> ws, newdetail);
                    b++;
                    fout << newdetail << "\n";
                }
                for (int i = 0; i <= 3; i++, b++)
                    getline(fin >> ws, inpt);
                fout << "\n"
                     << inpt << "\n";
            }
            else
            {
                if (fin.eof() != 1)
                    fout << inpt << "\n";
                else
                    fout << inpt;
                if (b % 4 == 0 && fin.eof() != 1)
                    fout << "\n";
            }
        }
    }
    void deleting()
    {
        string name;
        cout << "Enter name whose contact is to be Deleted: ";
        getline(cin >> ws, name);
        ifstream fin;
        ofstream fout;
        fin.open("ContactBook.txt", ios::in);
        fout.open("ContactBookTemporary.txt", ios::out | ios::trunc);
        string inpt;
        int b = 0;
        int c = 0;
        while (!fin.eof())
        {
            getline(fin >> ws, inpt);
            b++;
            if (inpt == name)
                c++;
            else
            {
                if (c >= 1 && c <= 3)
                    c++;
                else
                {
                    if (fin.eof() != 1)
                        fout << inpt << "\n";
                    else
                        fout << inpt;
                    if (b % 4 == 0 && fin.eof() != 1)
                        fout << "\n";
                }
            }
        }
    }
    void temporary_to_original()
    {
        ofstream fout1;
        ifstream fin1;
        fout1.open("ContactBook.txt", ios::out | ios::trunc);
        fin1.open("ContactBookTemporary.txt", ios::in);
        char reading[30];
        while (!fin1.eof())
        {
            fin1.getline(reading, 30);
            if (fin1.eof() == 0)
                fout1 << reading << "\n";
            else
                fout1 << reading;
        }
    }
    void exiting()
    {
        cout << "\n\nThank You For Using Contact Management System\n\n";
        exit(0);
    }
};

int main()
{
    Contact object;
    cout << "\n\t\t\t\t\t**** Welcome to Contacts Manager Application ****" << endl;
    cout << "INSTRUCTION: YOU CAN ONLY VIEW/SEARCH FOR A CONTACT IF YOU ARE A USER. TO EDIT, DELETE AN EXISTING CONTACT OR ADD ANY NEW CONTACT, SIGN IN AS ADMINISTRATOR." << endl;
block:
    cout << "\nSelect your identity(1/2)\n[1]USER\n[2]ADMIN\nEnter the choice:";
    int identity;
    int flag = 0;
    int flag1 = 0;
    cin >> identity;
    if (identity == 2)
    {
        char pass[5];
        cout << "\n\nEnter Admin 5 digits Passcode: ";
        for (int i = 0; i < 5; i++)
        {
            cin >> pass[i];
        }
        ifstream fin_pass("password.txt");
        char corr_pass;
        for (int i = 0; i < 5; i++)
        {
            fin_pass.get(corr_pass);
            if (pass[i] != corr_pass)
                flag1++;
        }

        if (flag1 == 0)
            cout << "\n\nWELCOME ADMIN\n\n";
        else
        {
            identity = 1;
            cout << "WRONG PASSCODE, YOU ARE SIGNED IN AS USER ONLY\n\n\nWELCOME USER\n\n";
        }
    }
    else
        cout << "\n\nWELCOME USER\n\n";
    while (1)
    {
        cout << "\n\n\t\t\t\t\t\tMAIN MENU\n\t\t\t\t\t=====================\n\t\t\t\t\t[1] Add a new Contact\n\t\t\t\t\t[2] List all Contacts\n\t\t\t\t\t[3] Search for contact\n\t\t\t\t\t[4] Edit a Contact\n\t\t\t\t\t[5] Delete a Contact\n\t\t\t\t\t[0] Exit\n\t\t\t\t\t=================\n\t\t";
        cout << "\t\t\tEnter the choice:";
        int op;
        cin >> op;
        switch (op)
        {
        case 1:
        {
            if (identity == 1)
            {
                cout << "\n\nSign in as Admin to add a new contact.\n\n";
                flag++;
            }
            else
            {
                object.adding();
                cout << "\nSuccessfully Added.\n";
            }
            break;
        }
        case 2:
        {
            object.listing();
            break;
        }
        case 3:
        {
            object.searching();
            break;
        }
        case 4:
        {
            if (identity == 1)
            {
                cout << "\n\nSign in as Admin to add a new contact.\n\n";
                flag++;
            }
            else
            {
                object.editing();
                object.temporary_to_original();
                cout << "\nSuccessfully Edited.\n";
            }
            break;
        }
        case 5:
        {
            if (identity == 1)
            {
                cout << "\n\nSign in as Admin to add a new contact.\n\n";
                flag++;
            }
            else
            {
                object.deleting();
                object.temporary_to_original();
                cout << "\nSuccessfully Deleted.\n";
            }
            break;
        }
        case 0:
        {
            object.exiting();
        }
        default:
            cout << "\n\nInvalid choice. Try again\n\n";
        }
        if (flag == 1)
        {
            flag = 0;
            goto block;
        }
    }
    return 0;
}
Cory Kramer
  • 98,167
  • 13
  • 130
  • 181
  • 1
    Required reading: [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons); [Why does std::getline() skip input after a formatted extraction?](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – molbdnilo Dec 14 '20 at 14:58

1 Answers1

0

The problem comes from the way you input the passcode.

You use the following code:

        for (int i = 0; i < 5; i++)
        {
            cin >> pass[i];
        }

This will read 12345 but will not absorb the newline submitted by pressing the enter key. It's still left in the input stream.

So then if you next add a contact in the adding function, you encounter this code...

        for (int i = 0; i < 4; i++)
        {
            cin.getline(inpt, 30);
            cout << details[i] << ": ";
            fout << inpt << "\n";
        }

The first thing that happens is the first cin.getline will return empty input, because the next thing left in the input stream is the newline left over from when you read the passcode.

To fix, I suggest you read the passcode with a getline command, as you have done in other places.

Edit: further clarification

This is a terrible pattern to follow:

getline(cin >> ws, name);

When you read from a string into a variable, the console waits until you press the enter key, then starts processing the stream. The newline character is left in the stream, though.

To Fix

I strongly suggest you write user-input functions and use them everywhere.

string getUserEnteredString();
int getUserEnteredInt();

Here is the implementation. (It's the same for both. Later, you'll learn about C++ templates to only have to write this once, but for you, since you are a beginner, I'll duplicate them.)

string getUserEnteredString() {
    string result;
    cin >> result;
    cin.ignore(1000, '\n');
    return result;
}

int getUserEnteredInt() {
    int result;
    cin >> result;
    cin.ignore(1000, '\n');
    return result;
}

Then, everywhere you have this pattern:

string name;
cout << "Prompt: ";
getline(cin >> ws, name);

...replace it with:

cout << "Prompt: ";
string name = getUserEnteredName();

Similarly, where you input a number in your menu:

cout << "\t\t\tEnter the choice:";
int op;
cin >> op;

...instead write:

cout << "\t\t\tEnter the choice:";
int op = getUserEnteredInt();

For the password, you have a dangerous piece of code where you only allocate 5 characters to the passcode character array called pass. The smallest change I could consider making that is still appropriate for your level of ability is this:

cout << "\n\nEnter Admin 5 digits Passcode: ";
string pass = getUserEnteredString();
ifstream fin_pass("password.txt");
string corr_pass;
getline(fin_pass, corr_pass);
if (pass != corr_pass) flag1 = 1;

It's not perfect, but it's better.

Wyck
  • 5,985
  • 4
  • 34
  • 44
  • I've a file for passcode. That's not the problem. I got into admin and add the contact. The problem is when i list the contacts in the file after adding. It generates a space line after saving the file but while the coding is running it doesn't generates the space line. That's the main problem I'm facing. – Samir_Chapagain Dec 14 '20 at 15:18
  • If you don't believe me, examine the file in a text editor after adding. Also, you can manually edit the file in a text editor before listing. Can you indulge me anyway? Please try inputting the password using getline and see if the problem goes away. You can also use a debugger to observe it returning an empty string for the first `cin.getline` in the `adding` function – Wyck Dec 14 '20 at 15:25
  • Provide me the code to be changed. I'm roaming round the code again and again but couldn't find how to debugg. – Samir_Chapagain Dec 14 '20 at 15:41
  • Your use of user stream input, both from the console and from files is wrong or poor in most places you apply it. I've modified my answer to provide more guidance. Short answer: write user-input functions that work in a simple way, then implement them correctly. – Wyck Dec 14 '20 at 16:33
  • If you don't like the magic `1000`, you can write: `cin.ignore(numeric_limits::max(), '\n')` But I'm trying to keep the answer appropriate to your skill level. – Wyck Dec 14 '20 at 16:36