Цикл while с оператором запятой дублирует кодовые стихи «break;»

Прочитав отличный ответ про оператор запятой в C / C ++ (Что делает оператор запятой — и я использую тот же пример кода), я хотел знать, какой является наиболее читабельным, поддерживаемым, предпочтительным способом реализации цикла while. В частности, цикл while, состояние которого зависит от операции или вычисления, а также от условия может быть ложным в первый раз (если цикл должен был пройти хотя бы один раз тогда do-while будет работать нормально).

Является ли версия с запятой наиболее предпочтительной? (как насчет ответа для каждого, а остальные могут голосовать, проголосовав соответственно?)

Простая реализация

Этот код имеет повторяющиеся утверждения, которые (скорее всего) всегда должны быть одинаковыми.

string s;
read_string(s);     // first call to set up the condition
while(s.len() > 5)  // might be false the first pass
{
//do something
read_string(s);  // subsequent identical code to update the condition
}

Реализация с использованием перерыва

string s;
while(1)                  // this looks like trouble
{
read_string(s);
if(s.len() > 5) break; // hmmm, where else might this loop exit
//do something
}

Реализация с использованием запятой

string s;
while( read_string(s), s.len() > 5 )
{
//do something
}

0

Решение

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

Возможно, у вас есть строка, которая всегда должна иметь минимальную длину. Если это так, вы можете определить
класс, который воплощает это требование:

template <size_t min>
class MinString{
std::string data;
public:
friend std::istream &operator>>(std::istream &is, MinString &m) {
std::string s;
read_string(is, s); // rewrite read_string to take an istream & as a parameter
if (s.length() >= min)
m.data = s;
else
is.setstate(std::ios::failbit);
return is;
}

operator std::string() { return data; }

// depending on needs, maybe more here such as assignment operator
// and/or ctor that enforce the same minimum length requirement

};

Это приводит к коду примерно так:

Minstring<5> s;
while (infile >> s)
process(s);

Другая возможность состоит в том, что у вас есть нормальные строки, но при некоторых обстоятельствах вам нужно выполнить чтение, которое должно быть в
минимум 5 символов. В этом случае исполнение должно быть в функции, а не в типе.

bool read_string_min(std::string &s, size_t min_len) {
read_string(s);
return s.length() >= min_len;
}

Опять же, с этим цикл может быть простым и чистым:

while (read_string_min(s, 5))
process(s);

Также возможно просто написать функцию, которая возвращает длину, которая была прочитана, и оставить применение минимума
длина в цикле while:

while (read_string(s) > 5)
process(s);

Некоторым это нравится из-за идеи, что она лучше соответствует принципу единой ответственности. IMO, «прочитать строку, состоящую как минимум из 5 символов», вполне подходит как отдельная обязанность, поэтому в лучшем случае это кажется мне слабым аргументом (но даже этот дизайн все же позволяет легко писать код чисто).

Резюме: все, что делает ввод, должно либо неявно, либо явно предоставлять какой-либо способ проверки правильности чтения ввода. То, что просто пытается прочитать некоторые входные данные, но не дает указания на успех / неудачу, является просто плохим дизайном (и это тот очевидный сбой в дизайне вашего read_string это приводит к проблеме, с которой вы столкнулись).

3

Другие решения

Есть четвертый вариант, который мне кажется лучше:

string s;
while( read_string(s) && s.len() > 5 )
{
//do something
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector