首页 > 解决方案 > 有人可以帮我微调这段代码中的 **else if** 语句吗?

问题描述

我正在尝试编写一个代码来检查用户输入的密码是否符合密码格式,例如“ L$$222ee”(第一个大写字母,后跟两个特殊字符,后跟三位数字,最后是两个小写字母)。我的代码运行良好;我只想完善else if语句。这是代码:

#include<stdio.h>
#include<string.h>
#include<ctype.h>
//format required: L$$222ee
int main(){
    char pass[8];
    printf("Enter password:\n");
    gets(pass);
    if(strlen(pass)<8){
        printf("Password is too short...!!!\n");
    }
    else if(isupper(pass[0]) && ((!isalpha(pass[1]) && !isalpha(pass[2])) && !isdigit(pass[1]) && !isdigit(pass[2])) 
    && (isdigit(pass[3]) && isdigit(pass[4]) && isdigit(pass[5])) && (isalpha(pass[6]) 
    && isalpha(pass[7]))){
        printf("Password is compliant");
    }
    else{
        printf("Error: password is not compliant with the format!!!\n");
    }
    return 0;
}

标签: arrayscif-statementconditional-statements

解决方案


由于所有这些 ctype.h 函数都具有相同的格式int func (int),您可以利用它来创建对应于所有需要完成的检查的查找表。查找表的优点是它比相当不可读的&&.

首先创建一个与 ctype 函数相同的函数 typedef:typedef int ctype_func_t (int);

然后制作一个在查找表中使用的结构。存储字符串索引、结果的真假条件以及函数本身:

typedef struct
{
  size_t         index;
  bool           cond;
  ctype_func_t*  check_func;
} check_t;

然后可以创建一个查找表:

const check_t fmt_check [] =
{
  {0, true,  isupper },
  {1, false, isalpha },
  {2, false, isalpha },
  {1, false, isdigit },
  {2, false, isdigit }, 
  {3, true,  isdigit },
  {4, true,  isdigit },
  {5, true,  isdigit },
  {6, true,  isalpha },
  {7, true,  isalpha },
};

顺序不重要,随意添加或删除格式要求。完整的函数如下所示:

int ispwcorrect (const char pw[8])
{
  typedef int ctype_func_t (int);
  typedef struct
  {
    size_t         index;
    bool           cond;
    ctype_func_t*  check_func;
  } check_t;

  const check_t fmt_check [] =
  {
    {0, true,  isupper },
    {1, false, isalpha },
    {2, false, isalpha },
    {1, false, isdigit },
    {2, false, isdigit }, 
    {3, true,  isdigit },
    {4, true,  isdigit },
    {5, true,  isdigit },
    {6, true,  isalpha },
    {7, true,  isalpha },
  };
  
  for(size_t i=0; i<sizeof fmt_check/sizeof *fmt_check; i++)
  {
    unsigned char ch = pw[ fmt_check[i].index ];
    
    if((bool)fmt_check[i].check_func(ch) != fmt_check[i].cond)
    {
      return false;
    }
  }  
  return true;
}

这应该是不言自明的,它通过循环中的函数指针调用 ctype 函数,并以特定的字符串索引字符作为参数。然后检查真/假条件。一旦出现不匹配,检查就会停止。

调用每个 ctype 函数后的强制转换bool是必要的,因为它们返回零或非负数int。因此,将 abool与这样的非零进行比较是int行不通的,因为 == 会将bool参数提升为 a int

这应该大大优于正则表达式,但会比原始 if-else 稍慢。


与您的问题无关,您在这里也有一个严重的错误:char pass[8];. 空终止符没有空间,所以你不能存储"L$$222ee"在里面pass


推荐阅读