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

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

我正在尝试实现一个简单的格式功能,根据给定的格式字符填充相应的内容。
我用std::stringstream把给定的格式串转成流,然后把字符一个个取出来。然后根据单个字符,将相关内容填入输出流中。 格式字符串以 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 == '[=12=]') 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;
}

正如预期的那样,程序应该输出如下内容:

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

但是在预期输出的末尾,有一个奇怪的字符:

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

查了半天,找不到可信的解释和具体的解决办法,很苦恼

这是编码问题吗?

我该如何解决这个问题?

假设刚刚处理了流中的最后一个字符。流中没有任何内容。

while (s_fmt.good()) {

这很好。毕竟,为什么不呢?到目前为止,一切都运行良好。整个字符串已被读取。一切依旧good()while 循环继续到 运行:

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

很遗憾,已到达字符串末尾。这失败了,when the end of the stream has been reached get() returns

EOF and sets failbit and eofbit.

显示的代码不检查,并盲目地将 returned EOF 值转换为 char。这就是你的“奇怪性格”。在 while 循环的下一次迭代中,它会发现事情不再是 good()(之前的 get() 失败),然后退出。太晚了。

要解决此问题,有必要从逻辑上重新安排事件的顺序。首先你 get() 下一个字符,然后你才能检查流是否为 good(),否则退出。或者,或者,检查一个明确的 EOF return 值,您的偏好。