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语句否定的主要内容,如果未能解决你的问题,请参考以下文章