-1

I am trying to finish my program and I need it to delete a line from a text file. I've tried multiple code from other people in trying to figure out why my "temp.txt" file won't rename and replace my "fruit.txt" file which is the file I was deleting a line from.

main.cpp

#include <iostream>
#include "filehandling.h"

using namespace std;

int main()
{
    program run;
    run.askUser();
    return 0;
}

filehandling.h

#ifndef FILEHANDLING_H_INCLUDED
#define FILEHANDLING_H_INCLUDED

#include <fstream>
#include <iostream>
#include <string>
#include <cstdio>
#include <vector>

using namespace std;

class program{
public:
    string name;
    string desc;
    ofstream out_stream;
    ifstream in_stream;


    void displayMenu () // Display for Menu
    {
        cout << "--------------------Welcome To Lemon Mart---------------------" << endl;
        cout << "\t1: Add a Fruit to your cart." << endl;
        cout << "\t2: Delete a item from your cart." << endl;
        cout << "\t3: List of items in your shopping cart." << endl;
        cout << "\t4: Checkout(Ends Program)." << endl;
    }

    void createFile() // Creates the file
    {
        out_stream.open ("fruit.txt");

        if(!out_stream.is_open())
        {
            cout << "Output file failed." << endl;
            exit(1);
        }
    }

    void writeToFile(string fruitName) // Writes Input to the file
    {
        out_stream << fruitName << endl;
    }

    void listFruits()          // fills array from file
    {
        in_stream.open("fruit.txt");
        vector<string> fruitVec;

        string str;
        while (getline(in_stream, str))
        {
            if(str.size() > 0)
                fruitVec.push_back(str);
        }


        cout << "Here's a list of what items you have in your cart currently" << endl << endl;
        for (string & line : fruitVec)
            cout << line << endl;
        cout << endl << endl;
        in_stream.close();
    }

   void delItem(string path,string eraseFruit)
   {
    string line;
    ifstream fin;

    fin.open(path);
    ofstream temp;
    temp.open("temp.txt");

    while (getline(fin, line))
    {
        if (line != eraseFruit)
            temp << line << endl;
    }

    temp.close();
    fin.close();

    const char * p = path.c_str();
    remove(p);
    rename("temp.txt", p);
    }


    void askUser()
    {
        int choice = 0;
        string path = "fruit.txt";
        string eraseFruit;

        createFile();

        while(choice <= 3)
        {
            displayMenu();
            cin >> choice;
            cout << endl;
            switch (choice)
            {
                case 1 :
                    // ADD FRUIT TO BASCKET
                    cout << "Whats the name of the fruit you wish to add to your cart?" << endl;
                    cin >> name;
                    cout << "Item added to cart." << endl << endl;
                    writeToFile(name);
                    choice = 0;
                    break;
                case 2 :
                    // Delete item from cart
                    cout << "What item would you like to delete from your cart?" << endl;
                    cin >> eraseFruit;
                    delItem(path, eraseFruit);
                    choice = 0;
                    break;
                case 3 :
                    // List Cart items
                    listFruits();
                    choice = 0;
                    break;
                case 4 :
                    // Exits Program
                    cout << "\tChecking Out, Have a good day!" << endl;
                    exit(1);
                    break;
                default :
                    cout << "Must select a option" << endl;
                    choice = 0;
                    break;
            }
        }
        out_stream.close();
    }
};




#endif // FILEHANDLING_H_INCLUDED
cigien
  • 57,834
  • 11
  • 73
  • 112
  • 1
    What's the idea behind putting the whole program in a header file? – Ted Lyngmo May 12 '21 at 16:30
  • Instead of this rather long program, make a very small program that only tries to do what your current program fails to do. If that fails too, put _that_ program in your question instead of the one you currently have there. Make a [mre]. – Ted Lyngmo May 12 '21 at 16:32
  • Ted the idea of the whole program being in a header file was so that my main had as little code as possible due to my teacher requiring – Jamie Lovenduski May 12 '21 at 17:09
  • I see. Well, you didn't really change anything by putting it in a header file though - but perhaps your teacher will just chuckle a bit and make the requirements a little clearer the next time. – Ted Lyngmo May 12 '21 at 17:21
  • Most likely lol, Im just trying to get it done at this point. Right now I need to figure out why I can't close the fruit.txt file. Because after what Ken wrote down below it does make the most sense since I tried error checking and it says no permission to delete – Jamie Lovenduski May 12 '21 at 17:24
  • 1
    :-) You could try not keeping the stream objects as class members. Most of the time when you see these types (`fstream`s) used, they are never explicitly closed. You use them a while and let them go out of scope (and then they will be automatically closed). Now, if your functions did the same: opened the file in the required mode inside a function - the file would be closed when the function returned. It may require some redesign – Ted Lyngmo May 12 '21 at 17:34

2 Answers2

1

The problem is that you have out_stream.open ("fruit.txt");, but you don't close it until the program ends, so you cannot remove() an open file. You should always test the return values from file operations, such as in the example here.

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
  • 1
    This is the most probable cause that I could find when browsing the code, although, it requires that OP uses one of the OS:es where removing/renaming open fails fails by default (Windows springs to mind). – Ted Lyngmo May 12 '21 at 16:36
  • Yes, I [looked it up](https://stackoverflow.com/q/2028874/1270789) and you are correct about Linux - I didn't realise that. – Ken Y-N May 12 '21 at 16:40
  • In general (perhaps by standard) POSIX systems let you unlink even open files - which is really useful since you can then make the operations 1. Fill temporary file. 2. Remove target. 3. Rename temporary file into target into 1. Fill temporary file, 2. Rename .... This means that whenever someone tries to open the target file, it'll be there. There are no gaps in time where it's suddenly gone. You either open the old or the new version of the file. Another perk: You can create a file, unlink it while keeping it open. You now have a temporary file to work with that will be removed when closed. – Ted Lyngmo May 12 '21 at 16:43
  • ... and it won't even be seen by other processes for a longer time than it takes to _open_create/remove_ it. – Ted Lyngmo May 12 '21 at 16:46
  • Okay I most likely believe this being the issue as well after doing more testing. The reason behind this is because when I do the test return values it says that the file doesn't have permission which means the file is still open. But what I don't understand is I thought I was closing the file in fin.close(). – Jamie Lovenduski May 12 '21 at 17:08
-1

Generally speaking, you can't "delete a line", rather you rewrite the file without the data you no longer want.

If the data you no longer want happens to be a "line" of text, then the resulting file will show that line as deleted.

PaulProgrammer
  • 16,175
  • 4
  • 39
  • 56