如何从二进制文件中读取最后一行
how to read last line from binary file
有一个二进制文件包含这样的数据(这两个文件都有字符串数据类型);
Tyler Bred
Guus Hiddink
Didier Droggba
我想读取位于文件末尾的数据(在这种情况下,确切地说是Didier和Droggba)。所以我写了一个代码来处理它,如下所示;
结构:
struct user
{
string id;
string pwd;
};
读取数据的代码:
void confirm(const char* f)
{
user u;
ifstream in;
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
}
我运行了上面的代码,但没有成功。我什么都没有。所以我更改了这样的代码;
void confirm(const char* f,user* u)
{
user u1;
ifstream in;
in.open(f, ios::in | ios::binary);
while (in >> u1.id >> u1.pwd)
{
if (!in)
{
cout << "failed to open file" << endl;
exit(0);
}
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
}
delete u;
}
}
不幸的是,这并没有奏效。我收到"访问违规…"错误消息。
我尝试了许多其他代码来解决这个问题,但这些东西也不起作用。我认为问题是:如果(in.of())但我不知道该如何改变它来解决这个问题。如果有人指出我的错误或给我小费,我将不胜感激。
文件中的每一行末尾通常都有一个换行符(在某些操作系统中为字符***s***)。您的代码。。。
while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
假设您在读取最后一个人的名字后会点击eof
,但当您读取该姓氏时,如果该行有一个换行符,您还没有点击eof()
,那么下一个while (in >>...
测试将失败,并跳过while
-循环体,永远不会进入if (in.eof())
。
你能做的最小的改变来修复你的代码:
while (in >> u.id >> u.pwd >> std::skipws)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
>> std::skipws
将前进到文件末尾或下一个名称,如您所希望的那样设置eof()
标志。
行实际上并不存在于二进制文件中,除非是作为约定,就像一行是由换行符'n'
终止的字节序列(与' '
和'n'
都不同)(该约定可能因操作系统而异,某些操作系统使用"rn"
或"nr"
甚至'r'
作为行尾)。
您可以使用std::getline
循环读取行,直到文件结束,将行保留在某个std::string
中,并解析最后一行字符串(使用std::istringstream、sscanf等)
或者,如Tony D’answer所建议的,将行尾视为空格分隔符。然后,具有Tyler Bred John Doe
的单个行将被处理为两个行Tyler Bred
和John Doe
。
一种可能是这样的:
void confirm(const char* f)
{
user u;
ifstream in(f, ios::in | ios::binary);
while (in >> u.id >> u.pwd)
;
cout << "Registration Complete.n";
cout << "Your user information:n";
cout << "ID:" << u.id << " " << "Password: " << u.pwd << "n";
}
然而,如果我这样做的话,我会为user
结构定义一个operator>>
,类似于以下内容:
struct user {
std::string id;
std::string pwd;
friend std::istream &operator>>(std::istream &is, user &u) {
return is >> u.id >> u.pwd;
}
};
这将主代码简化了一点,变成这样:
user u;
while (in >> u)
;
诚然,在这种情况下(只有两个字段),这只是一个微小的改进,但这仍然是一个小的改进,当你有更多的字段要处理时(尤其是当读取对象的代码变得更复杂时),将读取对象的码码隔离到自己的函数中可以大大简化代码的其余部分。
请注意,无论最后一个数据后面的文件中有多少空白,这都是有效的(尾随或缺少空白不会影响结果)。
实时演示
delete u
这将释放与user
结构相关联的存储器。如果文件中有超过1行,您将获得访问冲突,因为在下一次迭代中,您将再次接触与user
结构相关的内存。
还有这个:
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
是测试文件是否成功打开的正确方法。此外,您还需要处理每次读取中的换行符。
我假设你在找到第一场比赛后想退出。你应该这样修改你的代码:
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
delete u;
break;
}
尽管我不喜欢这种被调用者负责释放内存的模式。我建议让调用者决定如何处理user
结构中传递的内存。作为一个额外的建议,使用调试器可能有助于诊断此类问题。
- 读取文件的最后一行并输入到链接列表时出错
- 读取最后一行代码算法 - c++ 时出现问题
- 这段代码的最后一行在做什么?
- 我没有得到产量最低的产品.我该如何纠正它?最后一行是最低销售产品的输出.谢谢
- 丢失读入的每一行输入中的最后一个令牌
- 如何只阅读最后一行的开头?
- Ofstream一直给我函数的最后一行,而不是显示所有内容
- Codelite构建仅呈现最后一行的输出
- 以下递归程序的最后一行是如何工作的
- 如何在应用程序进行大量printf时,在固定输入的终端中设置最后一行
- 如何有效地读取C 中的最后一行文件
- 标准输入未读取最后一行
- 特征:将每一行除以最后一行
- cout 用于仅打印最后一行的 2D 字符串矢量
- 如何确定输入文件中的一行是否是最后一行?C++
- 多功能阵列最后一行相同的结果
- 为什么输入文件的最后一行运行两次?
- Fscanf 未从文件的最后一行 (C/C++) 读取预期值
- C++ - 将数字表从文件读取到 2D 数组中(仅存储最后一行)
- 在一行最后一个单词之后立即退出While循环