【问题标题】:How to determine how many characters `std::getline()` extracted?如何确定提取了多少个字符`std::getline()`?
【发布时间】:2018-12-08 17:58:13
【问题描述】:

假设我通过使用std::getline() 重载从std::istream 读取std::string。如何确定从流中提取了多少个字符? std::istream::gcount() 不能像这里讨论的那样工作:ifstream gcount returns 0 on getline string overload

#include <iostream>
#include <sstream>
#include <string>

int main()
{
    std::istringstream s( "hello world\n" );
    std::string str;
    std::getline( s, str );
    std::cout << "extracted " << s.gcount() << " characters" << std::endl;
}

Live example

注意,对于downvoters - 字符串的长度不是答案,因为std::getline() 可能会或可能不会从流中提取其他字符。

【问题讨论】:

  • 关于std::string::size的帽子?
  • @Galik 分隔符呢?
  • 如果std::getline 确实吞下了一个换行符,或者点击了EOF,则需要同时使用size()eof() 进行逆向工程,以获得准确的字符数。
  • @Slava 是的,我只是在想那个......
  • 有些人在否决问题之前需要了解更多C++,因为他们不理解这些问题。

标签: c++ iostream


【解决方案1】:

执行此操作的方法似乎并不完全简单,因为std::getline 可能(或可能不会)读取终止分隔符,并且在任何一种情况下它都不会将其放入字符串中。所以字符串的长度不足以告诉你到底读取了多少个字符。

你可以测试eof()看分隔符是否被读取:

std::getline(is, line);

auto n = line.size() + !is.eof();

将它包装在一个函数中会很好,但是如何传回额外的信息?

我认为的一种方法是如果已读取分隔符,则将其添加回来并让调用者处理它:

std::istream& getline(std::istream& is, std::string& line, char delim = '\n')
{
    if(std::getline(is, line, delim) && !is.eof())
        line.push_back(delim); // add the delimiter if it was in the stream

    return is;
}

但我不确定我会一直想要那个。

【讨论】:

  • 在使用 CRLF 作为行尾的平台上可能存在一个问题。
  • @Eljay 我正在尝试查找准确的信息,但据我所知,流子系统应该在所有平台上将多字节 EOL 序列无缝转换为 \n。这意味着即使gcount() 也不应该能够“看到”EOL 序列中的伴随字节,除非该文件专门以 binary 模式打开。但我不完全确定这一切是如何工作的,因为我不使用Windows,所以我正在尝试查找更多信息。
  • 从 AppleDOS 到 OS 9 的 Apple 计算机使用 CR 作为 EOL。 CP/M 计算机将 CRLF 用于 EOL,以及该沿袭的平台(DOS、Windows、OS/2)。 Unix 机器和其他机器(例如 AmigaOS)使用 LF 表示 EOL。我还看到一个使用 C1 控制代码集中的 NEL (\x85) 的。 IBM 3390 大型机文件通常是基于固定行大小的记录(文件条目中的元数据),并且没有行终止字符。
  • @Eljay 是的,但标准流库有责任将幕后的那些行尾序列转换为所有系统上的简单'\n'。所以C++程序员在写程序的时候只需要关心\n就行了。
  • @Eljay 我知道,我只是不确定原始计数是否可用于 any 流函数,包括 gcount(),除非文件以 binary 格式打开 模式。在这种情况下,您可以按预期在任何地方获得原始计数。所以我认为这个函数的行为与标准库函数完全一致。
猜你喜欢
  • 1970-01-01
  • 2020-03-22
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-08
  • 1970-01-01
  • 2021-04-22
相关资源
最近更新 更多