How to delete a line from a text file using fstream

I'm trying to make a simple phonebook app that can show contacts, add, and delete. I'm pretty new to C++ and fstream functions, can anyone help me with deleting a line in my bool erase() function?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include <iostream>
#include <conio.h>
#include <string>
#include <windows.h>
#include <fstream>
#include <cstdlib>
using namespace std;


//prototypes
void printline(char, int);


//global variable
fstream file;


class contact
{
    string name;
    string mob;
    string line;


    public:


        // Shows all contacts
        bool show()
        {
            if(name == "")
            {
                getline(file, line);
                cout << line + "\n";
                return 1;
            }
        }

        //The contact object is initialized by valid values
        bool add(string new_name, string new_mob)
        {
            if(file.is_open())
            {
                name = new_name;
                mob = new_mob;
                file << name + "   ";
                file << mob + "\n";
                return 1;
            }

        }

        //delete contact
        bool erase(string new_name)
        {
            
        }
};

int main()
{

    contact person[20];
    file.open("MyContacts.txt");
    int choice, i, counter;
    bool flag;
    bool cancel_flag;
    string temp_name, temp_mob;

    cout << "**** PHONEBOOK ******" << endl;


    do
    {
        cout << "\n\n\n";
        printline('-', 20);
        cout << "1. Show contacts" << endl
        << "2. Add Contact" << endl
        << "3. Delete Contact" << endl
        << "4. Quit" << endl << endl
        << "Your choice...";
        cin >> choice;

        system("cls");
        printline('-', 20);
        cancel_flag = 0;

        switch(choice)
        {
            case 1:

                cout << "Showing Contacts" << endl;
                printline('-', 20);

                for(i=0; i<20; i++)
                    person[i].show();
                    //if(person[i].show())
                        //flag = 1;


                //if(!flag)
                    //cout << "No contacts found!" << endl;
                break;

            case 2:
                cout << "Add New Contact\t\t\t\tpress $ to cancel" << endl;
                printline('-', 20);


                    flag = 1;
                    cout << "Name: "; cin >> temp_name;

                    //Cancel operation
                    if(temp_name=="$")
                    {
                        cancel_flag = 1;
                        break;
                    }
                    cout << "Mobile No.: "; cin >> temp_mob;

                    //Cancel operation
                    if(temp_mob=="$")
                    {
                        cancel_flag = 1;
                        break;
                    }


                if(cancel_flag)
                {
                    system("cls");
                    break;
                }


                //This code adds the contact to phonebook
                for(i=0; i<20; i++)
                    if(person[i].add(temp_name, temp_mob))
                    {
                        cout << "Contact added successfully!" << endl;
                        flag = 1;
                        break;
                    }

                //if(!flag)
                    //cout << "Memory full! Delete some contacts first."
					//<< endl;
                break;

            case 3:


                cout << "Enter a contact name to delete:"
                "\t\t\tpress $ to cancel\n";
                cin >> temp_name;

                //Cancel Operation
                if(temp_name=="$")
                {
                    system("cls");
                    break;
                }


                if(cancel_flag)
                    break;

                // This code deletes the contact
                if(flag)
                {
                    for(i=0; i<20; i++)
                        if(person[i].erase(temp_name))
                        {
                            cout << "Deleted successfully!" << endl;
                            break;
                        }
                }


            break;

            case 4:
                return 0;
                break;

        }
    } while(1);

    getch();
    file.close();
    return 0;
}

//prints a line
void printline(char ch, int size)
{
    for(int i=0; i<size; i++)
        cout << ch;
    cout << "\n";
}

Last edited on
Read the whole file and store it, then open it with ofstream(which I believe clears the data), then modify the stored data and dump it.
The following pseudocode fragment deals with long files which couldn't be hold in memory entirely.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
open input
open tmp_output

while not end of input

    read line from input
    if line has not to be deleted from file then
        write line to tmp_output
    end if

end while

close input
close tmp_output

rename tmp_output to input    // rename() is usually atomic on UNIX based systems 
I have tried following your pseudo-code but it my code seems to copy all the text to the temp file. Can you help me point out what's wrong?

1
2
3
4
5
6
7
8
9
10
11
12
bool deleteContact(string nm) //deletes a contact
        {
                while(!file.eof())
                {
                    getline(file, line);
                    if (line != nm)
                    {
                       rem << line << endl;
                    }
                }

        }


Inside my switch case:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    
                file.open("MyContacts.txt",fstream::in | fstream::out | fstream::app);
                rem.open("temp.txt",fstream::in | fstream::out | fstream::app);
                cout << "Enter a contact name to delete:" ;
                cin >> temp_name;
             

                for(i=0; i<20; i++)
                 {
                    if(person[i].deleteContact(temp_name))
                    {
                        cout << "Deleted successfully!" << endl;
                        break;
                    }
                 }
                file.close();
                rem.close();
                remove("MyContacts.txt");
                rename("temp.txt", "MyContacts.txt");
                break;
Last edited on
Line 6: Does nm exactly match line? If your files line does not only contain the name but also the phone number etc. then you should write a more sophisticated comparison function instead of the simple string::operator!=() as you use it in line 6.

The first call to deleteContact() scans the entire input file up to its end. All further 19 calls won't read anything - because the internal file pointer just points to the end of the file. You may better open the file on entering deleteContact() and close it on leaving.

Your function deleteContact() doesn't return any value, so its return value is undefined.

Some less important tips:
You don't need to remove the target file before renaming to it. It will be done by your operating system when handling rename().
Ok I redid the function to how you specified it and did some caveman debugging, I tried to print out line which was to be copied to temp, it printed out correctly but at the end of the execution mycontacts file still contains all of the lines.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool deleteContact(string nm) //deletes a contact
        {
            file.open("MyContacts.txt",fstream::in | fstream::out | fstream::app);
            rem.open("temp.txt",fstream::in | fstream::out | fstream::app);
            while(!file.eof())
            {
                getline(file, line);
                //cout << line << endl;
                if (line.substr(0, line.find(" ")) != nm)
                {
                   rem << line << endl;
                   cout << line << endl;
                }
            }
            file.close();
            rem.close();
            rename("temp.txt", "MyContacts.txt");
        }


I know I'm close, but I can't seem to find out what's going on
From Reference Manual, string:
Return Value
The position of the first character of the first match.
If no matches were found, the function returns string::npos.

You're comparing a string starting with a space character. To match it, nm also has to start with one.

Debug your line matching condition.
Topic archived. No new replies allowed.