"равно" по отношению к "не равным" операторам в выражении if-else
При написании инструкций if-else в C есть причина, по которой кто-то предпочитал бы использовать оператор "равный" над "не равным", если оба могут дать тот же результат?
В приведенном ниже коде представлен контекст. Если количество аргументов равно 2, строка будет извлекаться от пользователя. Однако, если получено другое значение аргументов, появится сообщение об ошибке.
int main(int argc, string argv[])
{
string msg;
if (argc == 2)
{
msg = GetString();
}
else
{
printf("ERROR: Please only enter a single key! \n");
return 1;
}
Однако я могу достичь того же результата, что и выше, изменив условие цикла if-else как "не равное" и перевернув связанные действия. См. Ниже:
int main(int argc, string argv[])
{
string msg;
if (argc != 2)
{
printf("ERROR: Please only enter a single key! \n");
return 1;
}
else
{
msg = GetString();
}
В любом случае, поскольку оба продукта дают одинаковый результат, следует ли использовать предпочтительный вариант над другим?
Ответы
Ответ 1
В С++ существует одна техническая причина, потому что, если у вас есть привычка использовать ==
over !=
, вам не нужно будет перегружать столько операторов.
Это имеет значение, когда вы имеете дело с объектами функций ( "функторы" ). Например, когда вы используете стандартный контейнерный класс для хранения собственных пользовательских объектов и хотите, чтобы они автоматически сортировались. Чтобы рабочий объект (например, std:: equal_to) работал, ваш класс должен перегружать только оператор ==
. Вам не нужно перегружать ==
и !=
оба.
Аналогично, для других объектов функций требуется только перегрузить <
, а не все < > == != <= >=
.
Как правило, отрицания нелегко понять человеческому мозгу. Особенно если у вас двойные отрицания. На большинстве языков программирования пользовательский язык сначала записывает проверку равенства, если порядок не имеет значения технически. Чаще всего это упрощает чтение кода.
Но так же часто с программированием и стилем кодирования нет чёрных или белых правил. Если причиной проверки является обнаружение ошибки, то наиболее читаемый способ записи обработки ошибок имеет приоритет над тем, что "люди находят отрицания труднее читать".
Считайте это не слишком хорошо написанным кодом:
if(input == good)
{
if(format == expected)
{
do_stuff();
return ok;
}
else
{
return error_format;
}
}
else
{
return error_input;
}
Представьте, что нам нужно добавить еще больше ошибок. Достаточно общий случай: предположим, что мы пишем анализатор или некоторый декодер протокола данных с большим количеством обработки ошибок. Множество уровней вложенных брекетов вскоре превратит код в полный беспорядок.
Мы можем избавиться от необходимости иметь вложенные операторы if, если мы перейдем от == к! =.
if(input != good)
{
return error_input;
}
if(format != expected)
{
return error_format;
}
// if we got here then all is well
do_stuff();
return ok;
Это будет более читаемым и масштабированным, если нам нужно добавить дополнительные проверки ошибок. Поэтому, перейдя на! =, Мы сделали код более удобочитаемым.
Ответ 2
Это просто проблема с кодировкой. Я ненавижу гнездовую основную логику, я напишу ее как:
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("ERROR: Please only enter a single key! \n");
return 1;
}
string msg = GetString();
}
BTW: знак main
должен быть int main(int argc, char *argv[])
.
Ответ 3
Я обычно предпочитаю "равный", потому что он делает код более "читаемым" для человека. Это упрощает код. Это было бы более называться "хорошим руководством по кодированию", чем "правило", поскольку оно вообще не влияет на время выполнения (это было частью моих предыдущих рекомендаций по составлению кода компании).
Проверьте это:
if ( !isEmpty() )
Потребуется ваш мозг на несколько миллисекунд больше, чтобы понять, что делает тест, чем если вы пишете:
if ( isEmpty() )
Даже если это не влияет на время выполнения, я обычно предпочитаю "равно" равным "не равно".
Те же аргументы относятся к именам переменных и функций. Атрибут/метод isSet
присваивается над isNotSet
. Чтение фрагмента кода, такого как if ( !isNotSet() )
, проще, чем если if ( isSet() )
, даже если они эквивалентны в конце.
Если вы используете код, на который вы не контролируете, и это дает члену, отвечающему на отрицательные вопросы, тогда:
if ( isNotSet() )
определенно легче читать для разработчика, чем:
if ( !isNotSet() )
Ответ 4
Как говорили другие, это проблема стиля. Нет никакой реальной разницы.
Однако нужно иметь в виду, что нужно стараться быть последовательным. Если у вас есть один блок проверки, если value1 == 2
, попробуйте не иметь следующую проверку блока value2 != 4
. Единственный плохой стиль - непоследовательный стиль.
Ответ 5
Это вопрос программирования. Как программист, вы должны решить, какой из них будет лучше работать для выполнения, обслуживания, удобочитаемости и производительности. Кроме того, это два совершенно разных утверждения. Если вы хотите, чтобы ваша функция вызывала ТОЛЬКО, когда argc равен 2 по сравнению с вызовом GetString(); когда число не равно 2.
Ответ 6
В настоящее время нет семантической разницы между этими двумя случаями, так как даже более простая оптимизация, применяемая компиляторами, может нарушить "предполагаемый поток выполнения".
Возможно, от 30 до 40 лет назад могла быть какая-то разница между двумя вариантами, когда шаг генерации кода компилятора C был вполне привязан к написанному коду.
Фактическая разница сегодня в синтаксисе и стильности.
Итак, при написании
while( *dst++=*src++ );
теперь может генерировать тот же машинный код, что и
for( i=0; src[i] != 0; i++ )
dst[i] = src[i];
dst[i] = '\0';
Последнее можно было бы гораздо легче читать, как видно из
if( ! isOK() )
dontDoIt();
else
doIt();
и в
if( isOK() )
doIt()
else
dontDoIt();
Но будьте уверены, "ясность" не является абсолютной ценностью: это зависит не только от "навыков программирования и вкуса" читателей/рецензентов, но и от самого кода.
Нижняя линия: сделайте выбор и придерживайтесь его для единообразия!