当 >> 时更改双引号的行为字符串流

发布于 2024-10-12 08:13:25 字数 273 浏览 6 评论 0原文

这就是我想做的:

假设我有一个字符串流。然后我 << "\"hello world\" Today";

然后当我这样做时,

sstr >> myString1 >> myString2;

我希望 myString1 有“hello world” 对于 myString2 来说,有“今天”

有没有办法(可能使用操纵器)来实现这一点?

谢谢

Here is what I'm trying to do:

say I have a stringstream. Then I << "\"hello world\" today";

then when I do

sstr >> myString1 >> myString2;

I would like myString1 to have "hello world"
and for myString2 to have "today"

Is there a way, possibly with a manipulator, to achieve this?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

赤濁 2024-10-19 08:13:25

简短回答: 没有

长回答:
没有任何操纵可以为您做到这一点。

替代答案:

您可以编写自己的类型,该类型可以与流运算符结合使用来完成此任务。

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>


class QuotedWord
{
    public:
        operator std::string const& () const { return data;}

    private:
        std::string     data;
      friend std::ostream& operator<<(std::ostream& str, QuotedWord const& value);
      {
        return str << value.data;
      }
      friend std::istream& operator>>(std::istream& str, QuotedWord& value);
      {
        char x;
        str >> x;
        if ((str) && (x == '"'))
        {
            std::string extra;
            std::getline(str, extra, '"');
            value.data = std::string("\"").append(extra).append("\"");
        }
        else
        {
            str.putback(x);
            str >> value.data;
        }
        return str;
      }
};

然后就可以正常使用了。

int main()
{
    QuotedWord  word;

    std::cin >> word;
    std::cout << word << "\n";

    // Easily convertible to string
    std::string tmp = word;
    std::cout << tmp << "\n"

    // because it converts to a string easily it can be used where string is needed.
    std::vector<std::string>   data;

    std::copy(std::istream_iterator<QuotedWord>(std::cin),
              std::istream_iterator<QuotedWord>(),

              // Notice we are using a vector of string here.
              std::back_inserter(data)
             );
}

> ./a.out
"This is" a test    // Input
"This is"           // Output
"This is"

Short Answer: No

Long Answer:
There are no manipulates that will do that for you.

Alternative Answer:

You could write your own type that could be used in conjunction with the stream operators do do this task.

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>


class QuotedWord
{
    public:
        operator std::string const& () const { return data;}

    private:
        std::string     data;
      friend std::ostream& operator<<(std::ostream& str, QuotedWord const& value);
      {
        return str << value.data;
      }
      friend std::istream& operator>>(std::istream& str, QuotedWord& value);
      {
        char x;
        str >> x;
        if ((str) && (x == '"'))
        {
            std::string extra;
            std::getline(str, extra, '"');
            value.data = std::string("\"").append(extra).append("\"");
        }
        else
        {
            str.putback(x);
            str >> value.data;
        }
        return str;
      }
};

Then it can be used normally.

int main()
{
    QuotedWord  word;

    std::cin >> word;
    std::cout << word << "\n";

    // Easily convertible to string
    std::string tmp = word;
    std::cout << tmp << "\n"

    // because it converts to a string easily it can be used where string is needed.
    std::vector<std::string>   data;

    std::copy(std::istream_iterator<QuotedWord>(std::cin),
              std::istream_iterator<QuotedWord>(),

              // Notice we are using a vector of string here.
              std::back_inserter(data)
             );
}

> ./a.out
"This is" a test    // Input
"This is"           // Output
"This is"
香草可樂 2024-10-19 08:13:25

不,

您要么需要更改流类型(从而更改解析语义),要么使用您自己的字符串类型(从而更改重载操作中的解析语义)。

相反,请考虑编写一个类似于 getline 的函数,该函数从流中解析可能引用的“单词”:

getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }

请注意,std::string 的输入已经以空格终止,因此您只需要处理向前查看引用的情况然后处理边缘情况,其中有很多:

  • 转义(引号内的引号)
    • 三种流行的样式是不允许的、反斜杠和双引号;各有优缺点
  • (可以包含 \n 吗?)
    • 这通常是一个数据错误,因此在某些情况下禁止它可能会有很大帮助
  • 如果引用的单词紧挨着另一个单词结尾会发生什么?
    • “\”你好世界\“今天”
  • 跳过前导空格?
    • 与 getline 不同,尊重流的skipws 标志是有意义的,但我可以看到在极少数情况下会出现相反的情况
    • istream 哨兵将为您处理此问题
  • 不会忘记使用流的特征和区域设置,或者使用已经做到这一点的方法!
    • 或记录您的假设

No.

You either need to change the stream type (and hence the parsing semantics) or use your own string type (and hence change the parsing semantics in your overloaded op>>).

Instead, consider writing a function, similar to getline, which parses a possibly-quoted "word" out of a stream:

getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }

