0

I tried earlier to use a for loop to put data in but became too problematic. So I tried to use a while loop, it works but when I tried to debug it it continued to put -858993460 into every slot. The .dat file is in the right spot and opens.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

struct record
{
    int item_id;
    string item_type;
    float item_price;
    int num_stock;
    string item_title;
    string item_author;
    int year_published;
};

void read_all_records(record records[], int &valid_entries);
int num_inventory_of_type(record records[], string type, int &valid_entries);
const int max_array = 100;
int main()
{
    int valid_entries = 0;
    record records[max_array];
    read_all_records(records, valid_entries);

    cout << "Stock Report" << endl;
    cout << "------------" << endl;
    int book = num_inventory_of_type(records, "book", valid_entries);
    cout << "Book's In Stock: " << book << endl;
    int cd = num_inventory_of_type(records, "cd", valid_entries);
    cout << "CD's In Stock: " << cd << endl;
    int dvd = num_inventory_of_type(records, "dvd", valid_entries);
    cout << "DVD's In Stock: " << dvd << endl;

    return 0;
}

void read_all_records(record records[], int &valid_entries)
{
    ifstream invfile;
    invfile.open("inventory.dat"); 
    if (!invfile.is_open())
    {
        cout<<"file open failed";
        exit(1);
    }
    while(invfile.good() && valid_entries < max_array)
    {
        invfile >> records[valid_entries].item_id >> records[valid_entries].item_type
            >> records[valid_entries].item_price >> records[valid_entries].num_stock
            >> records[valid_entries].item_title >> records[valid_entries].item_author
            >> records[valid_entries].year_published;
        if(!invfile.good())
            break;
        valid_entries++;

    }
    invfile.close();

}
int num_inventory_of_type(record records[], string type, int &valid_entries)
{
    int count = 0;
    int holder = 0;
    for (int count = 0; count<valid_entries; count++);
    {       
        if (records[count].item_type == type)
        {
            holder+=records[count].num_stock;

        }
    }

    return holder;
}

the .dat file is

123456
book
69.99
16
Problem_Solving_With_C++
Walter_Savitch
2011
123457
cd
9.99
32
Sigh_No_More
Mumford_and_Sons
2010
123458
dvd
17.99
15
Red_State
Kevin_Smith
2011
123459
cd
9.99
16
The_Church_Of_Rock_And_Roll
Foxy_Shazam
2012
123460
dvd
59.99
10
The_Walking_Dead_Season_1
Robert_Kirkman
2011 

all are on new lines, no spaces.

Basically it should start, run the read_all_records function and put the .dat data into the array. However, I put the cout << records[count].item_id; in the while loop just to see if the data was actually going in, and I get -858993460 each time. After that it should run the next function 3 times and return how many of each books there are.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Nogg
  • 337
  • 1
  • 4
  • 18
  • `while(!invfile.eof())` <-- well there's your error. – Mooing Duck Mar 28 '12 at 22:20
  • 1
    StackOverflow etiquette is to give a minimum example - the least amount of code possible that still displays your error. Nobody wants to look at all that. It might help you figure it out, too. – cmo Mar 28 '12 at 22:20
  • What is the error Mooing Duck? @CycoMatto, I apologize. I just wanted everyone to understand what the issue is because I have zero clue. – Nogg Mar 28 '12 at 22:22

3 Answers3

1

This isn't a direct answer to the problem, but perhaps it will go away after a refactoring:

std::istream& operator>>(std::istream& is, record& r) {
    return is >> r.item_id >> r.item_type >> … >> r.year_published;
}

int main () {
    if (std::ifstream invfile("inventory.dat")) {
        std::vector<record> records((std::istream_iterator<record>(invfile)),
                                     std::istream_iterator<record>());

        num_inventory_of_type(records, "dvd");
        num_inventory_of_type(records, "cd");
        num_inventory_of_type(records, "book");
    }
}

If you still want to print out each record as you read it, the code can be rearranged as follows:

        std::vector<record> records;
        for (std::istream_iterator<record> i(invfile);
             i != std::istream_iterator<record>(); ++i)
        {
            records.push_back(*i);
            std::cout << i->item_id << "\n";
        }
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • After the last record is read in, `!invfile.eof()` succeeds, so you read one more "record" after the last valid record. Now, this would explain the garbage you're seeing, but only on the last record, whereas the wording of your question implies that every record has a problem, which doesn't make much sense. In any event, you really shouldn't be writing code that way. The above answer is shorter, cleaner and, importantly, not vulnerable to off-by-one errors such as your code exhibits. Don't be so quick to dismiss help just because it isn't offered on your terms. – Marcelo Cantos Mar 28 '12 at 22:36
  • OK, it finally clicked (after reading the other answers). You are setting `record[0]`, then printing out `record[1]`, which obviously doesn't have anything in it yet. This doesn't negate the `!invfile.eof()` bug, mind you. – Marcelo Cantos Mar 28 '12 at 22:50
1

You used the integer type int on item_price. invfile >> records[count].item_price will then only extract 69 instead of 69.99, thus resulting in a error when you try to extract the year_published.

Use a float or double instead.

struct record
{
    int item_id;
    string item_type;
    float item_price;
    int num_stock;
    string item_title;
    string item_author;
    int year_published;
};

/* skipped identical lines */

while(invfile.good() && count < max_array)
{
    invfile >> records[count].item_id >> records[count].item_type
        >> records[count].item_price >> records[count].num_stock
        >> records[count].item_title >> records[count].item_author
        >> records[count].year_published;
        cout << records[count].item_price << endl;
        if(!invfile.good())
            break;
    cout << records[count].item_id << endl;
        count++;
}
invfile.close();

Note that you have an extra semicolon in for (int count = 0; count<max_array; count++);. I guess you didn't intend this, so remove it.

Zeta
  • 103,620
  • 13
  • 194
  • 236
  • Im bashing my head in right now for not seeing this. OMG. I spent seriously 10 hours trying to solve this...thank you SO much – Nogg Mar 28 '12 at 22:45
  • @Nogg: It's sometimes a good idea to print more values ;) - the id was valid, the `item_type` too, but the `item_price` was wrong. Also activate compiler warnings (`-Wall -Wextra` in gcc). Try to implement `std::istream& operator>>` which Marcelo provided, this will make your code a little bit easier to read. – Zeta Mar 28 '12 at 22:49
  • would you mind helping me out one more step further? I will edit my code after this, could you go over it and tell me why when I output it outputs the books correct but the cd's and dvd's output as zero. Nothing is different between the three. – Nogg Mar 28 '12 at 23:24
  • I already fixed this - see my last statement: `for (int count = 0; count – Zeta Mar 29 '12 at 08:04
0

You need to change int item_price; to a float so -> float item_price;

and as mentioned above you need to swap the count++; and cout << records[count].item_id line.

After these two changes it will work properly.

struct record
{
    int item_id;
    string item_type;
    float item_price; // <--- Needs to be a float
    int num_stock;
    string item_title;
    string item_author;
    int year_published;
};


// This order is required because you are storing in the current 'count' record and then you need to print it.  Then increment the count to store the next record  
cout << records[count].item_id;
count++;
Michael Wildermuth
  • 5,762
  • 3
  • 29
  • 48