[英]seekg() seeminlgy skipping characters past intended position C++
我一直在解析文件和使用 seekg() 时遇到问题。 每当在文件中达到某个字符时,我想循环直到满足条件。 循环在第一次迭代时工作正常,但是当它循环返回时,文件似乎跳过了一个字符并导致循环无法按预期运行。
具体来说,如果循环全部包含在文件的一行中,则循环可以正常工作,但当文件中的循环中至少有一个换行符时,循环会失败。
我应该提到我正在 Windows 上进行这项工作,我觉得问题出在 Windows 如何以\r\n
结束行。
在循环返回后使用seekg(-2, std::ios::cur)
可以解决开始循环条件后紧跟换行符的问题,但不适用于同一行中包含的循环。
代码的结构是让解释器 class 保存文件指针和相关变量,例如当前行和列。 这个 class 还有一个功能 map 定义如下:
// Define function type for command map
typedef void (Interpreter::*function)(void);
// Map for all the commands
std::map<char, function> command_map = {
{'+', increment_cell},
{'-', decrement_cell},
{'>', increment_ptr},
{'<', decrement_ptr},
{'.', output},
{',', input},
{'[', begin_loop},
{']', end_loop},
{' ', next_col},
{'\n', next_line}
};
它遍历每个字符,确定它是否具有以下 function 中的功能:
// Iterating through the file
void Interpreter::run() {
char current_char;
if(!this->file.eof() && this->file.good()) {
while(this->file.get(current_char)) {
// Make sure character is functional command (ie not a comment)
if(this->command_map.find(current_char) != this->command_map.end()) {
// Print the current command if in debug mode
if(this->debug_mode && current_char != ' ' && current_char != '\n') {
std::cout << this->filename << ":" << this->line << ":"
<< this->column << ": " << current_char << std::endl;
}
// Execute the command
(this->*(command_map[current_char]))();
}
// If it is not a functional command, it is a comment. The rest of the line is ignored
else{
std::string temp_line = "";
std::getline(file, temp_line);
this->line++;
this->column = 0;
}
this->temp_pos = file.tellg();
this->column++;
}
}
else {
std::cout << "Unable to find file " << this->filename << "." << std::endl;
exit(1);
}
file.close();
}
循环的开始(由 '[' 字符表示)将开始循环 position 设置为this->temp_pos
:
void Interpreter::begin_loop() {
this->loop_begin_pointer = this->temp_pos;
this->loop_begin_line = this->line;
this->loop_begin_col = this->column;
this->run();
}
当到达循环结束(由']'字符表示)时,如果不满足结束循环的条件,则将文件 cursor position 设置回循环的开头:
void Interpreter::end_loop() {
// If the cell's value is 0, we can end the loop
if(this->char_array[this->char_ptr] == 0) {
this->loop_begin_pointer = -1;
}
// Otherwise, go back to the beginning of the loop
if(this->loop_begin_pointer > -1){
this->file.seekg(this->loop_begin_pointer, std::ios::beg);
this->line = this->loop_begin_line;
this->column = this->loop_begin_col;
}
}
我能够输入调试信息,并且可以显示堆栈跟踪以进一步明确问题。
带有一行循环的堆栈跟踪( ++[->+<]
):
+ + [ - > + < ] [ - > + < ] done.
这按预期工作。
多行循环:
++[
-
>
+<]
堆栈跟踪:
+ + [ - > + < ] > + < ] <- when it looped back, it "skipped" '[' and '-' characters.
由于永远不会满足结束条件,因此永远循环(即第一个单元格的值永远不会为 0,因为它永远不会递减)。
奇怪的是,以下工作:
++[
-
>+<]
它遵循与第一个示例相同的堆栈跟踪。 这个工作和最后一个例子不工作是什么让我很难解决这个问题。
如果需要有关程序应该如何工作或其输出的更多信息,请告诉我。 抱歉,这篇文章太长了,我只想尽可能清楚。
编辑 1: class 具有文件 object 作为std::ifstream file;
. 在构造函数中,它使用this->file.open(filename)
打开,其中filename
作为参数传入。
对于文件 stream, seekg
最终是根据 C 标准库中的fseek
定义的。 C 标准有这样的说法:
7.21.9.2/4 For a text stream, either
offset
shall be zero, oroffset
shall be a value returned by an earlier successful call to theftell
function on a stream associated with the same file andwhence
shall beSEEK_SET
.
因此,对于以文本模式打开的文件,您无法对偏移量进行任何算术运算。 您可以倒回到开头,最后是 position,或者返回到您之前所在的 position 并使用tellg
(最终调用ftell
)捕获。 其他任何事情都会表现出未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.