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;
}
Run Code Online (Sandbox Code Playgroud)
尝试bye<hello,然后cadena得到bye而不是e<hello我认为unget与每次调用时最后一个字符一起工作,f***正在发生什么?
你观察到的问题根本不足为奇.首先,请注意底层流缓冲区可能支持或不支持ungetting字符.通常,支持至少一个回拨字符.这是否真实,以及是否支持更多字符完全取决于流缓冲区.
在您的测试程序中发生的事情只是第二次unget()失败,流进入失败状态(即std::ios_base::failbit设置),另一次尝试读取内容失败.失败的读取保持原始缓冲区不变,因为它没有经过测试(应该如此),看起来好像读了两次相同的字符串.
根本原因std::cin可能只支持一个字符,即stdin默认情况下它与之同步.结果,std::cin不做任何缓冲(导致它相当缓慢).通过不与stdin以下步骤同步,您可以获得更好的结果:
std::ios_base::sync_with_stdio(false);
Run Code Online (Sandbox Code Playgroud)
这将改善性能和更多角色成功的可能性.仍然无法保证您可以放回多个角色(甚至只有一个角色).如果你真的需要放回字符,你应该考虑使用一个过滤流缓冲区,它支持你需要的尽可能多的字符puthback.一般来说,令牌化输入不需要任何回拨字符,这是只有平庸支持的基本原因:由于回拨支持不好,你最好使用适当的标记,这样可以减少改进回放的需要.有些循环论证.但是,由于您始终可以创建自己的流缓冲区,因此它并不是真正有害的.