чтение, пока пользователь не введет пустую строку - PullRequest
1 голос
/ 10 декабря 2010

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

a) отрыв от цикла

std::vector<std::string> container;
for (; ;)
{
    std::string line = get_input();
    if (line.empty()) break;
    container.push_back(line);
}

b) чтение перед циклом и внутри цикла

std::vector<std::string> container;
std::string line = get_input();
while (!line.empty())
{
    container.push_back(line);
    line = get_input();
}

c) чтение как частьусловия цикла, версия присвоения

std::vector<std::string> container;
std::string line;
while (!(line = get_input()).empty())
{
    container.push_back(line);
}

d) считывается как часть условия цикла, версия последовательности

std::vector<std::string> container;
std::string line;
while (line = get_input(), !line.empty())
{
    container.push_back(line);
}

e) читается слишком много, удаляется после цикла

std::vector<std::string> container;
std::string line;
do
{
    line = get_input();
    container.push_back(line);
}
while (!line.empty());
container.pop_back();

Итак, какое решение вы бы предпочли и почему?Что будет проще всего понять новичку?

Ответы [ 4 ]

2 голосов
/ 10 декабря 2010

Я бы на самом деле использовал метод "d":

-Это, на мой взгляд, лучше всего показывает, что сделано: сначала прочитайте данные, затем, если это не «хорошие» данные (пустая строка), прекратите чтение данных. И все находится в ожидаемой позиции (проверка данных находится в части условия цикла, обработка данных в теле цикла.

Мтеод "а" скрывает проверку состояния, и мне труднее (на мой скромный взгляд) увидеть условие, которое "останавливает" цикл.

2 голосов
/ 10 декабря 2010

Я предпочитаю (а). просто и читается вполне естественно.

(b) повторяет строку, которая получает ввод.

(c) и (d) оба используют синтаксис, который может вводить в заблуждение новичков (в частности, запятая не в операторе или определении for и присвоение в условном выражении). Я, вероятно, предпочел бы (с), а не (d).

(е) ... неэффективно. Что если этот последний push_back вызвал перераспределение?

0 голосов
/ 10 декабря 2010

Модификация (d) делает его более эффективным и соответствует тому, что вы пытаетесь сделать лучше.

std::vector<std::string> container;
std::string line;
do
{
    line = get_input();
    if (!line.empty())
    {
        container.push_back(line);
    }
    else
    {
        break;
    }
}
while (true);
0 голосов
/ 10 декабря 2010

Как вы, вероятно, ожидаете от меня, я бы предложил прокси:

class non_blank {
   std::string data;

   friend operator>>(std::istream &is, non_blank &n) {
       std::string temp;

       std::getline(is, temp);

       // I'm not writing this from home, so I'm going from memory.
       // The following line is probably a little wrong.
       is.setbit(std::ios::fail, temp.length()!=0);
       return is;
   }
   operator std::string() { return data; }
};

non_blank line;
while (infile >> line)
    container.push_back(line);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...