文本文件二进制搜索
Text File Binary Search
我有一个测试文件,如下所示:
Ampersand Gregorina 5465874526370945
Anderson Bob 4235838387422002
Anderson Petunia 4235473838457294
Aphid Bumbellina 8392489357392473
Armstrong-Jones Mike 8238742438632892
代码如下:
#include <iostream>
#include <string>
#include <fstream>
class CardSearch
{
protected:
std::ifstream cardNumbers;
public:
CardSearch(std::string fileName)
{
cardNumbers.open(fileName, std::ios::in);
if (!cardNumbers.is_open())
{
std::cout << "Unable to open: " << fileName;
}
return;
}
std::string Find(std::string lastName, std::string firstName)
{
// Creating string variables to hold first and last name
// as well as card number. Also creating bools to decide whether
// or not the person has been found or if the last name is the only
// identifier for a found person
std::string lN;
std::string fN;
std::string creditNumber;
bool foundPerson = false;
// By using the seekg and tellg functions, we can find our place
// in the file and also calculate the amount of lines within the file
cardNumbers.seekg(0, std::ios::beg);
cardNumbers.clear();
std::streamsize first = cardNumbers.tellg();
cardNumbers.ignore(std::numeric_limits<std::streamsize>::max());
cardNumbers.clear();
std::streamsize last = cardNumbers.tellg();
cardNumbers.seekg(0, std::ios::beg);
std::streamsize lineNumbers = (last / 57);
std::streamsize middle;
while (first <= lineNumbers)
{
middle = (first + lineNumbers) / 2;
// middle * 57 takes us to the beginning of the correct line
cardNumbers.seekg(middle * 57, std::ios::beg);
cardNumbers.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
cardNumbers >> lN >> fN;
if (lN < lastName)
{
first = middle + 1;
}
else if (lN > lastName)
{
lineNumbers = middle - 1;
}
else
{
if (fN < firstName)
{
first = middle + 1;
}
else if (fN > firstName)
{
lineNumbers = middle - 1;
}
else if (fN == firstName)
{
foundPerson = true;
break;
}
}
}
if (foundPerson)
{
// When a person is found, we seek to the correct line position and
// offset by another 40 characters to receive the card number
cardNumbers.seekg((middle * 57) + 40, std::ios::beg);
std::cout << lN << ", " << fN << " ";
cardNumbers >> creditNumber;
return creditNumber;
}
return "Unable to find person.n";
}
};
int main()
{
CardSearch CS("C:/Users/Rafael/Desktop/StolenNumbers.txt");
std::string S = CS.Find("Ampersand", "Gregorina");
std::cout << S;
std::cin.ignore();
std::cin.get();
return 0;
}
除了列表中的第一条记录外,我可以检索到所有记录。看起来好像seekg在寻找正确的位置,但cardNumbers没有读取正确的信息。当"middle"设置为0时,seekg应查找第0行(middle*57),读取Ampersand Gregorina并进行比较。相反,它仍然在读安德森·鲍勃。
关于为什么会发生这种情况,有什么想法吗?
感谢
LineNumbers正在被循环修改,从4到1再到-1。-1使您的循环过早终止,因此您无法正确拾取第一个条目。
这似乎是一个家庭作业问题,所以我希望你能用它来引导自己找到答案。
使用seekg
等函数时,最好以binary mode
打开文件,而不是像您的代码现在所做的那样以文本模式打开文件。换句话说,你应该这样做:
cardNumbers.open(fileName, std::ios::in | std::ios::binary);
原因是以文本模式打开文件将允许完成行末翻译。这使得seekg
、tellg
等函数在最好的情况下不稳定(或幸运地工作),在最坏的情况下对文本处理毫无用处。
当文件以二进制模式打开时,seekg
和其他函数族会按预期工作,因为没有行末转换。实际上,您将在指定的文件中查找字节偏移量,而不会被行末转换所丢弃。
此外,一旦这样做,行中数据的长度不仅包括可见文本,还包括组成行序列末尾的不可见字符。因此,在二进制模式下,你手工计算的57是不正确的——它应该是58或59,这取决于你使用的是Linux/Unix还是Windows。
相关文章:
- 有根的二进制搜索树.保留与其父级的链接
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- 二进制搜索树叶数问题
- 为什么二进制搜索在我的测试中不起作用
- 正在尝试重载二进制搜索树分配运算符
- 我的二进制搜索程序只是关闭了
- 二进制搜索的终止点
- 递归二进制搜索与字符串数组
- 测试树是否为二进制搜索树
- 如何二进制搜索结构向量并在适当的索引处插入
- 如果你有一个固定大小的数组,你需要遍历它!n次,使用二进制搜索如何改变时间复杂性
- 字符串的递归二进制搜索-C++
- 使用二进制搜索树中的迭代器对象访问左侧节点
- 二进制搜索树没有匹配的函数调用
- 二进制搜索不适用于特定输出
- 如何在向量上进行二进制搜索以找到具有特定id的元素
- 如何将Z3_ast导出为二进制以及如何搜索函数名称?
- 二进制搜索树不变的标头文件
- 在C++中搜索二进制文件分隔符时出现不正确的偏移量
- 可视化 在 c++ 中读取和搜索二进制文件