xsk*_*xzr 10 c++ buffer stream language-lawyer
Run Code Online (Sandbox Code Playgroud)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确实更新输入序列:
Run Code Online (Sandbox Code Playgroud)pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;如果可能,改变文件位置以对应存储的位置
sp(如下所述).更改文件位置执行如下:
if
(om & ios_base?::?out) != 0,然后更新输出序列并写入任何非移位序列;将文件位置设置
sp为就像通过调用一样fsetpos;if
(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;
}
Run Code Online (Sandbox Code Playgroud)
程序是否保证输出t?
我可以看到你的重点朋友,事实上,这可能不仅对你自己来说可能是一些困惑的根源。
\n\n简短回答:
\n\n是的,seekoff将按照意愿更新输入序列seekpos。对于调用、输入或输出(或两者)更新哪个序列,两者的seekoff行为相同。seekpos
长解释:
\n\n不仅仅是按照惯例,而是根据标准本身,两者的行为seekoff都seekpos被定义为依赖于ios_base::openmode which参数。正如在另一个类模板 中所看到的,stringbuf派生自与 相同的父级filebuf,的覆盖seekoff显式声明该(which & ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bin) == ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bin 调用将定位输入序列;对于(which & ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bout) == ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bout 调用将定位输出序列;对于(which & (ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bin | ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bout)) == (ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bin | ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bout)和way ==或ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bbeg或ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bend 调用将定位输入和输出序列
但是,当直接在标准面前工作时,人们不必期望事情会自然而然地呈现出来。请参阅父类下的此处streambuf:
\n\n\nRun Code Online (Sandbox Code Playgroud)\n\npos_type seekoff(off_type off, ios_base::seekdir way,\n ios_base::openmode which\n = ios_base::in | ios_base::out) override;\n效果:以一种为派生自...的每个类单独定义的方式改变一个或多个受控序列中的流位置。
\nbasic_\xc2\xadstreambuf
因此,通过更仔细地查看您自己提供的报价seekpos标准filebuf:
\n\n\nRun Code Online (Sandbox Code Playgroud)\n\npos_type seekpos(pos_type sp,\n ios_base::openmode which\n = ios_base::in | ios_base::out) override;\n如果可能,更改文件位置以对应于存储的位置
\n\nsp(如下所述)。更改文件位置的执行方式如下:\n
\n- \n
如果
(om & ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bout) != 0,则更新输出序列并写入任何未移位序列;- \n
将文件位置设置为
sp好像通过调用fsetpos;- \n
如果
(om & ios_\xc2\xadbase\xe2\x80\x8b::\xe2\x80\x8bin) != 0,则更新输入序列;
下面一行说:
\n\n\n\n\n其中
\nom是传递给最后一次调用 open() 的打开模式。...
因此,这意味着您无法在调用本身中指定要更新哪个序列。正如这里的标准所说,实现应该简单地忽略(!)om。
我们不能错过的另一点是您提供的有关seekoff,其中写道:
\n\n\n接下来,寻找新位置: if
\nwidth > 0,callfseek(file, width * off, whence),否则 callfseek(file, 0, whence)。
所以底层只是对fseek. 但是在哪个特定的 FILE 对象上呢?输入和输出有单独的吗?我相信我们正在寻找的答案出现在filebuf下的规范中下的规范中:
\n\n\n\xc2\xa7 27.9.1.1
\n\n\n
\n- basic_filebuf 类将输入序列和输出序列与文件相关联。
\n- 读取和写入由类 basic_filebuf 的对象控制的序列的限制与使用标准 C 库文件读取和写入的限制相同。
\n- 特别是:\n\n
\n\n
- 如果文件未打开以进行读取,则无法读取输入序列。
\n- 如果文件未打开用于写入,则无法写入输出序列。
\n- 为输入序列和输出序列维护联合文件位置。
\n
如图所示,对于调用、输入或输出(或两者)更新哪个序列, 和 的行为是相同的,并且它仅由传递给 的内容seekoff决定。seekposopen()
另外,大约 5 年前就遇到过这个问题,我看到:fstreameekg()、seekp() 和 write()
\n\n编辑,以进一步澄清:
\n\n请注意规范seekoff说:
\n\n\n如果输出了最后一个操作,则更新输出序列并 写入任何未移位序列。
\n
seekpos还说:
\n\n\n更新输出序列并写入任何未移位序列;
\n
注释部分seekoff定义了 \xe2\x80\x9cWrite any unshift sequence\xe2\x80\x9d 的含义。因此,这两种方法应该是等效的。但随后两者都进一步指定:seekoff说它调用fseek并seekpos说它调用(在这方面fsetpos相同)。fseek
这样做的原因,甚至提到最后一个操作是输出位,是在考虑上面提到的 \xc2\xa7 27.9.1.1 节中的第 2 点时发现的,在 C11 标准 ISO/IEC 9899:2011 中对此进行了解释:
\n\n\n\n\n\xc2\xa77.21.5.3
\n\nfopen函数\xc2\xb67 当使用更新模式打开文件时(\'+\' 作为上面模式参数值列表中的第二个或第三个字符),输入和输出都可以在关联的流上执行。但是,如果没有对函数
\nfflush或文件定位函数(fseek、\nfsetpos或rewind)的中间调用,输出后面不得直接跟有输入,并且在没有对函数或文件定位函数( 、\n 或 )进行中间调用的情况下,输入后面不得直接跟有输出。文件定位功能,除非输入操作遇到文件结尾。
所以回答你下面的评论,是否seekoff会更新输入序列是不管最后一个操作是否输入的。如果没有输入最后一个操作,则存在上面讨论的未移位序列的技术细节。但整个类的部分想法stream是以一种不会让您因此类维护工作而困扰的方式封装 I/O。