【问题标题】:'If' condition not correctly evaluated“如果”条件未正确评估
【发布时间】:2019-09-23 15:14:54
【问题描述】:

要从 shell 接收包含在 (0, 8) 区间内的整数值,我将 cin 转换为数组的 uint8_t 元素,执行以下操作:

    char answer;

    do
    {
        // Instructions
        std::cout << "Linear actuator resolution is:\n"
                  << "\u0394x = \u03B1r/2^i, with \u03B1 = " << std::to_string(ALPHA)
                  << " degrees, r = " << std::to_string(pulleyR) << " m and i in [0 : 8]\n";

        // Parameter selection
        std::cout << "Please enter a valid value for param 'i': ";
        std::cin >> Engines_uSteppingLevel[RAIL];
        if(Engines_uSteppingLevel[RAIL] > (RES_LEVELS - 1))
            // Wrong selection, repeat question
            std::cout << '\r';
        else
        {
            // Print out the selected resolution and ask user to confirm or restart selection
            std::cout << "Selected linear resolution: " << std::fixed << std::setprecision(4)
                      << ALPHA*pulleyR/(1<<Engines_uSteppingLevel[RAIL])
                      << "m, enter 'y' to confirm, any other key to change selection ";
            std::cin >> answer;
            if(answer == 'y')
                break;
        }
    }while(true);

即使我输入了正确的值,循环也不会中断。

输入:

std::cout << Engines_uSteppingLevel[RAIL] << ' ' << (RES_LEVELS - 1) << '\n';

代替:

   std::cout << '\r';

shell 输出是:

Please enter a valid value for param 'i': 0
0 8
Please enter a valid value for param 'i': 3
3 8

这没有意义。

【问题讨论】:

  • 从标准输入读取的原始和熟(行缓冲)读取不能很好地混合。您需要摆脱_getch() 调用,或者摆脱std::cin 并仅使用_getch()
  • 不过,我认为您的问题是对 continue 关键字跳转到的确切位置的误解。
  • 对,它跳转到_getch()结果评估,所以只有在第一轮值正确的情况下,这个东西才能工作。不过,如果输入的第一个值是正确的,则不应达到“继续”
  • 你的代码中有很多有问题的东西。一,循环直到你按下y 是这段代码的作用,我不知道为什么这会让你感到惊讶。第二,std::fixedstd::setprecision 修饰符没有任何效果,因为您将字符串写入流,而不是数字。那么,RAIL 的值是多少,数组有多大呢?如果您访问数组中不存在的元素,程序可能会做一些非常奇怪的事情(“未定义行为”)。
  • 也请std::cout &lt;&lt; +Engines_uSteppingLevel[RAIL](或转换为int)。我怀疑您触发了基于字符的 I/O,并且您的变量包含 ASCII 值 '0''3' 而不是数值 03

标签: c++


【解决方案1】:

您在这里遇到的问题在于 C++ 处理 uint8_t 类型的方式:它认为它是一个字符。如果您将调试输出语句更改为:

std::cout << static_cast<int>(Engines_uSteppingLevel[RAIL]) << ' ' << (RES_LEVELS - 1) << '\n';

您会看到,当您输入“0”时,ASCII“0”存储在您的 uint8_t 变量中,其值为 48。类似地,当您输入“3”时,您存储的是 51,以此类推。

对您有用的最简单的解决方案是使用字符转换,如下所示:

Engines_uSteppingLevel[RAIL] -= '0';

请注意,此解决方案仅适用于单个数字值。更健壮、可扩展的解决方案将涉及 std::string 或 char 缓冲区,然后调用 atoi、strtoul、std::stoul 或类似的东西。

【讨论】:

  • uint8_tunsigned char 还是“扩展整数类型”实际上取决于实现。最简单的解决方案是读入一个数值变量,验证值,然后将其存储到数组中。
  • 这个答案很好地分析了(u)int8_t如何映射到不同平台上的不同提取运算符:stackoverflow.com/a/16006093/103167
猜你喜欢
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 1970-01-01
  • 2019-06-06
相关资源
最近更新 更多