【问题标题】:How to control Input in C++如何在 C++ 中控制输入
【发布时间】:2021-06-21 14:24:20
【问题描述】:

我正在编写一个程序,我在其中进行这样的检查:

int small;
cout<<"Small Pizza Price: "; 
cin>>small;
while(!isdigit(small)){
    cout<<"Small Pizza Price: ";
    cin>>small;
}

但是当用户输入整数以外的值时,程序就会中断。我想检查用户只输入整数值的位置。

【问题讨论】:

  • 您至少需要显示变量的数据类型。此代码的行为将完全根据small 的类型而改变,即使您认为它们不重要,您也总是需要显示变量声明。
  • isdigit 检查单个 字符 是否为数字。 (数字为'0''1''2''3''4''5''6''7''8' 和@98765433333@54@4。)是int,尝试输入除整数以外的任何内容都会将流设置为错误状态,然后进入无限循环。
  • 这应该怎么做?

标签: c++ c++17


【解决方案1】:

您需要检查int 的提取是否成功,如果没有成功,则可能是clear() 流的失败状态。 cin.eof()cin.bad() 可用于检查流是否处于不可恢复状态,或者您可以将它们与 std::ios::badbit | std::ios::eofbit 组合并检查 std::cin.rdstate() 是否设置了任何这些位。

检查提取是否成功通常通过在布尔上下文中检查流的状态来完成,如下所示:

if(!std::cin) { // or  if(not std::cin)  "not" is an alternative to "!"
    // the stream is in a failed state
}

当您使用std::cin &gt;&gt; small 从流中进行格式化提取时,operator&gt;&gt; 将返回对流的引用,这使得提取和检查状态变得容易:

if(not(std::cin >> small)) { /* extraction failed */ }

完整示例:

#include <iostream>
#include <limits>   // std::numeric_limits

int main() {
    int small;

    while(std::cout << "Small Pizza Price: " && not(std::cin >> small)) {
        // if(std::cin.eof() || std::cin.bad()) {    or:
        if(std::cin.rdstate() & (std::ios::badbit | std::ios::eofbit)) {
            std::cout << "aborted\n";
            return 1;
        }
        std::cout << "please enter a valid price\n";
        std::cin.clear();                            // clear the fail state
        // remove any lingering characters in the istream:
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }

    // small read successfully
}

【讨论】:

  • not 定义在哪里?
  • @TimRandall not 在语言中定义。它反转了bool 参数。它与! 相同,但对于像我这样经常错过! 的人来说更容易发现。 :-)
  • @TimRandall 这是 C++ 最隐蔽的特性之一。这是一个链接:en.cppreference.com/w/cpp/language/operator_alternative
  • if(std::cin.rdstate() &amp; (std::ios::badbit | std::ios::eofbit))也可以写成if(std::cin.bad() || std.cin.eof()),这样对有些人来说可能更容易理解。
  • @RemyLebeau 是的,我在文中提到了这些成员函数,但我可能也应该在代码中包含该选项。已更新。
【解决方案2】:

您没有在源代码中显示变量的声明,小。如果它是一个字符串,我假设提取运算符将向上解析流,直到它遇到空格。如果您要将“小”变量声明为整数或类似浮点的值,则流提取运算符将尝试使用流中当前包含的语言环境从流中解析整数。如果解析流的尝试失败,则将设置流的错误标志,您可以使用非“!”来测试它。运算符。

【讨论】:

    【解决方案3】:

    假设您希望程序只为变量int small 取整数值,我想指出以下几点。

    • char 值而不是int 传递给变量int small 时,程序显示undefined behavior/falls in infinite loop。发生的情况是 cin 进入失败状态,这使它忽略对它的进一步调用,直到错误标志和缓冲区被重置。

    • isdigit() 只接受一个char,如果它包含一个数字,则返回正数(char c='7')。如果char 不包含数字,则函数返回 0。


    可能的解决方案:

    • 要检查是否通过cin&gt;&gt;获取了有效的输入类型(在本例中为int),我们可以检查cin的返回值。如果输入无效,cin 将返回 false 值,反之亦然。

    • 当采用无效(在这种情况下为非数字)输入而不是有效(int)时,我们必须清除 cin 和输入缓冲区以进行进一步输入。为此,我们可以使用:

            cin.clear();
            cin.ignore(100, '\n');//clear next 100 value from input buffer
    
    • 作为您的问题的解决方案,此功能可用于检查输入是否有效。如果没有,它将继续输入,直到找到有效的。
    void get_Untill_Int(int* pInput)//keep taking input untill input is `int or float`
    {
        cin>> *pInput;
        /*-----------check input validation----------------*/
        while (!cin) 
        {
            cin.clear();
            cin.ignore(100, '\n');
            cout<<"Invalid Input Type.\nEnter again: ";
            cin >>*pInput;
        }
        /*-----------checked input validation-------------*/
    }
    

    最终节目

    int small;
    cout<<"Small Pizza Price: "; 
    get_Untill_Int(&small);
    

    【讨论】:

      【解决方案4】:

      您可以在变量未定义时进行检查,您将询问用户的输入,例如:

      int small;
      
      cout<<"Small Pizza Price: ";
      while(small == NULL){
      
          cin>>small;
      }
      

      由于您已将 small 定义为 int,它会重复询问,直到获得有效的 int 作为输入

      【讨论】:

      • 根据您的开发环境,这可能永远不会要求输入。例如small的值如果是在栈上创建的临时变量,可以初始化为0xCCCCCCCC。
      • small 不是未定义。它是 未初始化的 并且读取未初始化的变量会使您的程序具有未定义的行为。另外与NULL 比较可能不是您想要的。你可能想要int small = 0;,然后是while(small == 0)
      • 比较intNULL?它被初始化。是的,它可以编译,但它并没有达到预期的效果。
      • @TedLyngmo 如果用户希望 0 变小,你会怎么做?
      • @Makus 我不确定我是否理解这个问题。在您的示例中,small 在您阅读时未初始化(除非您建议将其设为不推荐的全局变量)。读取未初始化的变量会使程序具有未定义的行为。如果您初始化它(int small{};int small = 0;),您应该与初始化它的值进行比较,而不是用于比较指针的 NULL
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      相关资源
      最近更新 更多