我有一个C ++程序需要返回一个特定单词出现的行。例如,如果我的文件是这样的:
the cow jumped over
the moon with the
green cheese in his mouth
我需要打印出“with”的行。所有程序获取的是从文件开头的偏移量(在本例中为24,因为“with”是从文件开头的24个字符)。
如何打印整条线“月亮与”,只有偏移?
非常感谢!
答案 0 :(得分:3)
您可以通过单独读取每一行并在读取之前和之后记录文件位置来完成此操作。然后它只是一个简单的检查,看看该字的偏移是否落在该行的范围内。
#include <iostream>
#include <fstream>
#include <string>
std::string LineFromOffset(
const std::string &filename,
std::istream::pos_type targetIndex)
{
std::ifstream input(filename);
// Save the start position of the first line. Should be zero of course.
std::istream::pos_type lineStartIndex = input.tellg();
while(false == input.eof())
{
std::string line;
std::getline(input, line);
// Get the end position of the line
std::istream::pos_type lineEndIndex = input.tellg();
// If the index of the word we're looking for in the bounds of the
// line, return it
if(targetIndex >= lineStartIndex && targetIndex < lineEndIndex)
{
return line;
}
// The end of this line is the start of the next one. Set it
lineStartIndex = lineEndIndex;
}
// Need a better way to indicate failure
return "";
}
void PrintLineTest()
{
std::string str = LineFromOffset("test.txt", 24);
std::cout << str;
}
答案 1 :(得分:2)
一个好的解决方案是从头开始读取文件直到所需的位置(由@Chet Simpson回答)。如果你想要优化(例如非常大的文件,位于中间某处,典型的行相当短),你可以向后读取文件。但是,这仅适用于以二进制模式打开的文件(类似于unix的平台上的任何文件;在Windows上打开带有ios_base::binary
参数的文件。)
算法如下:
代码(在Windows上测试):
std::string GetSurroundingLine(std::istream& f, std::istream::pos_type start_pos)
{
std::istream::pos_type prev_pos = start_pos;
std::istream::pos_type pos;
char buffer[40]; // typical line length, so typical iteration count is 1
std::istream::pos_type size = sizeof(buffer);
// Look for the beginning of the line that includes the given position
while (true)
{
// Move back 40 bytes from prev_pos
if (prev_pos < size)
pos = 0;
else
pos = prev_pos - size;
f.seekg(pos);
// Read 40 bytes
f.read(buffer, prev_pos - pos);
if (!f)
throw;
// Look for a newline byte, which terminates previous line
int eol_pos;
for (eol_pos = sizeof(buffer) - 1; eol_pos >= 0; --eol_pos)
if (buffer[eol_pos] == '\n')
break;
// If found newline or got to beginning of file - done looking
if (eol_pos >= 0 || pos == (std::istream::pos_type)0)
{
pos += eol_pos + 1;
break;
}
}
// Position the read pointer
f.seekg(pos);
// Read the line
std::string s;
std::getline(f, s, '\n');
return s;
}
编辑:在类似Windows的平台上,行尾由\r\n
标记,因为您必须使用二进制模式,输出字符串将包含额外字符\r
(除非那里) <文件末尾没有行尾“),你可以扔掉它。
答案 2 :(得分:0)
每个操作都有功能 fopen - 打开文件
fseek - 将文件搜索到所需的偏移量
fread - 读取你想要的字节数
fclose - 关闭文件