Note that input into a std::string already terminates at whitespace, so you only need to handle peeking ahead for a quote and then handle edge cases, of which there are plenty:

  • escapes (quotes inside quotes)
    • the three prevalent styles are disallowed, backslash, and doubled quote; each has advantages and disadvantages
  • spanning multiple lines (can \n be included?)
    • this is often a data error, so disallowing it can be a big help in some circumstances
  • what happens if a quoted word ends next to another word?
    • "\"hello world\"today"
  • skip leading whitespace?
    • unlike getline, it makes sense to honor the stream's skipws flag, but I could see that going the other way in rare circumstances
    • the istream sentry will handle this for you
  • don't forget to use the stream's traits and locale, or use methods which already do that!
    • or document your assumptions
琉璃繁缕 2024-10-19 08:13:25

不是直接的,您需要一个“包装”类来终止您想要的地方。

struct QuotedStringReader
{
   std::string& str;
   QuotedStringReader( std::string& s ) : str( s ) {}
};

std::istream operator>>( std::istream&, const QuotedStringReader& qsr );

std::string s, s2;
stream >> QuotedStringReader( s ) << s2;

请注意,这是您流式传输到 const 的罕见情况 - 因为即使它是 const,您也可以写入内部 str,这样我就可以传入临时值。

实际上,由于您可能不知道要读什么,您可以简单地将其称为“TokenReader”,它会读取您定义为“令牌”的任何内容。

Not directly, you need a "wrapper" class that terminates where you want it to.

struct QuotedStringReader
{
   std::string& str;
   QuotedStringReader( std::string& s ) : str( s ) {}
};

std::istream operator>>( std::istream&, const QuotedStringReader& qsr );

std::string s, s2;
stream >> QuotedStringReader( s ) << s2;

Note that this is a rare occasion where you stream into a const - because you can write to the internal str even though it is const, and this way I can pass in a temporary.

Actually as you probably don't know what you are about to read you could simply call it "TokenReader" which reads whatever you define as a "token".

空城旧梦 2024-10-19 08:13:25

没有。不是那种特别的方式。您可以为字符串创建一个“强类型定义”,并设计一个新的运算符>>因为它就是这样表现的。

Nope. Not that particular way. You could create a "strong typedef" for string though and design a new operator>> for it that behaves that way.

差↓一点笑了 2024-10-19 08:13:25

在 c++14 中

#include <iostream>
#include <iomanip>
#include <sstream>

int main()
{
    std::stringstream ss;
    std::string in = "String with spaces, and embedded \"quotes\" too";
    std::string out;

    ss << std::quoted(in);
    std::cout << "read in     [" << in << "]\n"
              << "stored as   [" << ss.str() << "]\n";

    ss >> std::quoted(out);
    std::cout << "written out [" << out << "]\n";
}

输出:

read in     [String with spaces, and embedded "quotes" too]
stored as   ["String with spaces, and embedded \"quotes\" too"]
written out [String with spaces, and embedded "quotes" too]

*来源:https://en.cppreference。 com/w/cpp/io/manip/引用

In c++14

#include <iostream>
#include <iomanip>
#include <sstream>

int main()
{
    std::stringstream ss;
    std::string in = "String with spaces, and embedded \"quotes\" too";
    std::string out;

    ss << std::quoted(in);
    std::cout << "read in     [" << in << "]\n"
              << "stored as   [" << ss.str() << "]\n";

    ss >> std::quoted(out);
    std::cout << "written out [" << out << "]\n";
}

Output:

read in     [String with spaces, and embedded "quotes" too]
stored as   ["String with spaces, and embedded \"quotes\" too"]
written out [String with spaces, and embedded "quotes" too]

*Source:https://en.cppreference.com/w/cpp/io/manip/quoted

甜警司 2024-10-19 08:13:25

那是不可能的。这是因为,如果您查看 basic_istreamoperator>> 实现,它实际上是在您执行 sstr >> 时调用的。 myString1,您将在 for 循环中看到这一点:

else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta)))
   break;// whitespace, quit

意味着,一旦获得“空格”,就退出。因此,一旦获得空间,您就无法继续向 myString1 添加字符。

请注意,这是 MSVC++ 实现,但我确信您会在所有实现中找到等效的!

That is not possible. It's because if you look into the implementation of operator>> for basic_istream which is in fact called when you do sstr >> myString1, you will see this inside the for loop:

else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta)))
   break;// whitespace, quit

Means, once you get "space", Quit. So you cannot keep adding characters to your myString1 once you get space.

Note this is MSVC++ implementation, but I'm sure the equivalent you'll found in all implementation!

野の 2024-10-19 08:13:25

您可以重载输入流运算符并在其中包含解析语义。

std::istream& operator>>(std::istream& is, std::string& out)
{
    char c;
    is >> c;
    if (c == '\"')
    {
        std::getline(is, out, '\"');
        return is;
    }
    else
    {
        is.putback(c);
        return std::operator >>(is, out);
    }
}

int main()
{
    std::istringstream iss("\"hello world\" today");
    std::string test;
    while (iss >> test)
        std::cout << test << std::endl;
}

You can overload the input stream operator and include the parsing semantics there.

std::istream& operator>>(std::istream& is, std::string& out)
{
    char c;
    is >> c;
    if (c == '\"')
    {
        std::getline(is, out, '\"');
        return is;
    }
    else
    {
        is.putback(c);
        return std::operator >>(is, out);
    }
}

int main()
{
    std::istringstream iss("\"hello world\" today");
    std::string test;
    while (iss >> test)
        std::cout << test << std::endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文