C语言中有关布尔值和if/else if的代码评审

vuktfyat  于 2023-01-29  发布在  其他
关注(0)|答案(3)|浏览(112)

我想出了这个解决方案与一些关于CS50第2周问题集密码的帮助。提示是使用2函数来产生一个简单的密码检查器,验证输入字符串有1个大写字母,1个小写字母,1个数字,和1个符号。建议是使用布尔值。但是,我有3个问题,如何和为什么这样做:
1.布尔......我还在纠结呢。为什么不把真的部分放进去呢?布尔就一定是真的吗?
1.经过一番研究,我现在明白了if子句中的最后一条语句不必是else,因为它不能被指定。但是为什么一条if和三条else if可以工作呢?我最初预计它将是一种嵌套的if语句。

  1. bool valid(字符串密码)函数是否接受false和true作为输入,因为它被定义为使用bool?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>

bool valid(string password);

int main(void)
{
    string password = get_string("Enter your password: ");
    if (valid(password))
    {
        printf("Your password is valid!\n");
    }
    else
    {
        printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
    }
}
bool valid(string password)
{
    bool haslower = false;
    bool hasupper = false;
    bool hasdigit = false;
    bool haspunct = false;
    int i;

    for (i = 0; password[i] != '\0'; i++)
    {
        if (isupper(password[i]))
        {
            hasupper = true;
        }
        else if (islower(password[i]))
        {
            haslower = true;
        }
        else if (isdigit(password[i]))
        {
            hasdigit = true;
        }
        else if (ispunct(password[i]))
        {
            haspunct = true;
        }
    }

    if (hasupper && haslower && hasdigit && haspunct)
    {
        return true;
    }

    return false;
}
ifsvaxew

ifsvaxew1#

1.布尔或boolean是一种基本的数据类型。只有两个可能的值,true或false,可以表示为1或0。布尔用于表示某个东西是否为真,yer或no,在这种情况下,要么是一个有效的密码,要么不是。谷歌更多关于这一点。

  1. end?or else?if语句可以选择使用elseif链接在一起,其中 predicate 通过几个条件语句进行检查。例如,假设 predicate 是age。如果您的"age〈21 no alcholo",else yes alcohol "在这种情况下,您只需要2。如果您要检查某个学生是否有资格获得奖励,并且必须检查几个条件以查看是否满足每个条件,该怎么办?if语句不需要链接,但如果需要的话,它们也可以链接。它们可以嵌套在其他if、循环等等之中。谷歌一下你不懂的东西,过一段时间就会被官方文档所吸引。
    1.不,Bool是返回类型。函数返回true或false。参数接受一个字符串。所以它接受一组字符,在本例中是一个密码。
    你可以调用这个函数或者调用main中的函数或任何其他用户定义的函数,方法是调用函数valid并传入一个字符串参数。参数必须是字符串而不是布尔值。函数根据您在if语句中指定的条件要求来确定密码是否确实是有效的密码。我很惊讶您写了这个,但不理解它,但不放弃。你可以随意问更多的问题,下次你提到的台词也要更具体一些!
    你在看道格提供的cs50中的短裤吗?它们在帮助进一步解释材料方面非常有用。
    同样,这里有很多行话,但谷歌的话和概念,你不明白。
    祝你好运!
c8ib6hqw

c8ib6hqw2#

