A lot of the code is quite fragile. The first problem I found was in entering the file name. If the user simply presses enter when asked for a file name, the cin.get() fails.
From the reference on this site,
c_plus_plus_com wrote: |
---|
failbit Either no characters were written or an empty c-string was stored in s. |
Hence, in function
open_input()
,
cin.clear()
is needed after attempting to read the user input. (the same apples when getting the output file name too).
1 2 3
|
cin.get(name, MAX_FILE_NAME + 1); // Gets at most MAX_FILE_NAME characters
cin.clear(); // reset cin after failed input
cin.ignore(81, '\n'); // Remove newline character from keyboard buffer
|
That was the easy bit. I gave the program a valid input filname, but since I don't have any sample test data, I just had some random nonsense in the file.
The program entered an infinite loop. This is what I mean by 'fragile', it breaks if there are any problems with either user input or file input.
The fix for the file input was not so very complicated, but it affected more than one line of code.
My current version:
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
|
SalesRecord_Array read_records(ifstream& in, int &n) // Allocate space for records & read them
{
in >> n; // Read number of records
if (n < 1 || in.fail())
return NULL; // No records to read return
while (in && in.get() != '\n'); // Clear enter after number of records in file
SalesRecord_Array records; // Pointer for array of records
records = new SalesRecord[n]; // allocate space for records
if (records == NULL)
{
cout << "Can not allocate memory!";
exit(1);
}
int i = 0;
while (i < n && records[i]read(in) ) // Attempt to Read each record
{
i++;
}
if (i != n)
{
cout << "Expected number of records: " << n << '\n';
cout << "Actual number of records: " << i << '\n';
n = i; // adjust count accordingy
}
return records; // Return pointer to array
}
|
The above code doesn't assume the input will work. It tests that each attempt to read a record has succeeded. That means member function
read()
returns a
bool
, not
void
.
In turn it means each part of that function needs its own extra checking, or it could enter an infinite loop, at the place where it tries to read until a newline is found.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
bool SalesRecord::read(ifstream& in) // Read record from input stream, does not read commission values
{
in.get(item_id, MAX_ID_LEN + 1); // Read id
while (in && in.get() != '\n'); // Clear Enter after id
in.get(item_name, MAX_NAME_LEN + 1); // Read name: Last, First
while (in && in.get() != '\n'); // Clear Enter after name
in >> quantity_sold >> regular_price; // Read quantity sold value
while (in && in.get() != '\n'); // Clear Enter at end of record
return bool(in);
}
|