В чем разница между «if (isupper(аргумент) == true)» и » if (isupper(аргумент))»? Примечание: аргумент-это любой символ в моей программе

#c #cs50

Вопрос:

Я выполнял набор задач CS50 «Цезарь», и когда я попытался сдвинуть заглавные буквы, используя if (isupper(argument) == true) для проверки, был ли символ, который я хотел переместить, прописным, это не сработало, он подумал, что заглавные буквы на самом деле не были прописными. Когда я включил его if (isupper(argument)) , программа правильно сдвинула заглавные буквы. Есть ли какая — то разница между этими двумя форматами? Вот код, который я использовал (я имею в виду код в цикле for):

 #include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int main(int argc, char *argv[])
{
    //Check wether there is only 1 command line argument
    if (argc == 2)
    {
        //Check if there is any character that's not a digit
        for (int i = 0; i < strlen(argv[1]); i  )
        {
            if (isdigit(argv[1][i]) == false)
            {
                printf("Usage: ./caesar keyn");
                return 1;
            }
        }
    }
    else
    {
        printf("Usage: ./caesar keyn");
        return 1;
    }
    
    //Convert key to an int
    int key = atoi(argv[1]);
    
    //Prompt plaintext
    string plaintext = get_string("plaintext: ");
    string ciphertext = plaintext;
    
    //Shift ciphertext's characters by the amount of "key"
    for (int i = 0; i < strlen(plaintext); i  )
    {
        //If it isn't a letter, do nothing
        if (isalpha(plaintext[i]) == false)
        {
            ciphertext[i] = plaintext[i];
        }
        else
        {
            //If it's uppercase
            if (isupper(plaintext[i]) == true)
            {
                //Convert ASCII to alphabetical index
                plaintext[i] -= 'A';
                //Shift alphabetical index
                ciphertext[i] = (plaintext[i]   key) % 26;
                //Convert alphabetical index to ASCII
                ciphertext[i]  = 'A';
            }
            //If it's lowercase
            else if (islower(plaintext[i]))
            {
                //Convert ASCII to alphabetical index
                plaintext[i] -= 'a';
                //Shift alphabetical index
                ciphertext[i] = (plaintext[i]   key) % 26;
                //Convert alphabetical index to ASCII
                ciphertext[i]  = 'a';
            }
        
        }

    }
    
    //Print ciphertext
    printf("ciphertext: %sn", ciphertext);
}
 

Комментарии:

1. Сначала сохраните результат в переменной, прежде чем делать свое предположение, потому что функция должна сначала вернуть результат, а затем выполнить результирующие сравнения. Например, int result = isupper(аргумент); затем просмотрите содержимое «результата» с помощью отладки/точки останова. Я не говорю, что это правильный способ кодирования, но в данной ситуации это дает вам дополнительное представление, которое, я думаю, будет ценным.

2. true это одна из ценностей, которая обладает правдивостью.

3. @rici так и есть, хороший улов.

4. @rici, в котором они находятся , stdbool.h но если бы было допустимо/рекомендовано использовать их с isupper et. al., не следовало бы/не ctype.h должно было бы включать stdbool.h само по себе, и макросы должны были бы обеспечивать истинное логическое значение 1/0?

5.@крейг: если isupper бы вернули bool или даже _Bool , это было бы приемлемо для сравнения true . Даже тогда я бы этого не сделал, и я не думаю, что ты бы тоже этого сделал. if (booleanValue == true) это шум. Но неуместно говорить (как это сделал отредактированный комментарий), что вы не должны использовать true и false потому, что они не являются стандартными. Они стандартны, и у них есть применение. Это не один из них, и необходимо объяснить, почему это так. (И так оно и было.)

Ответ №1:

int isupper(int) не возвращает логическое значение (значение 0 или 1). Он возвращает ненулевое значение int, если аргумент в верхнем регистре.

разница между этими двумя условиями заключается в том, что одно сравнивает возвращаемое значение с одним, а другое сравнивает возвращаемое значение с ненулевым.

Комментарии:

1. О, в этом есть смысл! Спасибо за вклад! 😀

Ответ №2:

Когда у вас есть что-то, что вы считаете правдой/ложью, никогда не пишите

 if(thing == true)
 

или

 if(thing == false)
 

Просто напиши

 if(thing)
 

или

 if(!thing)
 

Оказывается, что isupper() и islower() и остальные функции <ctype.h> isxxx возвращают ноль/ненулевое значение для false/true, но не обязательно 0/1. Если isupper('A') вернется, скажем, 4, то if(isupper(argument)) будет работать так, как вы ожидаете, но if(isupper(argument) == true) всегда будет терпеть неудачу.

См.также вопрос 9.2 в списке часто задаваемых вопросов C.

Комментарии:

1. Хорошая практика. Однако, хотя true тест плохой, false тест в порядке [возможно, плохой стиль] (например (thing == 0) === (! thing) ). Лично я никогда не использую true/false определения, но второе [всегда] будет работать.

2. Хорошая рекомендация.

3. О, ух ты, теперь мне все так ясно! Это было действительно хорошо сказано, спасибо 🙂

4. Некоторая досадная деталь: если вы запустите cppcheck, он выдаст предупреждения: «[misra-c2012-14.4] Управляющее выражение оператора if и управляющее выражение оператора итерации должны иметь по существу логический тип» даже для кода, подобного if (function_returning_bool()) . Насколько более «по существу буланов», чем тип возврата bool , он может получить?

Ответ №3:

Это плохой стиль-сравнивать значение истинности (логическое выражение) с константой истинности

 if (isdigit(argv[1][i]) == false) // Bad style
if (!isdigit(argv[1][i]))         // Better

if (isupper(argument) == true) // Bad style
if (isupper(argument))         // Better 
 

В случае isupper наличия скрытой ошибки. Чтобы быть «истинным», в C достаточно быть ненулевым. Но true определяется как 1 в C.

==/!= true/false Также отображаются логические значения второго рейтинга, которые вы могли бы с таким же успехом сделать (X == true) == true . Избыточен и скрывает исходное состояние как гражданин первого ранга. Это показывает отсутствие некоторых знаний в области программирования (хотя и несерьезных).

Ответ №4:

Из стандарта C (7.4.1 Функции классификации символов)

1 Функции в этом подпункте возвращают ненулевое значение (true) тогда и только тогда, когда значение аргумента c соответствует значению в описании функции.

То есть в C любое ненулевое значение, используемое в условии, считается логическим истинным. Это не то же самое, что константа true , определенная в заголовке <stdbool.h> . Это любая из функций isdigit , isalpha или isupper может возвращать любое ненулевое значение в качестве истинного значения. Но это не означает, что функция вернет именно ту константу 1 , которая определена в заголовке <stdbool.h> как макрос true . Поэтому вместо этого, например, это утверждение if

 if (isupper(plaintext[i]) == true)
 

вы должны написать либо

 if (isupper(plaintext[i]) )
 

или, например,

 if (isupper(plaintext[i]) != false)
 

потому что константа false эквивалентна значению 0 .