【发布时间】:2025-12-10 11:15:02
【问题描述】:
我有一个如下所示的测试文件:
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 并进行比较。相反,它仍然阅读安德森鲍勃。
关于为什么会发生这种情况的任何想法?
谢谢
【问题讨论】:
-
这个中间?
middle = (first + lineNumbers) / 2; -
@rafa 您的整个方法存在缺陷。最大的错误是您在以文本模式打开的文件上使用了
seekg。当您以这种方式打开文件时,您无法可靠地使用此类功能。seekg在以二进制ios:binary模式打开的文件上的工作方式与您期望的一样。你的代码注定要失败的原因是,在文本模式下,翻译是针对行尾和 EOF 完成的,你不知道也不想跟踪(如果你会失去理智)试过)。如果您要这样做,请以二进制模式打开文件并从那里解决。 -
@PaulMcKenzie 您的解决方案是正确的,让我得以进步。现在,我对 Armstrong-Jones Mike 有意见。当 middle 设置为 4 时,它会从最后一行读取“73”作为姓氏,而 Mike 在正确的行读取第一行。因此,它显示为无法找到正确的记录
-
@rafa 我向您发布了我的建议,作为
seekg问题的答案。所以你是说还有一个问题?如果是这样,那么也许应该发布另一个问题?另外,57 这个神奇的数字是怎么得出的? -
不会让您的 stream.ignore 跳过字符,直到它到达 \n。即它永远不会读取第一行