stream :: seekoff会更新输入序列吗?

问题描述 投票:10回答:1

[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() == falseoff != 0 && width <= 0,则定位操作失败。否则,如果way != basic_­ios​::​curoff != 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中的位置(如下所述)。更改文件位置执行如下:

  1. 如果(om & ios_­base​::​out) != 0,则更新输出序列并写入任何非移位序列;
  2. 将文件位置设置为sp,就好像通过调用fsetpos一样;
  3. 如果(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

c++ stream buffer language-lawyer
1个回答
2
投票

我可以看到你的观点朋友,事实上,这可能是一些不仅为自己造成困惑的根源。

简短回答:

是的,seekoff将像seekpos一样更新输入序列。 seekoffseekpos在调用,输入或输出(或两者)更新哪个序列方面表现相同。

很长的解释:

不仅仅是通过惯例,而是根据标准本身,seekoffseekpos的行为被定义为依赖于ios_base::openmode which论证。从另一个类模板中可以看出,stringbuf来源于与filebuf相同的父类,the override for 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​::​begios_­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派生的每个类别单独定义的方式改变一个或多个受控序列中的流位置...

所以,通过更仔细地查看the quote you have provided yourself regarding seekpos of filebuf的标准:

pos_type seekpos(pos_type sp,
                 ios_base::openmode which
                   = ios_base::in | ios_base::out) override;

如果可能,更改文件位置以对应存储在sp中的位置(如下所述)。更改文件位置执行如下:

  1. 如果(om & ios_­base​::​out) != 0,则更新输出序列并写入任何非移位序列;
  2. 将文件位置设置为sp,就好像通过调用fsetpos一样;
  3. 如果(om & ios_­base​::​in) != 0,则更新输入序列;

以下行说:

其中om是传递给最后一次调用open()的开放模式。 ...

因此,这意味着您无法在调用中指定要更新的序列。同样,这里的标准说实现应该明显地忽略(!)om论证。

我们不必错过的另一点是你提供的有关seekoff的报价,其中说:

接下来,寻找新的位置:如果width > 0,请致电fseek(file, width * off, whence),否则请致电fseek(file, 0, whence)

所以它只是对fseek的调用。但是在哪个特定的FILE对象上呢?是否有单独的输入和输出?我相信我们正在寻找的答案出现在filebuf的规范中:

§ 27.9.1.1

  1. basic_filebuf类将输入序列和输出序列与文件相关联。
  2. 读取和编写由basic_filebuf类对象控制的序列的限制与使用Standard C库FILE读取和写入的限制相同。
  3. 特别是: 如果文件未打开,则无法读取输入序列。 如果文件未打开以进行写入,则无法写入输出序列。 为输入序列和输出序列保持联合文件位置。

同样,seekoffseekpos在调用,输入或输出(或两者)更新哪个序列方面表现相同,并且仅由传递给open()的内容确定。

另外,从大约5年前刚刚遇到这个我看到:fstream seekg(), seekp(), and write()

编辑,以进一步说明:

请注意seekoff的规格说:

如果输出了最后一个操作,则更新输出序列并写入任何非移位序列。

seekpos还说:

更新输出序列并写入任何非移位序列;

the remarks section for seekoff定义了“写任何非移位序列”的含义。因此,两种方法都应该是等价的。但随后两者都进一步说明:seekoff称它称为fseekseekpos称它称为fsetpos(在这方面与fseek相同)。

当考虑到上面提到的第27.9.1.1节中的第2点在C11标准,ISO / IEC 9899:2011中解释时,找到了这个原因,甚至提到最后一个操作是输出位。

§7.21.5.3 The fopen function

¶7使用更新模式打开文件时('+'作为上述模式参数值列表中的第二个或第三个字符),可以在关联的流上执行输入和输出。但是,如果没有对fflush函数或文件定位函数(fseekfsetposrewind)的干预调用,输出不应直接跟随输入,并且输入不应直接跟随输出而不干预文件定位函数,除非输入操作遇到文件结尾。

因此,要回答下面的评论,seekoff是否会更新输入序列,无论最后一次操作是否输入。如果没有输入最后一个操作,则具有上面讨论的非移位序列的技术性。但是整个stream类的部分想法是以一种不会因为这样的维护工作而烦扰你的方式封装i / o。

© www.soinside.com 2019 - 2024. All rights reserved.