Thread: structures and files

  1. #1
    Registered User eth0's Avatar
    Join Date
    Dec 2003
    Posts
    164

    structures and files

    Myself and everyone else seems to have given in on the old thread, so I have abandoned the method I was using last time with functions and gone for a slightly easier route.

    I need to write my array of structures to a file, and then write them back in again at a later stage. The code I am using is in the middle of main() in the 'switch' statement
    However, suprise suprise, its still giving me trouble and I can't get it to work

    Can anyone see where this is going wrong?

    I really really need to get this working. I would be eternaly grateful if anyone could sort this out for me. I have been working on this section for over 3 days now......its inhumaine...heh.

    Thank you

    Code:
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    struct StockItem
    {
        int code;
        char desc[20];
        float price;
    }stock[125];
    
    void disp_menu(void);
    struct StockItem enter_data();
    void see_stock(StockItem stock[125], int num_items);    
    
    main()
    {
        int ans, ctr;
        int num_items = 0;
        FILE *item_file = NULL;
        
        do
        {
            do
            {
                disp_menu();
                cin >> ans;
            } while ((ans<1) || (ans>6));
            
            switch (ans)
            {
                case 1: 
                    stock[num_items] = enter_data();
                    num_items++;
                    break; 
                case 2: 
                    see_stock(stock, num_items);
                    break;
                case 3: {
                    item_file = fopen("items.txt", "ab");
                    for (ctr=0;ctr<125;++ctr)
                    {
                        fwrite(&stock[ctr], sizeof(StockItem), 3, item_file);
                    }
                    fclose(item_file);
                    break; }
                case 4: {
                    item_file = fopen("items.txt", "rb");
                    for (ctr=0;ctr<125;++ctr)
                    {
                        fread(&stock[ctr], sizeof(StockItem), 3, item_file);
                    }
                    fclose(item_file);                                   
                    break; }
                default:
                    break;
            } 
        }while (ans!=5);
            
        return 0;
    
        system("PAUSE");
        return 0;
    }
    
    void disp_menu()
    {
        cout << "\n*** The Corner Shop ***\n\n";
        cout << "Select an option: \n\n";
        cout << "\t1. Enter new stock " << endl;
        cout << "\t2. See current stock " << endl;
        cout << "\t3. Save stock to disk " << endl;
        cout << "\t4. Load stock from disk " << endl;
        cout << "\t5. Exit \n" << endl;
        cout << "option> ";
    }
    
    StockItem enter_data()
    {
        StockItem stock_item;
        
        cout << "\n\nWhat is the product code: ";
        cin >> stock_item.code;
        cout << "What is the product description: ";
        fflush(stdin);
        cin.getline(stock_item.desc, 20);
        cout << "What is the product price: ";
        cin >> stock_item.price;  
        
        return (stock_item);
    }
    
    void see_stock(StockItem stock[125], int num_items)
    {
        int ctr;
        char ret;
    
        cout << "\n\nHere is the stock listing:\n\n";
        for (ctr = 0; ctr < num_items; ++ctr)
        {
            cout << "Item " << ctr+1 << endl;
            cout << "Product Code: " << stock[ctr].code <<  endl;
            cout << "Product Description: " << stock[ctr].desc << endl;
            cout << "Price: " << stock[ctr].price << endl;
            cout << "------------------------------------------------\n";
        }
    }

  2. #2
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    What you are doing is perhaps clumsy and awkward, but not unforgiviable for a beginer. the only outright bug I see is that you load 3 complete structures per entry in your loop.
    Code:
    fread(&stock[ctr], sizeof(StockItem),1,item_file);
    // you may also need a cast
    fread(static_cast<void *>(&stock[ctr]), sizeof(StockItem),1,item_file);
    Note also that ".txt" is highly misleading, you have a file of fixed length binary memory image records, not a text file. You will normally only do this when not only is speed critical but also random access (seek) is useful.

  3. #3
    Registered User eth0's Avatar
    Join Date
    Dec 2003
    Posts
    164
    hi grib, thanks for the suggestions.
    I thought the integer (3) was related to how many members there was in the structure. I must have read the docs wrong.

    I have included your suggestion, however I still cannot get the structures to save and reload, although it appears something is saved in the file created.
    I am not sure if that part is correct, but whatever I do, I cannot get the array of structures to repopulate.

    Please Help !

  4. #4
    Registered User eth0's Avatar
    Join Date
    Dec 2003
    Posts
    164
    I have just discovered that the data is being loaded back into the program, the problem is when calling this function

    see_stock(stock, num_items);

    the 'num_items' will be incorrect as the program has bee restarted.

    Can anyone tell me how to find a way of seeing how many arrays are in the program?
    Then I can pass that figure to the function and all should be correct.

    Thanks

  5. #5
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    You already know how many stock_items you have, you have 125, most of them garbage. When you save the file you always save 125 items, most of them garbage. When you load you have no way of knowing what items are not garbage. The first way around this is to only save those items that are not garbage. Then, when you load, keep track of how many items you have loaded. This is done by checking the return value from fread. fread returns the nuber of records read. The other problem is we should be prepared for the possibilty of having more records in the file than we have space for records.

    The easyest way to change your program is probably
    Code:
     case 3: {
         item_file = fopen("items.txt", "ab");
         fwrite(stock, sizeof(StockItem), num_items, item_file);
         fclose(item_file);
         break; }
     case 4: {
         item_file = fopen("items.txt", "rb");
         num_items = fread(stock, sizeof(StockItem), 125, item_file);
         fclose(item_file);                                   
         break; }
    This is also a very low-level very fast way to do this, but we are always limited to a maximum of 125 (or another compile time constant) number of records.

  6. #6
    Registered User eth0's Avatar
    Join Date
    Dec 2003
    Posts
    164
    Thank you. I have not got all this section working


  7. #7
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164

    Re: structures and files

    Originally posted by eth0
    Code:
            switch (ans)
            {
                case 1: 
                    stock[num_items] = enter_data();
                    num_items++; 
                    break; 
                case 2: 
                    see_stock(stock, num_items);
                    break;
                case 3: {
                    item_file = fopen("items.txt", "ab");
                    for (ctr=0;ctr<125;++ctr)
    Change this to for (ctr=0;ctr<num_items;++ctr)
                    {
                        fwrite(&stock[ctr], sizeof(StockItem), 3, item_file);
                    }
                    fclose(item_file);
                    break; }
                case 4: {
                    item_file = fopen("items.txt", "rb");
                    for (ctr=0;ctr<125;++ctr)
    Change this to a while statement to read until EOF and after each read 
    increment num_items.  Now num_items will represent the 
    number of array entries are loaded
                    {
                        fread(&stock[ctr], sizeof(StockItem), 3, item_file);
                    }
                    fclose(item_file);                                   
                    break; }
                default:
                    break;
            } 
        }while (ans!=5);
            
        return 0;
    
        system("PAUSE"); Gackkkkkk!!!
        return 0;
    }
    In the above, when you write your file, the read it in again, you've lost the number of actual records available.

    Grib's idea is quite workable, too.

    Originally posted by eth0
    Code:
    StockItem enter_data()
    {
        StockItem stock_item;
        
        cout << "\n\nWhat is the product code: ";
        cin >> stock_item.code;
        cout << "What is the product description: ";
        fflush(stdin);  Gackkkkkk!!!
        cin.getline(stock_item.desc, 20);
        cout << "What is the product price: ";
        cin >> stock_item.price;  
        
        return (stock_item);
    }
    fflush is not defined in the standard and will not work for many compilers. Best to look into the cin.ignore methof to clear the stream.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  8. #8
    Registered User eth0's Avatar
    Join Date
    Dec 2003
    Posts
    164
    In the above, when you write your file, the read it in again, you've lost the number of actual records available.
    That was what took me 3 days to work out....lol.
    I think my original method of using functions was probably working, it was the 'num_items' that caught me out.
    Oh well, it was a great learning experience.

    fflush(stdin); Gackkkkkk!!!
    This is down to my bad lecturer who seems to be mixing C and C++, hence things like 'fopen("items.txt", "ab")' which have now been removed, along with all the other C syntax I had in there.

    system("PAUSE"); Gackkkkkk!!!
    Due to me switching my code over from my Linux boxen, which I live on......over to a windows compiler, as the lecturer inisits on. Just happened to be DevC++, which normally needs it. It somehow managed to wiggle its way into this code.

  9. #9
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    >>along with all the other C syntax I had in there.
    In that case, change main( ) to either int main( ) or int main( int argc, char **argv ).
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  10. #10
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Originally posted by eth0
    fflush(stdin); Gackkkkkk!!!
    This is down to my bad lecturer who seems to be mixing C and C++...
    This is not good in either C nor C++. If your instructor is teaching fflush(stdin); or system("pause"); s/he is not teaching standard C/C++.

    Just wait until they get to getch(); -- another non-standard function that is not in most compilers.

    Originally posted by eth0
    Due to me switching my code over from my Linux boxen, which I live on......over to a windows compiler, as the lecturer inisits on.
    Sorry, but he's a dweeb. If he's teaching Windows Programming, OK. If he's teaching a language, it should not matter what platform you do your code on. He seems to be making you switch because he himself doesn't know the standard and doesn't want to figure out what isn't portable from compiler to compiler.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Create Copies of Files
    By Kanshu in forum C++ Programming
    Replies: 13
    Last Post: 05-09-2009, 07:53 AM
  2. How to create a C project with multiple source files
    By MSF1981 in forum C Programming
    Replies: 5
    Last Post: 03-22-2009, 09:25 AM
  3. Random access files and structures
    By DLR in forum C Programming
    Replies: 8
    Last Post: 04-21-2006, 03:24 PM
  4. header and source files
    By gtriarhos in forum C Programming
    Replies: 3
    Last Post: 10-02-2005, 03:16 AM
  5. more header files
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 10-28-2001, 01:56 PM