Reputation: 77
I have a data type that takes ID and Record location. The file contains around 1000 item, each contain id, first name, last name, GPA (each item total of 25 characters) My program seeks 25 characters for each loop, takes just the ID, put the ID and the record number in the table, etc..
Then, the user inputs the id, I retrieve the item from the table based on the given id, after that I get the record number, seek the item in the file, and then read the details.
Provided the headers of the recordlocation and the arrayhashtable classes, some stuff were removed to make it shorter
class RecordLocation{
public:
RecordLocation(int idd = -1, int rno = -1);
void setId(int);
int getId();
void setRNo(int);
int getRNo();
int Hash();
int LinearRehash(int initial_hash_value);
private:
int id;
int r_no;
};
/
typedef RecordLocation ItemType;
class ArrayHashTable{ //declares a class data type
public:
ArrayHashTable();//Fill info with null studnets
Error_Code RetrieveItem(ItemType& item, bool& found);
Error_Code InsertItem(ItemType item);
Error_Code DeleteItem(ItemType item);
void PrintAllItems();
private:
ItemType info[MAX_ITEMS];
int items;
};
/ data.txt short version
4609:hhhhh hhhhh :2:4737:ggggg ggggg :4:5530:rrrrr rrrr :4:4849:ttttttt tttttttttt:2:5563:ddddd dddd :2:4959:aaaa aaaaaaa :4:
/
void main(){
char buffer[26] = { '0' };
char id_buff[5];
int id;
ArrayHashTable object;
RecordLocation temp;
ifstream input("data.txt");
if (!input){
cout << "Unable to open file " << endl;
exit(1);
}
int i = 0;
int c;
//location 1
do{
input.seekg(25 * i);
input.read(id_buff, 4);
id = convert(id_buff);
temp.setId(id);
temp.setRNo(i);
object.InsertItem(temp);
i++;
}while (input);
//location 2
input.close();
}
Now what is baffling is with the following statement:
input.seekg(25 * 3);//3 is arbitrary
input.read(buffer, 25);
cout << buffer << endl;
If it is to be placed in location 1, then it is normal output. If it is in location 2 then the output is 0. if it is both in location 1 and 2, then both output is normal.
One way to solve this is to finish the do while statement, and then close the file and open it again, perform the statement and it is all normal. But this isn't an informed solution.
What I'm basically saying is that I'm done reading the file, and after that it seems that I can't get any more information out of it. I also did not add that part to ask the user for ID (to make it simpler)
Upvotes: 0
Views: 85
Reputation: 241861
If any call to input.read
fails, your program never notices, because you never check the return code of the read method. So we have to work out what happened, rather than seeing it. Fortunately, that's not too difficult in this case but in general you will find life to be easier if you get into the habit of checking for error returns.
We know that when Location 2 is reached, input
's failbit is set. That must be true, because the while loop doesn't exit until input
is false.
Since the failbit is set, neither the seekg
nor the read
do anything useful. The stream position is not modified, no data is read and the buffer is unmodified.
So when the program sends buffer
to std::cout
, what it is sending is whatever was previously in buffer
. If the code shown is at Location 1, then the fourth record will still be in buffer
. Otherwise, buffer
will contain a single '0' followed by NULs, since it was initialized to that. (0 and '0' are not the same.)
That perfectly explains the observed behaviour. Before you do the seekg, you need to clear input
's failbit.
In fact, the while
loop is also incorrect. After the last entry is read, input
will still be good
, and the loop will repeat. The read
will then fail, leaving id
unmodified but since you don't check, the program wiil contnue, using the bogus id. Now 'input' is false and the parse fails.
What you need to do is exit the loop if either the read
or the seekg
fail. The explicit test of the boolean conversion of input
is completely unnecessary and not useful because it comes too late.
Upvotes: 1
Reputation: 8514
According to cplusplus.com, for C++98:
If the eofbit flag is set before the call, the function fails (sets failbit and returns).
So once you have hit the end of the file, the EOF (end of file) bit is set and needs to be reset before using this function.
Note that for C++11:
The function clears the eofbit flag, if set before the call.
So, you could try a newer compiler, or clear the eof flag using clear
, e.g.:
input.clear();
Upvotes: 1