0

I've been having such a difficult time trying to "delete" a line from a text file and have looked everywhere. I'm a beginner with C++ so I have no idea how to use vectors yet.

When I run this program, it will not write anything to the tempFile. Am I missing something?


    string deleteLine, line;
    ifstream addressFile;
    addressFile.open("AddressBook.txt");
    ofstream tempFile;
    tempFile.open("temp.txt");

    int i = 1;
    while (getline(addressFile, line)) {
        cout << (i++) << " " << line << endl;
    }

    cout << "Which line do you want to remove?" << endl;
    cin >> deleteLine;

    // GOOD UP TO HERE

    while (getline(addressFile, line)) {
        if (line != deleteLine); {
            tempFile << line << endl;
        }
    }

    tempFile.close();
    addressFile.close();

    remove ("AddressBook.txt");
    rename ("temp.txt", "AddressBook.txt");
    cout << endl << endl;

Update - This is the current code I have and still not writing to tempFile

    ifstream addressFile;
    addressFile.open("AddressBook.txt");
    ofstream tempFile;
    tempFile.open("temp.txt");

    string line;
    int lineNum, i;

    i = 1;
    while (getline(addressFile, line)) {
        cout << (i++) << " " << line << endl;
    }

    addressFile.seekg(0);

    cout << "Which line number do you want to remove?" << endl;
    cin >> lineNum;

    // GOOD UP TO HERE
    i = 1;
    
    while (getline(addressFile, line)) {
        if (i++ != lineNum) {
            tempFile << line << endl;
        }
    }

    tempFile.close();
    addressFile.close();

    //remove ("AddressBook.txt");
    //rename ("temp.txt", "AddressBook.txt");
    cout << endl << endl;
  • First, read this: https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction Then, think a little bit about what you're trying to do. Do you want the user to choose a line number to delete or type in the text on the line? If you want to delete by number you need to change your code to accept a number and not a string. If you want them to type the text you should use `getline` since the input might have spaces. Since you've just read all of the lines in the file then trying to read more will fail. Close and open the file or seek to the beginning. – Retired Ninja Apr 13 '21 at 02:00
  • Once you read to the end of a file -- your are at the end and can't read further without resetting the file position indicator back to a point earlier in the file (usually the beginning). That is covered by @RemyLebeau in his answer. – David C. Rankin Apr 13 '21 at 02:10
  • @RetiredNinja that other question has no relevance on this issue, since there nothing in this code is calling `std::getline()` after a formatted extraction on the same stream – Remy Lebeau Apr 13 '21 at 02:11
  • @RemyLebeau Ah, you're right. So used to seeing that problem I've trained myself to see it even when it isn't there. :) – Retired Ninja Apr 13 '21 at 02:14
  • @RetiredNinja Thanks for the documentation! I understand the difference now. – Nicholas Renard Apr 13 '21 at 02:21
  • 1
    `if (line != deleteLine); {` – Jeremy Friesner Apr 13 '21 at 02:43
  • @All -- Still having issues after changing the code around to identify an `int` instead of a `string`. Nothing will write to the tempFile – Nicholas Renard Apr 13 '21 at 02:49

1 Answers1

2

In your 1st while loop, you are reading lines from addressFile until the end of the file is reached. Then, your 2nd while loop is trying to read lines from the same file again, but there is nothing left to read.

You need to seek addressFile back to the beginning of the file before you can re-read the lines again. Add this statement between your 2 loops:

addressFile.seekg(0);

With that fixed, you still have some other problems.

In your 2nd loop, your if has an erroneous ; on it, so you are not going to actually ignore any lines, you will write all of the lines to tempFile.

Also, you should consider asking the user for a line number to ignore, not an actual line of text. And validate the user's input before using it.

You should also verify that the files are being opened successfully.

Try this:

ifstream addressFile("AddressBook.txt");
if (!addressFile.is_open()) {
    cerr << "Can't open AddressBook.txt" << endl;
    return;
}

ofstream tempFile("temp.txt");
if (!tempFile.is_open()) {
    cerr << "Can't create temp.txt" << endl;
    return;
}

string line;
int lineNum, i;

i = 1;
while (getline(addressFile, line)) {
    cout << (i++) << " " << line << endl;
}

addressFile.seekg(0);

do {
    cout << "Which line number do you want to remove?" << endl;
    if (cin >> lineNum) {
        if (lineNum > 0) break;
        cerr << "Please choose a number greater than zero" << endl;
    }
    else {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cerr << "Invalid number, try again" << endl;
    }
}
while (true);

i = 1;
while (getline(addressFile, line)) {
    if (i != lineNum) {
        tempFile << line << endl;
    }
    ++i;
}

tempFile.close();
addressFile.close();

remove ("AddressBook.txt");
rename ("temp.txt", "AddressBook.txt");
cout << endl << endl;
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
  • That seek is pretty useful. I haven't seen that before. I tried your example and it still is not writing anything to tempFile. – Nicholas Renard Apr 13 '21 at 02:20
  • @NicholasRenard did you check the result of `tempFile.open()` to verify it is successful in opening the output file? – Remy Lebeau Apr 13 '21 at 14:08