【问题标题】:How and when to use the getline function to perform calculations?如何以及何时使用 getline 函数执行计算?
【发布时间】:2019-02-09 10:31:50
【问题描述】:

我正在学习 C++ 课程,有人要求我使用 getline 计算圆的面积。我被建议不要使用cin,除非真的有必要。

下面是我的代码..

#include <iostream>
#include <string>

int main()
{
    std::string question ("Enter the radius: ");
    std::string s_radius;
    std::cout << question;

    getline(std::cin, s_radius);

    const double PI = 3.14159;
    double n_radius = std::stod(s_radius);
    double area = PI * n_radius * n_radius;

    std::cout << "The area of the circle = " << area << std::endl;

    return 0;
}

真的有必要通过接受字符串作为输入并将其转换为数字来执行计算的过程吗?

【问题讨论】:

  • 如何获取输入以及对输入进行的计算是正交问题。使用cin 通常更容易,有时更容易使用getline,这取决于输入的格式。但是,“除非真的有必要,否则不要使用 cin”我以前从未听说过
  • @Carcigenicate 无论您使用std::cin &gt;&gt; 还是getline,您都可以忽略错误,但这并没有真正使它们与众不同
  • 一定有什么误解——你还在使用std::cin。 (如果不使用std::cin,从标准输入中读取并不容易。)如果要求您使用getline 读取输入,则无法绕过转换。
  • 在切线上:数字是一个符号——即某种字符串——而不是数字。 “12”和“XII”都是代表数字十二的数字。文字数值,如3.141590,是数字。另一方面,PIn_radius 的值不是。

标签: c++ getline


【解决方案1】:

真的有必要通过接受字符串作为输入并将其转换为数字来执行计算的过程吗?

这不是绝对必要的,但它确实会养成良好的习惯。假设您要向用户询问 2 个号码并使用类似

std::cout << "Enter first number: ";
std::cin >> first_number;
std::cout << "Enter second number: ";
std::cin >> second_number;

对于用户输入的第一个数字123boboperator&gt;&gt; 将开始读取它,一旦它到达b,它将停止并将123 存储到first_number 中。现在流中仍有bob。当它询问第二个数字时,因为bob 仍在流中,它将失败并且second_number 将设置为0。然后程序将继续运行,您将得到垃圾输出,因为您接受了垃圾输入。

现在,如果您以 std:string 的形式读入,然后转换为您想要的内容,则可以更轻松地捕获这些类型的错误。 getline(std::cin, some_string); 将从输入缓冲区中取出所有 123bob,因此您不必担心必须清理它。然后使用stoi(或任何stox 函数)它将读取它的有效值。这些函数还有第二个参数,它是一个指向 size_t 的指针,如果你传递它一个,它将存储字符串中第一个未转换字符的位置,你可以使用它来判断整个输入字符串是否有效或不是。所以,如果你有

std::string input;
std::cout << "Enter some number: ";
std::getline(std::cin, input);
std::size_t pos;
double number = std::stod(input, &pos);
if (pos == input.size())
    std::cout << "valid input\n";
else
    std::cout << "invalid input\n";

然后1.23bob 将导致invalid input 打印,而1.23 导致valid input 打印。您甚至可以在循环中使用它来确保您只获得有效的输入,例如

double number;
do
{   
    std::string input;
    std::cout << "Enter some number: ";
    std::getline(std::cin, input);
    std::size_t pos;
    number = std::stod(input, &pos);
    if (pos != input.size())
        std::cout << "invalid input\n";
    else
        break;
} while(true)

TL;DR:如果你依赖用户只输入有效的输入,你最终会被烧毁。作为字符串读入和转换提供了一种一致的方式来确保您只从用户那里获得良好的输入。

【讨论】:

    【解决方案2】:

    我被建议不要使用 cin,除非真的有必要。

    首先有个误区,因为你还在用std::cin。我会将您的问题解释为使用std::cin::operator &gt;&gt;getline(std::cin,...)。接下来我宁愿建议你相反:如果可以,直接使用operator&gt;&gt;,如果必须,回退到getline

    一个非常人为的例子:

    想象一下,您将整数以这种(不必要的复杂)格式存储在文件中,

    3123212
    ^-------- number of digits of the first number
     ^^^----- first number
        ^---- number of digits of the second number
         ^^-- second number
    

    您不能使用纯std::cin &gt;&gt; 来读取这些数字。相反,您需要阅读整行然后解析数字。然而,即便如此,我强烈建议为operator&gt;&gt; 提供重载,类似于

    struct NumbersReadFromStrangeFormat {
        std::vector<int> numbers;
    };
    
    std::isstream& operator>>(std::istream& in,NumbersReadFromStrangeFormat& num) {
        // use getline and parse the numbers from the string
        return in;
    }
    

    这样你就可以再写:

    NumbersReadFromStrangeFormat numbers;
    std::cin >> numbers;
    

    结论: 重载operator&gt;&gt; 是从输入流中读取内容的惯用方式。 “使用std::cin”或“使用getline”并不是真正的替代品。 “避免使用std::cin”一定是一种误解。如果没有 operator&gt;&gt; 的重载已经可以满足您的需要,您可以编写自己的并很好地隐藏任何 getline 或其他解析细节。

    【讨论】:

      猜你喜欢
      • 2013-01-13
      • 1970-01-01
      • 2011-10-21
      • 2014-09-05
      • 2021-08-05
      • 2021-07-15
      • 2020-03-28
      • 2016-02-07
      • 1970-01-01
      相关资源
      最近更新 更多