C中的if语句否定

Posted

技术标签:

【中文标题】C中的if语句否定【英文标题】:if statement negation in C 【发布时间】:2021-08-20 17:01:04 【问题描述】:

您好,我目前正在做一个编程练习,我想确定一些事情。

这是关于 if 语句的否定,像这样:if(!(condition)),if 语句的否定和 not 有什么区别?这是一个程序示例,它通过 if(!(condition)) 而不是 if(condition) 给了我想要的结果。

这是函数,这个函数的目的是检查字符串是否为数字。这个功能我已经测试过了。

bool check_key(char* key)
    for(int i =0; i <strlen(key); i++)
    
        if(!isdigit(key[i]))
            return false;
    
    return true;

但是这个版本为什么不行?

bool check_key(char* key)
    for(int i =0; i <strlen(key); i++)
    
        if(isdigit(key[i]))
            return true;
    
    return false;

我错过了什么吗?

对不起,如果我的英语不好,我不是本地人。

【问题讨论】:

例如,如果我输入字符串“4xx”,它将被返回为真并被无否定函数视为数字,而否定函数将返回字符串为假而不考虑字符串作为数字。 拿一支笔和一张纸复习一下程序。对于"4xx",第一次迭代条件为真,所以return true被立即调用,所以函数返回真。 取决于返回类型,isdigit() 返回一个 int,因此否定等于 if (isdigit(key[i]) == 0... 因此,在您退出后,它在第二种情况下不会按预期工作,如果条件为真,而您可能需要比较更多字符... 第一个停止检查并在看到第一个非数字时返回。第二个在看到第一个数字时停止检查并返回。 这类似于De Morgan's law。这就像问为什么a || b 不等于!(!a || !b) 【参考方案1】:

这个函数

bool check_key(char* key)
    for(int i =0; i <strlen(key);i++)
    
        if(isdigit(key[i]))
            return true;
    

    return false;

检查指针key 指向的字符串是否包含至少一个代表数字的符号。一旦找到这样的符号,函数就会退出。

这个函数

bool check_key(char* key)
    for(int i =0; i <strlen(key);i++)
    
        if(!isdigit(key[i]))
            return false;
        
        return true;
    

检查指针键指向的字符串的所有符号是否都代表数字。

也就是第一个函数中if语句的子语句

        if(isdigit(key[i]))
            return true;

当当前符号代表一个数字时获得控制权,如果是,则函数立即退出,尽管其他符号可以代表非数字,但返回 true。

在第二个函数中,if 语句的子语句

        if(!isdigit(key[i]))
            return false;
        

在当前符号不代表数字时获得控制权,如果是,则函数立即退出,返回 false。这意味着指针键指向的字符串至少包含一个非数字符号。

注意这两个函数都不正确。尽管空字符串不包含任何数字,但对您而言似乎正确的函数对空字符串返回 true。

同样调用函数strlen也是低效的。

函数应该至少按以下方式声明和定义

bool check_key( const char *key )

    if ( *key == '\0' ) return false;

    while ( isdigit( ( unsigned char )*key ) ) ++key;

    return *key == '\0';

【讨论】:

((unsigned char)*key) 是什么意思?哪里返回 true ?以及为什么返回 *key == '\0' @dieri 传递给函数 isdigit 字符应转换为 unsigned char 类型。否则,该函数可以调用未定义的行为。此返回语句 return *key == '\0';意味着如果在循环之后当前符号是终止零符号 '\0' 那么它意味着所有前面的符号都是数字。也就是说,在这种情况下,条件 *key == '\0' 的计算结果为逻辑真。否则,它被评估为逻辑假。这是将 int 类型的表达式 1 或 0 转换为返回类型 bool 的函数的结果:true 或 false。 @dieri 关于isdigit((unsigned char )*key) 部分的更多信息:弗拉德是对的,这是一个悲惨的、难以回忆的可怕麻烦事。如果类型 char 是有符号的(因为它在许多编译器下),并且如果您的输入字符串包含非 ASCII 字符,它们可能看起来是负数,这意味着您将负数传递给 isdigit(),如果 @987654331 @ 的实现很简单,它可能会崩溃,根据标准它是允许的。将传递给任何 isxxx 宏的每个字符显式转换为可修复该问题。 好的,谢谢,你有什么建议吗,我真的需要提高我的编程技能,任何 youtube 频道?书 ?还是网站? @dieri 您需要从 Internet 下载 C 标准草案的副本。它是可用的。【参考方案2】:

第一个版本在找到不是数字的字符后立即返回false。如果到达循环末尾,则返回true。所以它只返回true如果每个字符是一个数字,即字符串看起来像一个数字。

第二个版本一找到数字字符就返回true。如果到达循环末尾,则返回false。因此,如果 任何 个字符是数字,则返回 true,如果 没有 个字符是数字,则仅返回 false

所以如果key 包含数字和非数字的混合,例如"a1b",第一个版本将返回false,但第二个版本将返回true

【讨论】:

其实第一个只检查第一个字符并返回。 哦,对了。我什至修复了缩进,但没有看到。 哦,不,是我被缩进骗了。 doh,我在编辑时弄错了缩进——我讨厌人们不在 if 正文周围加上大括号。【参考方案3】:

您偶然发现了一个重要、深刻但有时容易被忽视的逻辑问题。当你写的时候

for(i = 0; i < strlen(key); i++) 
    if(!isdigit(key[i]))
        return false;

return true;

你的意思是如果任何字符不是数字,返回false

但是当你说

for(i = 0; i < strlen(key); i++) 
    if(isdigit(key[i]))
        return true;

return false;

您的意思是如果任何字符是数字,则返回 true

看到区别了吗?

对于输入 "123",两个函数都返回 true。

对于输入 "abc",两个函数都返回 false。

但是对于输入"12x",第二个函数返回true,因为至少有一个字符是数字。另一方面,第一个函数正确返回 false,因为至少有一个字符不是数字。

这与De Morgan's Law有关。

您可能还想考虑如果给定输入(如 "-123"" 123""123 ""123\n"),该函数应该做什么。

【讨论】:

再次阅读第一个的作用。您删除了一个 这会改变它。 感谢您的洞察力,我知道我忘记了这种简单的 if 语句机制。我已经尝试使用“123”的函数,它已作为数字返回,必须添加其他参数才能使其工作! @dieri 另一个容易忘记的案例是"-123"。 (根据您的需要,您可能还想接受"+123"。)

以上是关于C中的if语句否定的主要内容,如果未能解决你的问题,请参考以下文章

在 if 语句内继续循环与在循环内使用 if 语句的否定

带有条件赋值的嵌套否定 if 语句

c语言中的 条件语句 if else

c语言中的条件语句if

JSP中的if语句。

python中循环语句