我有一个获取ID和记录位置的数据类型。 该文件包含大约1000个项目,每个项目包含id,名字,姓氏,GPA(每个项目共25个字符) 我的程序为每个循环寻找25个字符,只需要ID,将ID和记录号放在表中等等。
然后,用户输入id,我根据给定的id从表中检索项目,之后我得到记录号,在文件中查找项目,然后阅读详细信息。
提供了recordlocation和arrayhashtable类的标题,删除了一些东西以缩短它们
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中 短版
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();
}
现在令人困惑的是以下声明:
input.seekg(25 * 3);//3 is arbitrary
input.read(buffer, 25);
cout << buffer << endl;
如果要将其放置在位置1,那么它是正常输出。如果它在位置2,则输出为0.如果它在位置1和2中,则两个输出都是正常的。
解决此问题的一种方法是完成do while语句,然后关闭文件并再次打开它,执行语句就可以了。但这不是一个明智的解决方案。
我基本上说的是我已经读完了文件,之后我似乎无法从中获取更多信息。我也没有添加该部分来询问用户ID(使其更简单)
答案 0 :(得分:1)
根据cplusplus.com,对于C ++ 98:
如果在呼叫之前设置了eofbit标志,则该功能失败(设置 failbit and returns)。
因此,一旦你到达文件的末尾,EOF(文件结束)位就会被设置,需要在使用此功能之前重置。
请注意,对于C ++ 11:
如果在通话前设置,该功能会清除eofbit标志。
因此,您可以尝试更新的编译器,或使用clear
清除eof标志,例如:
input.clear();
答案 1 :(得分:1)
如果对input.read
的任何调用失败,您的程序将永远不会注意到,因为您从不检查read方法的返回代码。因此,我们必须弄清楚发生了什么,而不是看到它。幸运的是,在这种情况下这并不太难,但一般来说,如果你养成检查错误返回的习惯,你会觉得生活会更容易。
我们知道,当达到位置2时,会设置input
的failbit。这必须是真的,因为在input
为假之前,while循环不会退出。
由于设置了failbit,seekg
和read
都没有做任何有用的事情。不修改流位置,不读取数据且未修改缓冲区。
因此,当程序将buffer
发送给std::cout
时,它发送的内容就是之前buffer
中的内容。如果显示的代码位于位置1,则第四条记录仍将位于buffer
。否则,buffer
将包含单个'0',后跟NUL,因为它已初始化为NUL。 (0和'0'不一样。)
这完美地解释了观察到的行为。在进行搜索之前,您需要清除input
的failbit。
实际上,while
循环也是错误的。读完最后一个条目后,input
仍为good
,循环将重复。 read
将失败,id
保持不变,但由于您没有检查,程序将继续使用虚假ID。现在'input'为false并且解析失败。
如果read
或seekg
失败,您需要做的是退出循环。 input
的布尔转换的显式测试是完全没有必要的,因为它来得太晚了没用。