简体   繁体   English

[C++]为什么使用 std::stringstream 迭代 std::string 会给出异常字符?

[英][C++]Why Iterating over a std::string using std::stringstream gives an exception character?

I'm trying to implement a simple format function that fills in the corresponding content based on the given format character.我正在尝试实现一个简单的格式函数,该函数根据给定的格式字符填充相应的内容。
I use std::stringstream to convert the given format string into a stream, and then take out the characters one by one.我使用std::stringstream将给定的格式字符串转换为流,然后将字符一一取出。 Then, based on the individual characters, fill in the relevant content into the output stream.然后,根据单个字符,将相关内容填入输出流中。 The format string is given in std::string type.格式字符串以std::string类型给出。

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

int main() {
    std::string fmt = "[%t]%Y-%M-%D<%H:%m:%s>:%c";
    std::stringstream s_res;
    std::stringstream s_fmt(fmt);
    while (s_fmt.good()) {
        char c = (char) s_fmt.get();
        if (c == '\0') break; // I'm not sure this stagement is necessary.
        if (c == '%') {
            switch (s_fmt.peek()) {
                case 't':
                    s_res << "Type";
                    break;
                case 'Y':
                    s_res << "Year";
                    break;
                case 'M':
                    s_res << "Month";
                    break;
                case 'D':
                    s_res << "Day";
                    break;
                case 'H':
                    s_res << "Hour";
                    break;
                case 'm':
                    s_res << "min";
                    break;
                case 's':
                    s_res << "sec";
                    break;
                case 'c':
                    s_res << "content";
                    break;
            }
            s_fmt.get();
            continue;
        }
        s_res << c;
    }
    std::cout << s_res.str();
    return 0;
}

As expected, the program should output something like this:正如预期的那样,程序应该输出如下内容:

Expected output: [Type]Year-Month-Day<Hour:min:sec>:content

But at the end of the expected output, there is a strange character:但是在预期输出的末尾,出现了一个奇怪的字符:

Actual Output:[Type]Year-Month-Day<Hour:min:sec>:content
========================================================^

I checked for a long time and was very troubled to find no credible explanation or concrete solution.查了半天,很苦恼,没有找到可信的解释,也没有具体的解决办法。

Is this a problem caused by encoding?这是编码引起的问题吗?

How can I solve this issue?我该如何解决这个问题?

Let's say that the last character in the stream has just been processed.假设流中的最后一个字符刚刚被处理。 There's nothing left in the stream.流中什么都没有了。

while (s_fmt.good()) {

This is perfectly fine.这完全没问题。 After all, why wouldn't it be?毕竟,为什么不呢? Everything worked swimmingly well, up until now.到目前为止,一切都运行良好。 The entire string has been read.已读取整个字符串。 Everything is still good() .一切都good() The while loop continues to run: while循环继续运行:

   char c = (char) s_fmt.get();

Unfortunately, the end of the string has already been reached.不幸的是,已经到达字符串的末尾。 This fails, and when the end of the stream has been reached get() returns这失败了,当到达流的末尾时get()返回

EOF and sets failbit and eofbit. EOF并设置 failbit 和 eofbit。

The shown code does not check that, and blindly converts the returned EOF value to a char .显示的代码不会检查,并盲目地将返回的EOF值转换为char That's your "strange character".那是你的“奇怪的性格”。 And on the next iteration of the while loop, it will discover that things aren't good() any more (the previous get() failed), and bail out.while循环的下一次迭代中,它会发现事情不再good() (之前的get()失败),并退出。 Too late.为时已晚。

To fix this it will be necessary to logically rearrange the sequence of events.为了解决这个问题,有必要在逻辑上重新安排事件的顺序。 First you get() the next character, and only then you can check if the stream is good() , and bail out otherwise.首先你get()下一个字符,只有这样你才能检查流是否是good() ,否则就退出。 Or, alternatively, check for an explicit EOF return value, your preference.或者,也可以根据您的偏好检查明确的EOF返回值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM