last item in inventory viewed twice

In the code below i am having a bit of trouble. the program should allow you to view the items in a list of items, add a new item or edit and existing item on the list. i am having trouble with a few thing.

1.first when you view the inventory the last item is viewed twice and i have no clue why.

2. second is that the "edit an item" ( void changeRecord) doesn't work like at all and i have no clue why(well it displays but the info it displays is all garbage and when you enter data it doesn't save the data).

Any help would be appreciated, thank you for your time and i hope to hear back.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

void addRecord(fstream &);
void viewRecord(fstream &);
void changeRecord(fstream &);
int menu();

const int DESC_SIZE = 21;
const int DATE_SIZE = 11;

struct inventoryData

{
        char desc[DESC_SIZE];
        int quantity;
        double wholesale;
        double retail;
        char date[DATE_SIZE];

};


int main()
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);
    if (dataFile.fail())
    {
        dataFile.open("inventory.dat", ios::out);
        dataFile.close();
    }

    for (;;)
    {
        int selection = menu();
        if (selection == 4)
            break;

        switch (selection)
        {
        case 1:
            viewRecord(dataFile);
            break;
        case 2:
            addRecord(dataFile);
            break;
        case 3:
            changeRecord(dataFile);
            break;
        default:
            cout << "Invalid - Please use 1 to 4" << endl;
            break;
        }
    }

    return 0;
}

void addRecord(fstream &notused)
{
    fstream file("inventory.dat", ios::in | ios::out | ios::app | ios::binary);
    inventoryData item;

    cout << "Enter the data for the item" << endl;
    cout << "Name: ";
    cin.ignore();
    cin.getline(item.desc, DESC_SIZE);

    cout << "Number of Items: ";
    cin >> item.quantity;

    cout << "Wholesale cost: ";
    cin >> item.wholesale;

    cout << "Retail price: ";
    cin >> item.retail;

    cout << "Date (MO/DA/YEAR): ";
      cin >> item.date;

    file.write(reinterpret_cast<char *>(&item), sizeof(item));

    return;
}

void viewRecord(fstream &notused)
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);
    inventoryData item;
    while (dataFile)
    {
        dataFile.read(reinterpret_cast<char*>(&item), sizeof(item));
        cout << "Name: " << item.desc << endl;
        cout << "Number of Items: " << item.quantity << endl;
        cout << "Wholesale Cost: " << item.wholesale << endl;
        cout << "Retail Cost: " << item.retail << endl;
        cout << "Date: " << item.date << endl;
        cout << endl;
    }
}


void changeRecord(fstream &file)
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);

    inventoryData item;
    int recordNumber;

    cout << "Please choose a record number you want to edit" << endl;
    cin >> recordNumber;
    dataFile.seekg(recordNumber * sizeof(item), ios::beg);
    dataFile.read(reinterpret_cast<char *>(&item), sizeof(item));
    cout << "Name: " << item.desc << endl;
    cout << "Number of Items: " << item.quantity << endl;
    cout << "Wholesale cost: " << item.wholesale << endl;
    cout << "Retail price: " << item.retail << endl;
    cout << "Date: " << item.date << endl;
    cout << endl;

    cout << "Enter the new data:\n";
    cout << "Name: ";
    cin.ignore();
    cin.getline(item.desc, DESC_SIZE);
    cout << "Number of Items: ";
    cin >> item.quantity;
    cout << "Wholesale cost: ";
    cin >> item.wholesale;
    cout << "Retail price: ";
    cin >> item.retail;
    cout << "Date Date (MO/DA/YEAR)";
    cin >> item.date;

    dataFile.seekp(recordNumber * sizeof(item), ios::beg);
    dataFile.write(reinterpret_cast<char *>(&item), sizeof(item));

}

