0

So I have to make a bank program for an assignment, and my professor wants a log file of every "operation"(He was really vague about that, I decided to log inputs and outputs). The issue I'm having though is that every time I call a new function, I have to reopen the file and it overwrites what was previously there. As far as I can tell, using .open repeatedly will cause whatever function I'm in to ignore the previous output.
I tried declaring a global ofstream hoping that it would change, but the issue persists either way. Flushing and/or closing didn't seem to help,but it's entirely possible I misused them or the syntax was wrong. The code below is the main function, read_accts function, and menu function. If I terminate the program before calling the read_accts function, the log file will have "How many accounts are there?" But if I allow the program to call the other two functions, then the log file only has the output of the menu file. I apologize for the long post, but I'm at a loss as to what's going wrong.

int main()
{
    ofstream log;
    log.open("Log.txt");
    int MAX_NUM = 100;
    BankAccount account[MAX_NUM];
    int num_accts = 0;
    char selection = 'Z';
    cout << "How many accounts are there?" << endl;
    log << "How many accounts are there?" << endl;
    cin >> MAX_NUM;
    read_accts(account, MAX_NUM, num_accts);
    cout << endl;
    cout << "There are " << num_accts << " accounts" << endl;
    log << "There are " << num_accts << " accounts" << endl;
    cout << endl;
    print_accts(account, MAX_NUM);
    cout << endl;
    `

    while (selection != 'Q' && selection != 'q')
    {

        menu();
        cin >> selection;
        log << selection;
        switch (selection)
        {
            case 'W':
                case 'w':
                withdrawal(account, num_accts);
                break;
            case 'D':
                case 'd':
                deposit(account, num_accts);
                break;
            case 'N':
                case 'n':
                new_acct(account, num_accts);
                break;
            case 'B':
                case 'b':
                balance(account, num_accts);
                break;
            case 'I':
                case 'i':
                account_info(account, num_accts);
                break;
            case 'C':
                case 'c':
                close_acct(account, num_accts);
                break;
            case 'Q':
                case 'q':
                print_accts(account, num_accts);
                break;
            default:
                cout << "Invalid selection" << endl;
                log << "Invalid selection" << endl;

        }
        cout << endl;
    }
    print_accts(account, MAX_NUM);
    cout << "Goodbye" << endl;
    log.close();
    return 0;
}

int read_accts(BankAccount account[], int MAX_NUM, int &num_accts)
{
    ofstream log;
    log.open("log.txt", std::ofstream::app);
    string f;
    string l;
    int social;
    int acct;
    string type;
    double bal;
    int i = 0;
    ifstream readfile;
    readfile.open("bankdatain.txt");
    if (!readfile)
    {
        cout << "Can't open input file." << endl;
        log << "Can't open input file." << endl;
        exit(1);
    }
    while (readfile >> f >> l >> social >> acct >> type >> bal)
    {
        account[i].setfname(f);
        account[i].setlname(l);
        account[i].setssnum(social);
        account[i].setacctnum(acct);
        account[i].settype(type);
        account[i].setbalance(bal);
        i++;
        num_accts++;
    }

    return num_accts;
}

void menu()
{
    ofstream log;
    log.open("Log.txt");
    cout << "W - Withdrawal" << endl;
    log << "W - Withdrawal" << endl;
    cout << "D - Deposit" << endl;
    log << "D - Deposit" << endl;
    cout << "N - New account" << endl;
    log << "N - New account" << endl;
    cout << "B - Balance" << endl;
    log << "B - Balance" << endl;
    cout << "I - Account Info" << endl;
    log << "I - Account Info" << endl;
    cout << "C - Close Account" << endl;
    log << "C - Close Account" << endl;
    cout << "Q - Quit" << endl;
    log << "Q - Quit" << endl;
    cout << "Please make your selection: " << endl;
    log << "Please make your  selection: " << endl;
}
user4581301
  • 33,082
  • 7
  • 33
  • 54

2 Answers2

0

As far as I know, by default, ofstream will open file in std::fstream::out mode, if will erase the existed file or create new file.

Change it to std::fstream::app http://www.cplusplus.com/reference/fstream/fstream/open/

Edited: Seem like you use two ostream to just one file. It can't deny access Using std:fstream how to deny access (read and write) to the file

Pass the ostream to called function

int read_accts(BankAccount account[],int MAX_NUM,int &num_accts, ostream& log)
{
log.open("log.txt",std::ofstream::app); // remove this line since you already open it in main()

while call it in main

read_accts(account,MAX_NUM,num_accts, log);
Community
  • 1
  • 1
khôi nguyễn
  • 626
  • 6
  • 15
  • Fstream doesn't make a difference, is it possible that using "file.open" in main() and then using it again in another function causes the issue? I guess I'm looking for a way to keep the file open across every function, if that's possible. – Charlie Monnone Nov 26 '16 at 03:43
  • @CharlieMonnone Updated! – khôi nguyễn Nov 26 '16 at 03:49
  • Passing log as a parameter doesn't appear to work; as far as I can tell once I call the read_accts function ofstream stops working. – Charlie Monnone Nov 26 '16 at 04:14
  • @CharlieMonnone you should remove the .open in read_accts since you already open the file in main, then you pass its references, it no need to open it again. – khôi nguyễn Nov 26 '16 at 04:19
  • It's working now, removing log.open("log.txt",std::ofstream::app); did the trick. Thank you!. – Charlie Monnone Nov 26 '16 at 04:23
  • Opening a file that is already open is considered failure to open [and `open` "Calls setstate(failbit) on failure."](http://en.cppreference.com/w/cpp/io/basic_fstream/open) `failbit` needs to be cleared before continuing. Better to just not reopen the file. – user4581301 Nov 26 '16 at 04:24
0

I think your only problem is That you must add this before you write into file.

log.seekp(0, std::ios_base::end);

this will set the file pointer to the end of file and continue to write from there.

Your file is already open in int main () it will be better if you pass the variable log into the function int read_accts(BankAccount account[], int MAX_NUM, int &num_accts) and make it int read_accts(BankAccount account[], int MAX_NUM, int &num_accts, ofstream log );

and make its definition

int read_accts(BankAccount account[], int MAX_NUM, int &num_accts, ofstream log )
{
    string f;
    string l;
    int social;
    int acct;
    string type;
    double bal;
    int i = 0;
    ifstream readfile;
    readfile.open("bankdatain.txt");
    if (!readfile)
    {
        cout << "Can't open input file." << endl;
        log << "Can't open input file." << endl;
        exit(1);
    }
    while (readfile >> f >> l >> social >> acct >> type >> bal)
    {
        account[i].setfname(f);
        account[i].setlname(l);
        account[i].setssnum(social);
        account[i].setacctnum(acct);
        account[i].settype(type);
        account[i].setbalance(bal);
        i++;
        num_accts++;
    }

    return num_accts;
} 

PS syntax of seekp() is

  ostream& seekp (streampos pos);
  ostream& seekp (streamoff off, ios_base::seekdir way);

refer here

PS its equivalent for ifstream is seekg ( 0, std::ios_base::end )

WARhead
  • 643
  • 5
  • 17