What I would like to do:

-  Read data from text file
-  Display data from text file
-  Add new data to text file
-  Save new data to text file

The file format used is as follows:

Number of items in text file (3)

Name 1
Number 1
Date 1

Name 2
Number 2
Date 2

Name 3
Number 3
Date 3

etc.....

The code I have:

struct Shoes {

    char  Name[20];  
    unsigned int Number;  
    double Size; 

};

int Main()
{

    //Load file into struct////////////////////////////
    fstream input_file;

    // open the file
    input_file.open(FILENAME);

    Shoes Shoe[MAX];

    int i = 0;  //counter
    int num; //number of components in file

    input_file >> num;

    for(int i=0; i<num; i++)
    {   
        input_file >> Shoe[i].Name >> Shoe[i].Number >> Shoe[i].Size;
    }  
    ///////////////////////////////////////////////////// 

    //Add new element/////////////////////////////
    cout << "Enter Name, Number and Date: ";
    cin >> Shoe[i].Name >> Shoe[i].Number >> Shoe[i].Size;
    //////////////////////////////////////////////

    //Diaplay all + new element//
    for(int i=0; i<num; i++)
    {
        cout << "\n" << Shoe[i].Name << "\n" << Shoe[i].Number << "\n" << Shoe[i].Size << "\n\n";

    }
    ///////////////////////////

    //Write/save all to file//
    for(int i=0; i<num+1; i++)
    {
        input_file << Shoe[i].Name << "\n" << Shoe[i].Number << "\n" << Shoe[i].Size << "\n\n";

    }
    ///////////////////////////

    input_file.close(); 

}

The problem:

I can read the data from the text file into a struct array and add a new element to the array. But the code I have used does not work to write/save the data to the array. Could anyone help me or suggest a better way to do this. Ideally seperate functions to load, add a new element, display and save to a .txt file are needed.

Simplest: use std::ifstream for input, std::ofstream for output.

// read from file
{
    std::ifstream file( FILENAME ) ; // open file for input

    // read stuff
    // ...

} // file is closed when the stream goes out of scope

// over-write the contents of the file
{
    std::ofstream file( FILENAME ) ; // open file for output (truncated)

    // write stuff
    // ...

} // file is closed when the stream goes out of scope

If you want to use the same (ope)n std::fstream for both reading and writing, after reading, before over-writing:
a. clear any possible error state
b. seek to the beginning of the stream

What exactly is the behavior? Does it print the shoe data out correctly, or is that also failing?

One problem I see is that when you add an element, it overwrites the first one, rather than adding it to the end of the array. You probably want this:

    //Add new element/////////////////////////////
    cout << "Enter Name, Number and Date: ";
    cin >> Shoe[num].Name >> Shoe[num].Number >> Shoe[num].Size;
    num++;
    //////////////////////////////////////////////

Note that this only adds a single element, at that, since it isn't inside a loop.

As for converting the code into separate functions, this should be fairly dimply to do. The main complication is that you'll need to pass the count of the actual element explicitly to the print, insert and write functions. You can get that count from the read function:

int readShoes(fstream source, Shoe& shoe)
{
    int i = 0;  //counter
    int num; //number of components in file

    input_file >> num;

    for(int i=0; i<num; i++)
    {   
        input_file >> shoe[i].Name >> shoe[i].Number >> shoe[i].Size;
    }

    return num;
}

Sorry for the late reply. The printing of the data works. My main problem is writing to the file. I have the code below to add a new element, display the array with the new element and then write to the file. Once I run the code and open the file the file is blank. I tried using ios::app but that does the same.

Also I do not understand 'return num;'. Is it not easier to pass it as a variable? int read(num, shoe& shoe)?

Thanks for the help so far.

ofstream output_file;
output_file.open(FILENAME, ios::out);

//new element///
cout << "Enter Name, Number and Date: ";
cin >> Shoe[num].Name >> Shoe[num].Number >> Shoe[num].Date;
num++;
///////////////

//Output all + new element//
for(int i=0; i<num; i++)
{
    cout << "\n" << Shoe[i].Name << "\n" << Shoe[i].Number << "\n" << Shoe[i].Date << "\n\n";
}
///////////////////////////

//Write to file///////////
for(int i=0; i<num+1; i++)
{
    output_file << Shoe[i].Name << "\n" << Shoe[i].Number << "\n" << Shoe[i].Date << "\n\n";

}
//////////////////////////

output_file.close();

Edited 4 Years Ago by Hey90

Also what would be the best way to pass the shoe array?

Have you checked output_file to see if it is opening the file. ou can put this in your code after you open the file to make sure it is really opening the file.

if(output_file.fail())
    cout << "The file could not be opened!\n";

Also I am confused about arrays. Here (in the code below) I have a menu to load data and then display it in separate functions. When I load the data from the file into the Shoe struct using Load(num, Shoe) does this overwrite in the memory over what is already there for num and Shoe? When I then call Dispaly(num, Shoe) it just resets num to 0 and shoe to 0 and so displays nothing. How do I stop this and keep what I loaded into num and shoe originally? I hope this makes some sort of sense.

int main()
{
    int num = 0;
    Shoes Shoe[MAX];   // the database
    char Input;         

    // loop until the user wishes to exit
    while (1) {

    // show the menu of options
    cout << "1. Load Data" << endl;
    cout << "2. Display" << endl << endl;

    // user choice
    cout << "Choose an options: ";
    cin >> Input;
    cout << endl;

    switch(Input) {

        case '1':
        Load(num, Shoe);
        break;

        case '2':
        Display(num, Shoe);
        break;

    }
  }
}

--------------------------------------------------------------------------------------

int Load(int num, int Shoes Shoe[])
{
    //Load file into struct////////////////////////////
    fstream input_file;

    // open the file
    input_file.open(FILENAME);

    Shoes Shoe[MAX];
    int i = 0;  //counter
    int num; //number of components in file

    input_file >> num;

    for(int i=0; i<num; i++)
    {   
        input_file >> Shoe[i].Name >> Shoe[i].Number >> Shoe[i].Size;
    }  
    ///////////////////////////////////////////////////// 

    input_file.close();
}

----------------------------------------------------------------------------------------------------

void Display(int num, Shoes Shoe[])
{

    int i; //counter    

    cout << num << "\n\n";

    for(int i=0; i<num; i++)
    {
        cout << Shoe[i].Name << "\n" << Shoe[i].Number << "\n" << Shoe[i].Date << "\n\n";

    }

}

Edited 4 Years Ago by Hey90

When the program goes back to main it resets num = 0?

You have to pass num by reference if you want it to hold the data between the functions. The way you are doing it now is passing by value. Here is a little example of the difference.

#include <iostream>

using namespace std;

void PassRef(int & num)
{
    num += 5;
}

void PassValue(int num)
{
    num += 5;
}

int main()
{
    int number = 10;
    cout << "before PassRef() number = " << number << endl;
    PassRef(number);
    cout << "after PassRef() number = " << number << endl;

    number = 10;
    cout << "before PassValue() number = " << number << endl;
    PassValue(number);
    cout << "after PassValue() number = " << number << endl;
    cin.get();
    return 0;
}

Edited 4 Years Ago by NathanOliver

Ok I understand thank you very much. It is working now.

This article has been dead for over six months. Start a new discussion instead.