C++ C++;不';我不能像我想的那样工作
unget的工作方式和我想象的不一样。。。让我解释一下。正如我所想,unget获取流中提取的最后一个字符,并将其放回流中(并准备再次提取)。在内部,它减少了流缓冲区中的指针(创建哨兵和其他东西)C++ C++;不';我不能像我想的那样工作,c++,istream,C++,Istream,unget的工作方式和我想象的不一样。。。让我解释一下。正如我所想,unget获取流中提取的最后一个字符,并将其放回流中(并准备再次提取)。在内部,它减少了流缓冲区中的指针(创建哨兵和其他东西) 但是,当我一个接一个地使用两个unget()时,它的行为会变得非常奇怪。如果你写一些类似于hello的东西,你观察到的问题一点也不奇怪。首先,请注意,底层流缓冲区可能支持取消设置字符,也可能不支持取消设置字符。通常,至少支持一个字符的回拨。这是否真实以及是否支持更多字符完全取决于流缓冲区 测试程序中发生
但是,当我一个接一个地使用两个unget()时,它的行为会变得非常奇怪。如果你写一些类似于
hello的东西,你观察到的问题一点也不奇怪。首先,请注意,底层流缓冲区可能支持取消设置字符,也可能不支持取消设置字符。通常,至少支持一个字符的回拨。这是否真实以及是否支持更多字符完全取决于流缓冲区
测试程序中发生的情况很简单,第二次unget()
失败,流进入失败状态(即设置了std::ios\u base::failbit
),另一次读取某个内容的尝试失败。失败的读取使原始缓冲区保持不变,并且由于未对其进行测试(它应该进行测试),因此看起来好像相同的字符串被读取了两次
std::cin
可能只支持一个要放回的字符的根本原因是默认情况下它与stdin
同步。因此,std::cin
不做任何缓冲(这导致它也相当慢)。如果不与stdin进行同步,您很有可能获得更好的结果:
std::ios_base::sync_with_stdio(false);
这将提高性能,并使更多角色获得成功的可能性。仍然无法保证您可以将多个字符(甚至仅一个字符)放回原处。如果你真的需要回放字符,你应该考虑使用一个过滤流缓冲器,它支持你需要的尽可能多的字符回退。一般来说,标记化输入不需要任何字符的回拨,这是只有一般支持的基本原因:因为回拨支持不好,所以最好使用适当的标记化,以减少改进回拨的需要。有点像循环论证。由于您可以创建自己的流缓冲区,因此它实际上并不有害。您观察到的问题一点也不奇怪。首先,请注意,底层流缓冲区可能支持取消设置字符,也可能不支持取消设置字符。通常,至少支持一个字符的回拨。这是否真实以及是否支持更多字符完全取决于流缓冲区
测试程序中发生的情况很简单,第二次unget()
失败,流进入失败状态(即设置了std::ios\u base::failbit
),另一次读取某个内容的尝试失败。失败的读取使原始缓冲区保持不变,并且由于未对其进行测试(它应该进行测试),因此看起来好像相同的字符串被读取了两次
std::cin
可能只支持一个要放回的字符的根本原因是默认情况下它与stdin
同步。因此,std::cin
不做任何缓冲(这导致它也相当慢)。如果不与stdin进行同步,您很有可能获得更好的结果:
std::ios_base::sync_with_stdio(false);
这将提高性能,并使更多角色获得成功的可能性。仍然无法保证您可以将多个字符(甚至仅一个字符)放回原处。如果你真的需要回放字符,你应该考虑使用一个过滤流缓冲器,它支持你需要的尽可能多的字符回退。一般来说,标记化输入不需要任何字符的回拨,这是只有一般支持的基本原因:因为回拨支持不好,所以最好使用适当的标记化,以减少改进回拨的需要。有点像循环论证。由于您总是可以创建自己的流缓冲区,因此它实际上并不有害。这种行为的实际原因与前面的答案中解释的流的故障位有关。我可以提供一个变通代码,帮助您实现所需的结果
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
// compile using g++ -std=c++11 -lboost_iostreams
#define MAX_CHARS 256
using namespace std;
int main(){
boost::iostreams::filtering_istream cinn(std::cin,0,1);
char cadena[MAX_CHARS];
cout << "Write something: ";
cinn.getline(cadena, MAX_CHARS, '<');
cout << endl << "Your first word delimited by < is: " << cadena << endl;
cinn.unget(); //Delimiter (removed by getline) is put back in the stream
cinn.unget(); //!?
cinn >> cadena;
cout << "Your phrase with 2 ungets done..." << cadena;
return 0;
}
#包括
#包括
//使用g++-std=c++11-lboost\u iostreams编译
#定义最大字符数256
使用名称空间std;
int main(){
boost::iostreams::filtering_istream cinn(std::cin,0,1);
char cadena[MAX_CHARS];
cout此行为的实际原因与前面的答案中解释的流的故障位有关。我可以提供一个变通代码,帮助您实现所需的结果
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
// compile using g++ -std=c++11 -lboost_iostreams
#define MAX_CHARS 256
using namespace std;
int main(){
boost::iostreams::filtering_istream cinn(std::cin,0,1);
char cadena[MAX_CHARS];
cout << "Write something: ";
cinn.getline(cadena, MAX_CHARS, '<');
cout << endl << "Your first word delimited by < is: " << cadena << endl;
cinn.unget(); //Delimiter (removed by getline) is put back in the stream
cinn.unget(); //!?
cinn >> cadena;
cout << "Your phrase with 2 ungets done..." << cadena;
return 0;
}
#包括
#包括
//使用g++-std=c++11-lboost\u iostreams编译
#定义最大字符数256
使用名称空间std;
int main(){
boost::iostreams::filtering_istream cinn(std::cin,0,1);
char cadena[MAX_CHARS];
难道“我以为unget每次被调用时都与最后一个字符一起工作”-不,只有一次。那么它是如何工作的?(感谢黑暗猎鹰在我的帖子中正确地放置了<)@n、 m:流缓冲区接口中没有任何东西可以阻止尽可能多的放回字符…也没有任何东西可以保证你甚至可以放回一个字符!这完全取决于流缓冲区。“我认为unget每次调用时都会与最后一个字符一起工作”-不,只有一次。那么它是如何工作的?(感谢黑暗猎鹰在我的帖子中正确地添加了<)@ N.M.:流缓冲区中的任何东西都不阻止你想要的多个回放字符…而且没有任何东西保证你甚至能返回一个字符,完全取决于流缓冲器。所以它完全依赖于我正在使用的CIN实现?难道没有为C++中的流解开ANSI函数吗?我感到困惑。什么是stdin?为什么它与cin同步?谢谢你的回答。@Carrascado:std::istre