0

I am struggling with a programming assignment in my C++ class. The assignment involves creating a random access file to store inventory for a hardware store. I can create, read and write to the file just fine. I have a function which opens the file or creates a new one if it does not exist. This function then returns the open file as std::fstream. I am trying to pass that open file to another function which prints out the contents of the file to the console. When I call the print function the first time it works just fine. However, when I return to the main menu and try and call the print function again, it prints out nothing from the file.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include "HardwareData.h"

void printMenu();
unsigned short int getMenuChoice();
std::string getFileName();
std::fstream openFile(const std::string& fileName);
std::fstream newFile(const std::string& filename);
void printHeader();
void printAllRecords(std::fstream& file);
void newRecord(std::fstream& file);
unsigned int getRecordNum(const std::string& prompt);
bool recordIsBlank(std::fstream& file, unsigned int recordNum);

int main() {

    unsigned short int menuChoice{0};
    std::string filename;
    std::fstream file;

    while(menuChoice != 6){
        printMenu();
        menuChoice = getMenuChoice();
        switch(menuChoice){
            case 1:
                filename = getFileName();
                file = openFile(filename);
                break;
            case 2:
                printAllRecords(file);
                break;
            case 3:
                newRecord(file);
                break;
            case 4:
                break;
            case 5:
                break;
            default:
                break;
        }
    }
    return(0);
}

std::string getFileName(){

    std::string filename;

    std::cout << "Enter a filename:";
    std::cin >> filename;

    return filename;
}

std::fstream openFile(const std::string& filename){

    std::fstream file{filename, std::ios::in | std::ios::out | std::ios::binary};

    if(!file){
        std::cout << "File could not be opened." << std::endl;
        std::cout << "Creating new file." << std::endl;
        file = newFile(filename);
        std::cout << "Successfully created " << filename << std::endl;
    }
    else{
        std::cout << filename << " opened successfully" << std::endl;
    }

    return file;
}

std::fstream newFile(const std::string& filename){

    std::ofstream file{filename, std::ios::out | std::ios::binary};

    if(!file){
        std::cerr << "File could not be created." << std::endl;
        exit(EXIT_FAILURE);
    }

    HardwareData emptyRecord;

    for(int i=0; i<100; i++){
        file.write(reinterpret_cast<const char*>(&emptyRecord), sizeof(HardwareData));
    }
    file.close();

    return openFile(filename);
}

void printHeader(){
    std::cout << "Record#    Tool Name         Quantity        Cost \n";
    std::cout << "==================================================\n";

}

void printAllRecords(std::fstream& file){

    file.seekg(0);

    HardwareData record;
    file.read(reinterpret_cast<char*>(&record), sizeof(HardwareData));

    printHeader();
    while(!file.eof()){
        if(record.getRecordNum() != 0){
            record.printRecord();
        }
        file.read(reinterpret_cast<char*>(&record), sizeof(HardwareData));
    }
}

I was expecting to pass the file by reference and still be able to use that reference again on another function call. I am not getting any errors

Lateralus
  • 792
  • 9
  • 19
  • 2
    If you read to the end of the file you need to reset it to the beginning and clear the error from hitting EOF before you can continue to use it. – Retired Ninja Jul 20 '19 at 01:31
  • 1
    Thank you! Based on your suggestion, I found this thread https://stackoverflow.com/questions/5343173/returning-to-beginning-of-file-after-getline So I used: file.clear(); file.seekg(o, std::ios::beg); It seems to work well. Would that be an appropriate solution? – Lateralus Jul 20 '19 at 01:35
  • 1
    Yes! Or you can open the file multiple times and use each stream independently. (But there's a fairly small limit to open file handles, so beware of that solution.) – GaryO Jul 20 '19 at 01:41
  • [Be wary of `while(!file.eof())`.](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) You have avoided one of its nastier effects, but more than just eof can happen to block reading. – user4581301 Jul 20 '19 at 02:24
  • There is a difference between keeping a file open vs. open a file on demand and close it when you're done with reading/writing. I usually prefer the latter as the file is safely processed after closing (or I got an error and know that it failed) even if my appl. crashs later. Additionally, number of concurrent file handles supported by OS is a lesser issue in this case. In opposition, keeping a file open might be done to block other applications for concurrent access. MS seems to do so in their Office appl.s (may be with additional options in open) but I don't like this feature very much... – Scheff's Cat Jul 20 '19 at 08:13
  • See [How to debug small programs.](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – L. F. Jul 20 '19 at 09:53
  • Show definition for `HardwareData` – Barmak Shemirani Jul 20 '19 at 13:20

0 Answers0