C++ 使用cin.ignore(std::numeric_limits<;std::streamsize>;::max(),';\n';)

C++ 使用cin.ignore(std::numeric_limits<;std::streamsize>;::max(),';\n';),c++,C++,所以我最近看了一个关于stringstreams的教程,其中有一个代码用于“数据验证” std::cout>value) 完成=正确; 其他的 std::cout仅当整数直接从cin读取时,才有意义以这种方式使用ignore(),但代码从cin读取字符串,然后使用istringstream解析整数,因此ignore()错误,因为它将忽略cin上的下一个输入,而不是失败的输入 不仅如此,无论输入是否成功,代码都会擦除cin缓冲区 代码应该更像这样: std::cout仅当整数直接从cin读取时,以

所以我最近看了一个关于stringstreams的教程,其中有一个代码用于“数据验证”

std::cout>value)
完成=正确;
其他的
std::cout仅当整数直接从
cin
读取时,才有意义以这种方式使用
ignore()
,但代码从
cin
读取
字符串,然后使用
istringstream
解析整数,因此
ignore()
错误,因为它将忽略cin上的下一个输入,而不是失败的输入

不仅如此,无论输入是否成功,代码都会擦除
cin
缓冲区

代码应该更像这样:

std::cout仅当整数直接从
cin
读取时,以这种方式使用
ignore()
才有意义,但代码从
cin
读取
字符串,然后使用
istringstream
解析整数,因此
ignore()
错误,因为它将忽略cin上的下一个输入,而不是失败的输入

不仅如此,无论输入是否成功,代码都会擦除
cin
缓冲区

代码应该更像这样:


std::cout
std::cin>>条目
在下一个空格字符之前都是只读的(有关更多详细信息,请参阅),因此,如果要在第一次提示时输入例如
一些东西
,则只会读取
一些
。在
some
失败并重新进入循环
std::cin>>后,条目将读入
thing
,而不管下一个输入行是什么。当运行程序时,您的控制台将如下所示(为了清晰起见,我添加了一些注释):

当提示用户时,您应该读入他们输入的所有内容,否则他们的一些输入可能会被遗漏,以后会被错误读入

忽略其余输入的一种方法是通过
std::cin.ignore(…)
。另一种方法是通过读取整行数据来获取输入。使用
std::getline
看起来像这样:

    std::cout << "\n--- Data validation ------------------------------------" << std::endl;
    
    int value{};
    std::string entry {};
    bool done = false;
    do {
        std::cout << "Please enter an integer: ";
        std::getline(std::cin, entry);
        std::istringstream validator {entry};
        if (validator >> value) 
            done = true;
        else 
            std::cout << "Sorry, that's not an integer" << std::endl;
            
         // no need to use cin.ignore
    } while (!done);
    
    std::cout << "You entered the integer: " << value << std::endl;
    
    std::cout << std::endl;

std::cout
std::cin>>条目
在下一个空格字符之前都是只读的(有关更多详细信息,请参阅),因此,如果要在第一次提示时输入例如
一些东西
,则只会读取
一些
。在
some
失败并重新进入循环
std::cin>>后,条目将读入
thing
,而不管下一个输入行是什么。当运行程序时,您的控制台将如下所示(为了清晰起见,我添加了一些注释):

当提示用户时,您应该读入他们输入的所有内容,否则他们的一些输入可能会被遗漏,以后会被错误读入

忽略其余输入的一种方法是通过
std::cin.ignore(…)
。另一种方法是通过读取整行数据来获取输入。使用
std::getline
看起来像这样:

    std::cout << "\n--- Data validation ------------------------------------" << std::endl;
    
    int value{};
    std::string entry {};
    bool done = false;
    do {
        std::cout << "Please enter an integer: ";
        std::getline(std::cin, entry);
        std::istringstream validator {entry};
        if (validator >> value) 
            done = true;
        else 
            std::cout << "Sorry, that's not an integer" << std::endl;
            
         // no need to use cin.ignore
    } while (!done);
    
    std::cout << "You entered the integer: " << value << std::endl;
    
    std::cout << std::endl;


std::cout
std::cin>>条目
仅在下一个空格字符之前读取,因此如果要输入例如
ab
,它不会在下一次提示输入内容之前忽略
b
。@IlCapitano原始代码通过后续的
ignore()忽略
b
如果
a
无法转换为
int
。我的第一个例子再现了同样的行为。第二个例子没有,但是你答案中的代码不会忽略
b
,这可能是个问题。@IlCapitano第一个例子忽略
b
,就像原始代码忽略一样,但第二个没有。如果要为第一个提示输入
asdf asdf
,为第二个提示输入
42
,即使在第二个提示之后,它也会失败,因为它不会忽略第一个提示中的第二个
asdf
std::cin>>条目只读取到下一个空格字符,因此,如果您要输入例如
ab
,它不会在下一次提示输入内容之前忽略
b
。@IlCapitano如果
a
无法转换为
int
,则原始代码会通过后续的
ignore()
忽略
b
。我的第一个例子再现了同样的行为。第二个例子没有,但是你答案中的代码不会忽略
b
,这可能是个问题。@IlCapitano第一个例子忽略
b
,就像原始代码忽略一样,但第二个没有。如果在第一个提示中输入
asdf asdf
,在第二个提示中输入
42
,即使在第二个提示之后,它也会失败,因为它没有忽略第一个提示中的第二个
asdf
。是我还是教程忘记用
std::cin.clear()清除失败时的
cin
状态位
?@Casey
cin
如果提供任何输入,都不应该失败,因为它只读取字符串。@IlCapitano。我忽略了那部分。
istringstream
也会在每次迭代中重新创建。是我还是教程忘记用
std::cin.clear()
清除失败时的
cin
状态位?@Casey
cin
如果提供任何输入,都不会失败,因为它只读取字符串。@IlCapitano。我忽略了那部分。
istringstream
也会在每次迭代中重新创建。假设我在条目中输入'12 3',当我将其传递到验证器中,验证器将其传递到'int value'中时,'3'是什么?当我用getline替换std::cin时,它要求输入两次,为什么?@Padawan'3'会被留下,下次你要求输入时,它会被读取。@Padawan,它要求输入两次,为什么?我刚试过,但我没有