1.布尔......我还在纠结呢。为什么不把真的部分放进去呢?布尔就一定是真的吗?
我假设您实际上是在问为什么不必像if(hasupper && haslower)那样执行== true,这实际上与bool类型无关,而是与if和C中类似的选择语句有关。* 任何 * 传递给这些语句的普通变量或指针类型都会被求值为"if non-zero then true,类似地,像==这样的逻辑运算符返回10。这可以追溯到C甚至没有bool类型之前的时间。
然而,以这种方式只使用bool类型的变量被认为是好的风格。if(mybool)是可以的一些编码标准不赞成像if(mypointer)这样的代码,而是鼓励显式if(mypointer != NULL)
还要注意的是,C中的bool类型具有将任何非零整数值转换为true/false的内置功能,因此bool b=123;会导致true(反过来等于1)。
1.经过一番研究,我现在明白了if子句中的最后一个语句不必是else,因为它不能被指定。但是为什么一个if和三个else if可以工作呢?我最初预计它会是一种嵌套的if语句。
elseif的末尾总是可选的。事实上,在C语言中并没有什么叫做else if的东西,这只是一个非常常见的编码风格约定。每个else总是属于前一个if,所以你的代码实际上使用的是else。它可以被100%等效地重写(但更难读)如下:

// harder to read
if (isupper(password[i]))
{
  hasupper = true;
}
else 
  if (islower(password[i]))
  {
    haslower = true;
  }
  else 
    if (isdigit(password[i]))
    {
      hasdigit = true;
    }
    else 
      if (ispunct(password[i]))
      {
        haspunct = true;
      }

这样做是因为每个ifelse都可以接受下一行的一条语句,而不需要花括号,你也可以显式地输入花括号,但这样可读性更差:

// even harder to read
if (isupper(password[i]))
{
  hasupper = true;
}
else 
{
  if (islower(password[i]))
  {
    haslower = true;
  }
  else 
  {
    if (isdigit(password[i]))
    {
      hasdigit = true;
    }
    else 
    {
      if (ispunct(password[i]))
      {
        haspunct = true;
      }
    }
  }
}

else if编码风格约定减少了缩进和大括号的数量,因此它被广泛用作"事实上的"标准编码风格(事实上,这是所有C程序员都同意的极少数与风格相关的问题之一)。

  1. bool valid(字符串密码)函数是否接受false和true作为输入,因为它被定义为使用bool?
    函数名前面的类型声明了函数的返回类型(输出)。函数的输入由参数指定,在本例中为string password。这是CS50编写char* password的错误方法。一个更好的方法是使用 * const correction *-因为这个函数不应该修改字符串,所以应该声明为bool valid (const char* password);
wlsrxk51

wlsrxk513#

您还可以通过将比较结果直接赋给变量来完全消除if/else的使用,因为比较操作的结果是一个可以赋值的值,就像x + 5可以赋值一样:

bool valid(const char *password)
{
    bool haslower = false;
    bool hasupper = false;
    bool hasdigit = false;
    bool haspunct = false;

    for (int i = 0; password[i] != '\0'; i++)
    {
        hasupper = hasupper || isupper(password[i]);
        haslower = haslower || islower(password[i]);
        hasdigit = hasdigit || isdigit(password[i]);
        haspunct = haspunct || ispunct(password[i]);
    }

    return(hasupper && haslower && hasdigit && haspunct);
}

代码必须比has* = is*(password[i]);更复杂,因为一旦has*变量中的任何一个是true,它就必须保持truepassword的每个charhas*变量的每个新值都必须与该has*变量的先前值进行or运算。
由于||运算符是短路的,因此一旦has*变量中的任何一个为真,就不需要也不会再调用对应的is*()函数。
C没有任何||=复合运算符,因此不能编写

hasupper ||= isupper(password[i]);

不过,您 * 可以 * 使用按位或复合运算符|=

hasupper |= isupper(password[i]);

尽管这并没有短路,而且对bool值使用按位运算符可能不是一种好的风格,这种风格不好的一个原因是,在|||=运算符与&&&=运算符之间,在对称性上有一个关键的区别。
如上所述,|||=运算符都将“进位”true值,因为非零值或位的任何设置将总是进位到true最终结果:0 || 10 | 2都是true。但如果要检查 * 所有 * 字符是否都是大写,例如,&=而不是等价于&&:一米三〇三是一米三〇三,但一米三〇三是一米三〇三.

相关问题