c++ - 如何从 C++ 中的 istream 中干净地提取字符串分隔字符串

标签 c++ string delimiter istream

我正在尝试从一个带有字符串作为分隔符的istream中提取一个字符串,但我还没有发现任何行为接近于的字符串操作istreams 中的 find()substr()

这是一个 istream 内容示例: delim_oneFUUBARdelim_two 我的目标是使用尽可能少的解决方法将 FUUBAR 变成一个字符串。

我目前的解决方案是使用 this 将所有 istream 内容复制到一个字符串中它的解决方案,然后使用字符串操作提取。有没有一种方法可以避免这种不必要的复制,并且只根据需要从 istream 中读取尽可能多的内容,以保留分隔字符串之后的所有内容,以防以类似的方式找到更多内容?

最佳答案

您可以轻松地创建一个将使用预期的分隔符或定界符的类型:

struct Text
{
    std::string t_;
};

std::istream& operator>>(std::istream& is, Text& t)
{
    is >> std::skipws;
    for (char c: t.t_)
    {
        if (is.peek() != c)
        {
            is.setstate(std::ios::failbit);
            break;
        }
        is.get(); // throw away known-matching char
    }
    return is;
}

ideone 上查看实际效果

当先前的流提取自然停止而不消耗定界符时(例如 int 提取后跟一个不以数字开头的定界符),这通常是这种情况,除非先前的提取是一个std::string .单字符定界符可以指定给getline,但是假设你的定界符是"</block>"并且流包含 "<black>metalic</black></block>42" - 你想要提取一些东西 "<black>metallic</black> "变成 string ,扔掉 "</block>" 定界符,留下 "42 "在流中:

struct Until_Delim {
    Until_Delim(std::string& s, std::string delim) : s_(s), delim_(delim) { }
    std::string& s_;
    std::string delim_;
};

std::istream& operator>>(std::istream& is, const Until_Delim& ud)
{
    std::istream::sentry sentry(is);
    size_t in_delim = 0;
    for (char c = is.get(); is; c = is.get())
    {
        if (c == ud.delim_[in_delim])
        {
            if (++in_delim == ud.delim_.size())
                break;
            continue;
        }
        if (in_delim) // was part-way into delimiter match...
        {
            ud.s_.append(ud.delim_, 0, in_delim);
            in_delim = 0;
        }
        ud.s_ += c;
    }
    // may need to trim trailing whitespace...
    if (is.flags() & std::ios_base::skipws)
        while (!ud.s_.empty() && std::isspace(ud.s_.back()))
            ud.s_.pop_back();
    return is;
}

这可以用作:

string a_string;
if (some_stream >> Until_Delim(a_string, "</block>") >> whatevers_after)
    ...

这个表示法可能看起来有点老套,但在标准库的 std::quoted() 中有先例。 .

可以看到代码运行here .

关于c++ - 如何从 C++ 中的 istream 中干净地提取字符串分隔字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22692336/

相关文章:

c++ - 共享库 (libNNN.so) 是否/应该共享常量数据?

c - (C 编程) 如何将字符串插入字符数组,然后打印出该数组的所有元素?

javascript拆分正则表达式

c++ - C 从竖线字符分隔的文件中读入

c++ - 转换运算符和构造函数的歧义

C++ FIR 噪声滤波器

c++ - 字符串类 C++

c++ - 在 C++ 中使用它在内存中的起始地址编辑字符串

sed - 如何删除第一次出现 ";"到第一个空格/制表符之间的所有内容?

java - 分割字符串不带分隔符