Как и когда использовать функцию getline для выполнения расчетов? - PullRequest
0 голосов
/ 04 сентября 2018

Я беру курс по 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;
}

Действительно ли необходимо пройти процесс принятия строки в качестве входных данных и преобразовать ее в число для выполнения вычисления?

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Действительно ли необходимо пройти процесс принятия строки в качестве входных данных и преобразовать ее в число для выполнения вычисления?

Это не является строго необходимым, но оно навязывает хорошие привычки. Предположим, вы собираетесь запросить 2 номера у пользователей и использовать что-то вроде

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

Для первого номера пользователь вводит 123bob. operator>> начнет читать его, и как только он достигнет 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: если вы полагаетесь на то, что пользователь вводит только действительные данные, в конечном итоге вы обожжетесь. Чтение в виде строки и преобразование предлагает последовательный способ гарантировать, что вы получаете только хороший вклад от вашего пользователя.

0 голосов
/ 04 сентября 2018

Мне посоветовали воздержаться от использования cin, если это действительно не нужно.

Прежде всего, есть недоразумение, потому что вы все еще используете std::cin. Я интерпретирую ваш вопрос как std::cin::operator >> против getline(std::cin,...). Далее я бы предпочел вам обратное: используйте operator>> напрямую, если можете, и отступите к getline, если нужно.

Очень надуманный пример:

Представьте, что у вас есть целые числа, хранящиеся в файле в этом (излишне сложном) формате,

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

Вы не можете использовать голые std::cin >> для чтения этих чисел. Вместо этого вам нужно прочитать всю строку, а затем проанализировать числа. Однако даже для этого я настоятельно рекомендую предоставить перегрузку для operator>>, что-то вроде

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>> - это нелепый способ чтения чего-либо из входного потока. «Использование std::cin» или «использование getline» на самом деле не являются альтернативой. «Воздержание от использования std::cin» должно быть недоразумением. Если нет перегрузки operator>>, которая уже делает то, что вам нужно, вы можете написать свою собственную и аккуратно скрыть любые getline или другие детали анализа.

...