int menu()
{
    int menuSelection = 0;

    cout << fixed << showpoint << setprecision(2);
    cout << "----------Inventory----------" << endl;
    cout << "1 - View inventory" << endl;
    cout << "2 - Add an item" << endl;
    cout << "3 - Edit an item" << endl;
    cout << "4 - End Program" << endl;

    cin.clear();
    fflush(stdin);
    cin >> menuSelection;

    return menuSelection;
}
Last edited on
OK so i found something weird when I was testing out the same code i retested the edit option and found that when i entered 3 or more items it worked but it was off by one item. say i entered plates, pens and cups when i to edit option 2 in this case pens it edited cups but i see no reason in the code for this im still looking but i am finding nothing going to check the Dat file to see if maybe there is a problem there will update.
Last edited on
Ok so yea its off set by one like 0=1 and 1=2 and so on going to see if i can fix it or at least let the user know that the count starts from 0 because i don't really know how to fix that and the book isn't giving any clues any help with that will be welcomed but now the main problem is the double display for the last item on the list as it makes the code look ugly.
just changed it to this for now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void changeRecord(fstream &file)
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);

    inventoryData item;
    int recordNumber;

    cout << "Please choose a record number you want to edit " << endl;
    cout << "Please note that all record numbers start from 0 on" << endl;
    cout << "to edit item 1 you would have to enter a 0 to edit" << endl;
    cout << "item 2 enter 1 etc..." << endl;
    cin >> recordNumber;
    dataFile.seekg(recordNumber * sizeof(item), ios::beg);
    dataFile.read(reinterpret_cast<char *>(&item), sizeof(item));
    cout << "Name: " << item.desc << endl;
    cout << "Number of Items: " << item.quantity << endl;
    cout << "Wholesale cost: " << item.wholesale << endl;
    cout << "Retail price: " << item.retail << endl;
    cout << "Date: " << item.date << endl;
    cout << endl;

    cout << "Enter the new data:\n";
    cout << "Name: ";
    cin.ignore();
    cin.getline(item.desc, DESC_SIZE);
    cout << "Number of Items: ";
    cin >> item.quantity;
    cout << "Wholesale cost: ";
    cin >> item.wholesale;
    cout << "Retail price: ";
    cin >> item.retail;
    cout << "Date Date (MO/DA/YEAR)";
    cin >> item.date;

    dataFile.seekp(recordNumber * sizeof(item), ios::beg);
    dataFile.write(reinterpret_cast<char *>(&item), sizeof(item));

}
when you view the inventory the last item is viewed twice and i have no clue why
1
2
3
4
    while (dataFile)
    {
        dataFile.read(reinterpret_cast<char*>(&item), sizeof(item));
        cout << "Name: " << item.desc << endl;


You're not checking if read succeeds. When you reach the end of file, the read fails due to EOF, but you're always printing item.desc. Since the previous read consumed the last byte of the file, the failed read doesn't get to read anything, and you end up printing item.desc, unchanged since the previous loop iteration.

This "last item appears twice" is the common symptom of the beginner error of testing stream status in the loop condition - that goes all the way back to the equally wrong "while(!feof(fp))" that bites C beginners.

Test the success of the read before doing anything with its results: instead of "while (dataFile)" it should be "while(dataFile.read(reinterpret_cast<char*>(&item), sizeof(item))) { cout << "Name: " << item.desc ..."
Last edited on
in response to the above code wouldn't that stop the code from showing multiple inventory items limiting it to one. (at least that is what i'm experiencing)
wouldn't that stop the code from showing multiple inventory items limiting it to one.

No, the suggested change should work.
could you show your latest code for function viewRecord() please.
The First one is just to see the view record fast the second one is so you can use the program right away.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void viewRecord(fstream &notused)
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);
    inventoryData item;

        While (dataFile.read(reinterpret_cast<char*>(&item), sizeof(item)));
          {
        cout << "Name: " << item.desc << endl;
        cout << "Number of Items: " << item.quantity << endl;
        cout << "Wholesale Cost: " << item.wholesale << endl;
        cout << "Retail Cost: " << item.retail << endl;
        cout << "Date: " << item.date << endl;
        cout << endl;
            }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

void addRecord(fstream &);
void viewRecord(fstream &);
void changeRecord(fstream &);
int menu();

const int DESC_SIZE = 21;
const int DATE_SIZE = 11;

struct inventoryData

{
        char desc[DESC_SIZE];
        int quantity;
        double wholesale;
        double retail;
        char date[DATE_SIZE];

};


