流::seekoff 是否更新了输入序列
Does stream::seekoff update the input sequence?
In [filebuf.virtuals]:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
效果:让
width
表示a_codecvt.encoding()
。如果is_open() == false
或off != 0 && width <= 0
,则定位操作失败。否则,如果way != basic_ios::cur
或off != 0
,并且如果输出了最后一个操作,则更新输出序列并写入任何取消移位序列。接下来,寻找新的位置:如果width > 0
,则呼叫fseek(file, width * off, whence)
,否则呼叫fseek(file, 0, whence)
。
它没有提到此函数更新输入序列。相比之下,seekpos
确实更新了输入序列:
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
如果可能,更改文件位置以对应于存储在
sp
中的位置(如下所述)。更改文件位置执行如下:
如果
(om & ios_base::out) != 0
,则更新输出序列并写入任何未移位序列;将文件位置设置为
sp
,就像通过调用fsetpos
一样;如果
(om & ios_base::in) != 0
,则更新输入序列;
那么seekoff
能保证更新输入序列吗?
对于一个具体示例,请考虑:
#include <fstream>
#include <iostream>
int main()
{
std::fstream f("test.txt"); // test.txt contains "test"
char ch;
f >> ch;
f.rdbuf()->pubseekoff(0, std::ios_base::beg);
f >> ch;
std::cout << ch;
}
程序是否保证输出t
?
我可以看到你的观点朋友,事实上,这可能不仅仅是你自己一些困惑的根源。
简短的回答:
是的,seekoff
会像seekpos
一样更新输入序列。seekoff
和seekpos
在调用、输入或输出(或两者)更新哪个序列方面行为相同。
详细解释:
不是仅仅通过惯例,而是根据标准本身,seekoff
和seekpos
的行为都被定义为依赖于ios_base::openmode which
论点。在另一个类模板中可以看出,stringbuf
,派生自与filebuf
相同的父级,seekoff
的覆盖明确声明,对于(which & ios_base::in) == ios_base::in
调用将定位输入序列;对于(which & ios_base::out) == ios_base::out
调用将定位输出序列;对于(which & (ios_base::in | ios_base::out)) == (ios_base::in | ios_base::out)
和way ==
ios_base::beg
或ios_base::end
调用将同时定位输入和输出序列。
但是,当直接在标准面前工作时,人们不必期望事物只是呈现自己。请参阅父类streambuf
下的此处:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
效果:以为派生自
basic_streambuf
的每个类单独定义的方式更改一个或多个受控序列中的流位置...
因此,通过更仔细地查看您自己提供的有关filebuf
seekpos
报价的标准:
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
如果可能,更改文件位置以对应于存储在
sp
中的位置(如下所述)。更改文件位置执行如下:
如果
(om & ios_base::out) != 0
,则更新输出序列并写入任何未移位序列;将文件位置设置为
sp
,就像调用fsetpos
一样;如果
(om & ios_base::in) != 0
,则更新输入序列;
以下行说:
其中
om
是传递给最后一次调用 open() 的开放模式。
因此,这意味着您无法在调用本身中指定要更新的序列。例如,这里的标准说实现应该明显忽略(!)om
参数。
我们不必错过的另一点是您提供的关于seekoff
的报价中,其中说:
接下来,寻找新的位置:如果
width > 0
,则呼叫fseek(file, width * off, whence)
,否则呼叫fseek(file, 0, whence)
。
所以在背后,它只是一个对fseek
的呼吁。但是在哪个特定的文件对象上?输入和输出是否有单独的?我相信我们正在寻找的答案出现在 filebif 下的规范中:
§ 27.9.1.1
- 类basic_filebuf将输入序列和 带有文件的输出序列。
- 读取和写入由类对象控制的序列的限制 basic_filebuf与使用标准 C 库进行读写相同 文件。
- 特别:
- 如果文件未打开以供读取,则无法读取输入序列。
- 如果文件未打开以进行写入,则无法写入输出序列。
- 输入序列和输出序列都保持联合文件位置。
例如,seekoff
和seekpos
的行为对于调用、输入或输出(或两者)正在更新的序列相同,并且仅由传递给open()
的内容确定。
另外,大约 5 年前刚刚遇到这个问题,我看到:fstream seekg()、seekp() 和 write()
编辑,以进一步澄清:
请注意seekoff
的规范说:
如果输出了最后一个操作,则更新输出序列和写入任何未移位序列。
seekpos
还说:
更新输出序列并写入任何未移位序列;
seekoff
的备注部分定义了"编写任何未移位序列"的含义。因此,对于这两种方法,它应该是等效的。但随后两者都进一步说明:seekoff
说它叫fseek
,seekpos
说它叫fsetpos
(在这方面与fseek
相同)。
当考虑到上述§ 27.9.1.1节中的第2点在C11标准ISO/IEC 9899:2011中进行了解释时,可以找到其原因,甚至提到最后一个操作是输出位:
§7.21.5.3
fopen
函数¶7 当文件以更新模式打开时("+"作为 上面的模式参数值列表),输入和输出都可以在 关联的流。但是,输出后不应直接跟着没有 对
fflush
函数或文件定位函数(fseek
的干预调用,fsetpos
或rewind
),并且输入后不应直接跟着输出,而没有 对文件定位函数的干预调用,除非输入操作遇到文件末尾。
因此,要回答您在下面的评论,seekoff
是否会更新输入序列与是否输入最后一个操作无关。如果最后一个操作不是输入的,那么上面讨论的取消移位序列存在技术性。但是整个stream
类的部分想法是以一种不会打扰您进行此类维护工作的方式封装 i/o。
- 从C++本机插件更新Vector3数组
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 2D数组来自文本输入,中间有空格
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 检查输入是否不是整数或数字
- 正在尝试了解输入验证循环
- QGraphicsPolygonItem在拖动时未更新QPolygonF坐标
- 读取文件并输入到矢量中
- C++如何通过用户输入删除列表元素
- 流::seekoff 是否更新了输入序列
- 更新成员集合使用STL给定输入收集
- 我将如何连续更新变量,并同时等待输入
- 与更新的输入文件同步程序
- 如何检查输入文件是否已更新
- 如何更新最近在 std::vector<pair<int, int>> 中输入的元素?
- 使用boost:asio和select?阻止TCP输入或文件更新
- 逗号运算符无法更新基类构造的输入参数
- 更新输入的每个字符的标签
- CDialog更新输入框值
- 读取CAN输入时更新GUI元素的效率/速度