"if (isupper(argument) == true)" 和“if (isupper(argument))”有什么区别?注意:参数是我程序中的任何字符

What's the difference between "if (isupper(argument) == true)" and " if (isupper(argument))"? Note: argument is any char in my program

我在做 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 key\n");
                return 1;
            }
        }
    }
    else
    {
        printf("Usage: ./caesar key\n");
        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: %s\n", ciphertext);
}

int isupper(int) 不是 return 布尔值(0 或 1 值)。如果 arg 是大写的,它 return 是一个非零整数。

两种情况的区别在于,一种是将return值与1进行比较,另一种是将return值与非零值进行比较。

当你有一些你认为是true/false的东西时,永远不要写

if(thing == true)

if(thing == false)

随便写

if(thing)

if(!thing)

原来 isupper()islower() 以及 <ctype.h> return zero/nonzero 中的其余 isxxx 函数用于 false/true,但 不一定 0/1。如果 isupper('A') returns,比方说,4,那么 if(isupper(argument)) 会按你预期的那样工作,但 if(isupper(argument) == true) 总是会失败。

另见 question 9.2 in the C FAQ list

将真值(布尔表达式)与真值常数进行比较是一种糟糕的风格

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 的情况下,有一个隐藏的 bug。为了成为“真”,在 C 中非零就足够了。但是true在C中定义为1.

==/!= true/false 也显示二等布尔值,你也可以做 (X == true) == true。冗余和隐藏作为一等公民的原始状态。它显示了编程知识的缺失(虽然不严重)

来自C标准(7.4.1字符分类函数)

1 The functions in this subclause return nonzero (true) if and only if the value of the argument c conforms to that in the description of the function.

即在 C 中,条件中使用的任何 non-zero 值都被视为逻辑真。它与 header <stdbool.h> 中定义的常量 true 不同。即任何函数 isdigitisalphaisupper 都可以 return 任何 non-zero 值作为真值。但并不意味着函数将return恰好1定义在header<stdbool.h>中的常量true作为宏true。因此,例如这个 if 语句

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

你必须写

if (isupper(plaintext[i]) )

或者例如

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

因为常量 false 等价于值 0.