C ++中的istream :: unget()不能像我想象的那样工作

时间:2013-11-18 19:56:19

标签: c++ istream

unget没有像我想象的那样工作......让我解释一下自己。我认为,unget会获取流中提取的最后一个字符,然后将其放回流中(并准备再次提取)。在内部,它正在减少流缓冲区中的指针(创建哨兵和所有东西)。

但是,当我在另一个后面使用两个unget()时,它的行为变得非常奇怪。如果写hello<bye之类的东西,我使用<作为分隔符,如果我使用getline,后来两个ungets,它会返回hello,而不是o<bye"。这是我的代码:

#include <iostream>
#define MAX_CHARS 256

using namespace std;

int main(){

    char cadena[MAX_CHARS];

    cout << "Write something: ";
    cin.getline(cadena, MAX_CHARS, '<');

    cout << endl << "Your first word delimited by < is: " << cadena << endl;

    cin.unget(); //Delimiter (removed by getline) is put back in the stream
    cin.unget(); //!?
    cin >> cadena;

    cout << "Your phrase with 2 ungets done..." << cadena;
    return 0;
}

尝试使用bye<hello,然后cadena获取bye而不是e<hello我认为每次调用时最后一个字符的unget是什么,f ***正在发生什么?

2 个答案:

答案 0 :(得分:6)

您所观察到的问题根本不足为奇。首先,请注意底层流缓冲区可能支持或不支持未输入字符。通常,支持至少一个回拨字符。这是否真实,以及是否支持更多字符完全取决于流缓冲区。

您的测试程序中发生的情况只是第二个unget()失败,流进入失败状态(即std::ios_base::failbit已设置),另一次尝试读取内容失败。失败的读取会使原始缓冲区保持不变,因为它未经过测试(应该如此),看起来好像读了两次相同的字符串。

std::cin可能只支持一个字符的基本原因是它默认与stdin同步。结果,std::cin没有做任何缓冲(导致它相当缓慢)。通过与stdin

同步,您可以获得更好的结果
std::ios_base::sync_with_stdio(false);

这将改善性能以及让更多角色成功的可能性。仍然无法保证您可以放回多个角色(甚至只有一个角色)。如果你真的需要放回字符,你应该考虑使用一个过滤流缓冲区,它支持你需要的尽可能多的字符puthback。一般来说,令牌化输入不需要任何回拨字符,这是只有平庸支持的基本原因:由于回拨支持不好,你最好使用适当的标记,这样可以减少改进回放的需要。有些循环论证。因为你总是可以创建自己的流缓冲区,但它并没有真正有害。

答案 1 :(得分:2)

此行为的实际原因与流的failbits有关,如上一个答案中所述。我可以提供一些代码,可以帮助您实现所需的结果。

For x = lbound(sat) To ubound(sat)
    If Sheet1.Cells(4, j) = Sat(x) Then
        Sheet1.Cells(i, j) = 0
        Exit For
    End If
Next