int main()
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);
    if (dataFile.fail())
    {
        dataFile.open("inventory.dat", ios::out);
        dataFile.close();
    }

    for (;;)
    {
        int selection = menu();
        if (selection == 4)
            break;

        switch (selection)
        {
        case 1:
            viewRecord(dataFile);
            break;
        case 2:
            addRecord(dataFile);
            break;
        case 3:
            changeRecord(dataFile);
            break;
        default:
            cout << "Invalid - Please enter a number 1 to 4" << endl;
            break;
        }
    }

    return 0;
}

void addRecord(fstream &notused)
{
    fstream file("inventory.dat", ios::in | ios::out | ios::app | ios::binary);
    inventoryData item;

    cout << "Enter the data for the item" << endl;
    cout << "Name: ";
    cin.ignore();
    cin.getline(item.desc, DESC_SIZE);

    cout << "Number of Items: ";
    cin >> item.quantity;

    cout << "Wholesale cost: ";
    cin >> item.wholesale;

    cout << "Retail price: ";
    cin >> item.retail;

    cout << "Date (MO/DA/YEAR): ";
      cin >> item.date;

    file.write(reinterpret_cast<char *>(&item), sizeof(item));

    return;
}

void viewRecord(fstream &notused)
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);
    inventoryData item;

        While (dataFile.read(reinterpret_cast<char*>(&item), sizeof(item)));
          {
        cout << "Name: " << item.desc << endl;
        cout << "Number of Items: " << item.quantity << endl;
        cout << "Wholesale Cost: " << item.wholesale << endl;
        cout << "Retail Cost: " << item.retail << endl;
        cout << "Date: " << item.date << endl;
        cout << endl;
            }
}


void changeRecord(fstream &file)
{
    fstream dataFile("inventory.dat", ios::in | ios::out | ios::binary);

    inventoryData item;
    int recordNumber;

    cout << "Please choose a record number you want to edit " << endl;
    cout << "Please note that all record numbers start from 0 on" << endl;
    cout << "to edit item 1 you would have to enter a 0 to edit" << endl;
    cout << "item 2 enter 1 etc..." << endl;
    cin >> recordNumber;
    dataFile.seekg(recordNumber * sizeof(item), ios::beg);
    dataFile.read(reinterpret_cast<char *>(&item), sizeof(item));
    cout << "Name: " << item.desc << endl;
    cout << "Number of Items: " << item.quantity << endl;
    cout << "Wholesale cost: " << item.wholesale << endl;
    cout << "Retail price: " << item.retail << endl;
    cout << "Date: " << item.date << endl;
    cout << endl;

    cout << "Enter the new information:\n";
    cout << "Name: ";
    cin.ignore();
    cin.getline(item.desc, DESC_SIZE);
    cout << "Number of Items: ";
    cin >> item.quantity;
    cout << "Wholesale cost: ";
    cin >> item.wholesale;
    cout << "Retail price: ";
    cin >> item.retail;
    cout << "Date Date (MO/DA/YEAR)";
    cin >> item.date;

    dataFile.seekp(recordNumber * sizeof(item), ios::beg);
    dataFile.write(reinterpret_cast<char *>(&item), sizeof(item));

}

int menu()
{
    int menuSelection = 0;

    cout << fixed << showpoint << setprecision(2);
    cout << "----------Inventory----------" << endl;
    cout << "1 - View inventory" << endl;
    cout << "2 - Add an item" << endl;
    cout << "3 - Edit an item" << endl;
    cout << "4 - End Program" << endl;

    cin.clear();
    fflush(stdin);
    cin >> menuSelection;

    return menuSelection;
}
There are two errors at line 6/96:

 
        While (dataFile.read(reinterpret_cast<char*>(&item), sizeof(item)));


1. "While" should be all lower case. (probably some sort of copy+paste error).

2. The line should not end in a semicolon.

What happens is, the semicolon represents an empty statement for the body of the loop. So the while loop reads each record of the file, and executes the empty statement each time. After the loop has ended, the rest of the code is executed, which displays the last record.

The line should read simply:
 
        while (dataFile.read(reinterpret_cast<char*>(&item), sizeof(item)))

(no semicolon).
Last edited on
Topic archived. No new replies allowed.