如何检查变量是否等于多个值

时间:2019-07-07 14:17:26

标签: c logical-operators

在C中 我想检查变量是否等于多个值,并且不完全分离也不知道如何编码。

if (str[i]=='u'||'o'||'i'||'e'||'a')让我永远是真实的,我不明白为什么,我需要解释。

if (str[i]==('u'||'o'||'i'||'e'||'a'))总是给我假,我不明白为什么,我需要解释。

谢谢。

5 个答案:

答案 0 :(得分:2)

以下表达式始终返回true的原因:

if (str[i] == 'u'||'o'||'i'||'e'||'a')

是字符常量的值为true。因此,以上内容实际上是相同的:

if (str[i] == 'u'|| 1 || 1 || 1 || 1)

您打算做的是这个

if (str[i] == 'u' || str[i] == 'o' || str[i] == 'i' || str[i] == 'e' || str[i] == 'a')

请注意,每次比较都需要重复相等表达式。

答案 1 :(得分:2)

您需要:

d = [[0, 0, 192], [0, 0, 0, 0, 56]]

d = [[int(bool(x)) for x in l] for l in d]

print(d)

一个[[0, 0, 1], [0, 0, 0, 0, 1]]

import numpy as np

d = np.array([[0, 1, 2], [3, 0, 4], [5, 6, 0]])
d = np.where(d == 0, 0, 1)

print(d)

可能有更好的机会为您提供更好的代码(自从C的第一个版本以来,上述开关就被用于有效的词法化),而且很多人(包括我)也发现它更具可读性。 (如果您将案例放在{}复合语句中,很多人会发现它更具可读性,但是我正在经历一个阶段,我会尽可能地将它们排除在外。)

答案 2 :(得分:1)

不同的结果与运算符优先级有关。

x == y || z

相同
(x == y) || z

不同
x == (y || z)    

您的表达式为'u'||'o'||'i'||'e'||'a',因此在我们的情况下,y将为'u',而z将为'o'||'i'||'e'||'a'z的计算结果为true,因为至少一个操作数(在本例中为所有操作数)非零。因此,第一行将等效于(str[i] == 'u') || 1,该行当然总会求值为1,这是正确的。另一方面,str[i] == ('u' || 1)str[i] == 1相同,因为'u' || 1的计算结果为1。

在C语言中,没有很好的内置方法来完成这样的事情。您可以做的,很容易概括的是编写这样的自定义函数:

bool isMember(char e, char*s, size_t size)
{
    for(size_t i; i<size; i++) {
        if(s[i] == e)
            return true;
    }
    return false;
}

上述功能很容易针对不同类型进行修改。但是在您的情况下,可以这样使用:

char characters[] = {'u','o','i','e','a'};
if (isMember(str[i], characters, sizeof(characters)) {

在处理char时,有一些更简单的方法,但我选择此解决方案是因为它不仅限于char

答案 3 :(得分:0)

使用||(str[i]=='u'||'o'||'i'||'e'||'a')之类的多个值来束缚(str[i]==('u'||'o'||'i'||'e'||'a'))运算符并不用于检查某个值是否是一组值中的一个。

||运算符是逻辑或运算符。它将两个操作数都视为布尔值,并根据操作数求值为0或1。 C standard的6.5.14节详细介绍了此运算符的使用:

  

2 每个操作数应具有标量类型。

     

3 如果||运算符的两个操作数中的任何一个不等于0,则其结果为1;否则,结果为0。结果的类型为int

     

4 与逐位|运算符不同,||运算符保证从左到右的求值;如果对第二个操作数求值,则在第一个和第二个操作数的求值之间有一个序列点。如果第一个操作数比较不等于0,则不计算第二个操作数。

由于C没有真正的布尔类型,所以任何整数值(包括字符常量)都可以作为||的操作数。因此,任何非零值都将被视为true,而零将被视为false。另外,请注意上面第4段中的内容,该运算符具有“短路”评估功能,这意味着如果仅通过查看左侧即可知道该运算符的结果,则不会评估右侧。

现在,将其应用于表达式。首先:

if (str[i]=='u'||'o'||'i'||'e'||'a')

由于此处要处理多个运算符,因此需要应用详细的here运算符优先级规则。由于相等比较运算符==的优先级高于逻辑OR运算符||,因此,其解析如下:

if ((str[i]=='u')||'o'||'i'||'e'||'a')

因此,我们首先评估str[i]=='u'。根据{{​​1}}是否为str[i],它可以是0或1。然后我们评估第一个'u',所以我们有||1||'o'

在第一种情况下,左侧操作数为1,因此不评估右侧上方的第4段,其中包括其他0||'o'运算符,因此最终结果为1,即为true,这是期望的结果。在第二种情况下,0为假,因此我们看一下右边的||。这是一个字符常量,其值是用于编码字符'o'的值。如果您的系统使用ASCII(很可能会这样做),则该值为111。由于这是一个非零值,因此整个表达式'o'的计算结果为1,即true。同样,由于0||'o'的短路行为,由于左侧为true,因此未评估下一个||运算符。这意味着上面的表达式总是正确的。

现在转到第二个表达式:

||

首先评估的是if (str[i]==('u'||'o'||'i'||'e'||'a')) 'u'||'o'字符的ASCII码为117,该字符非零,因此第一个'u'的结果为1,右侧为||的运算符,不进行评估。现在,您有了||。除非str[i] == 1包含不可打印的字符,否则您将永远找不到编码为1的字符,因此该表达式的计算结果始终为0,即false。

C没有内置的运算符来检查值是否是集合的成员,这意味着您需要显式检查str每个字符:

str[i]

或者您可以创建一个字符数组来检查并遍历它们:

if ((str[i]=='u') || (str[i]=='o') || (str[i]=='i') || (str[i]=='e') || (str[i]=='a'))

或者您可以使用char vowels[5] = "aeiou"; // an array of char, but NOT a string int found = 0; for (int j = 0; j < sizeof(vowels); j++) { if (str[i] == vowels[j]) { found = 1; break; } } if (found) { ... 来为您遍历所有值:

strchr

或将if (strchr("aeiou", str[i])) 用于失败情况:

switch

答案 4 :(得分:0)

||运算符不允许您以这种方式“链接”条件。 a || b || c的值为(a || b) || c-a || b结果(将为0或1)将与c或。

对于您要执行的操作,最干净的选择是使用Machine_1在对Tim Biegeleisen的答案的评论中建议的strchr

#include <string.h>
...
if ( str[i] >= 0 && strchr( "aeiou", str[i] ) )
{
  // str[i] is one of 'a', 'e', 'i', 'o', or 'u'
}

我检查str[i]是否为负数,因为chux声称将str[i]的负值传递给strchr会导致不确定的行为;但是,从标准来看,我认为这不是真的:

7.24字符串处理

7.24.1字符串函数约定

...
3对于本节中的所有功能,每个字符都应被解释为具有以下类型: unsigned char(因此,每种可能的对象表示形式都是有效的,并且具有 不同的值)。

但是,出于理智的考虑,我们还是将其保留。