如何验证密码在C中至少有一个大写,小写和数字?

时间:2013-10-29 14:57:46

标签: c passwords uppercase lowercase

我该怎么做才能让它保持循环,直到它至少有一个大写,小写和数字?

我卡住了,真的卡住了......

char password[100][15];
i=1;
     printf("Password [3..10]: ");
        gets(password[i]);
        while (strlen(password[i])>10 || strlen(password[i])<3 || ) {   
        do{
        printf("  Password must contain at least 1 uppercase, 1 lowercase, and 1 number\nPassword [3..10]: ");
        gets(password[i]);
        } while (strlen(password[i])>10 || strlen(password[i])<3 );

5 个答案:

答案 0 :(得分:10)

这应该有效:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int is_legal(char *p) {
  int number = 0, lower = 0, upper = 0, length = 0;
  for( ; *p; p++) {
      number += isdigit(*p);   
      lower  += islower(*p);     
      upper  += isupper(*p);
      length++;
  }
  return number > 0 && lower > 0 && upper > 0  && length > 3 && length < 10;
}

char *my_gets(char *buf, int bufsize, FILE *file) {
    if(fgets(buf, bufsize, file) == 0) {
        return 0;
    }
    int n = strlen(buf);
    if(buf[n-1] == '\n') buf[n-1] = 0;
    return buf;
}

int get_password(char *buf, int bufsize, FILE *file) {
    printf("Password [3..10]: ");
    if(my_gets(buf, bufsize, file) == 0) {
        return -1;
    }
    while(is_legal(buf) == 0) {
       printf("  Password must contain at least 1 uppercase, 1 lowercase, and 1    umber\nPassword [3..10]: ");
       if(my_gets(buf, bufsize, file) == 0) {
           return -1;
       }
    }
    return 0;
}

int main(void) {
    char password[100][15];
    int i = 0;
    if(get_password(password[i], sizeof(password[i]), stdin) != 0) {
        fprintf(stderr, "Error getting password\n");
        exit(1);
   }
   return 0;
}

答案 1 :(得分:2)

使用此正则表达式:

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$

它表示您必须至少有一个小写字符,一个大写字符和至少一个数字PLUS,它的输入次数少于ctype方法。

示例:

#include <regex.h>

int main (int argc, char *argv[])
{
    regex_t regex;
    int regexResult = regcomp(&regex, "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$", 0);
    regexResult = regexec(&regex, passwordVariableHere, 0, NULL, 0);

    if (!regex)
    {
        // Match
    }
}

答案 2 :(得分:0)

查看ctype.h标题。检查密码的每个字符,直到满足所有条件(上限,下限,数字)。如果您到达密码字符串的末尾并且任何条件都不满意,则密码错误。

答案 3 :(得分:0)

也许这是检查ASCII表中字符位置的简单方法。对于uppsercase字符,您可以将所有字符检查为65到90之间的数字,对于小写字符,可以检查相同的数字。

对于数字,您可以使用标准c库中的atoi()函数。

或者另一种可能性是使用ctype.h中的函数:islower(),isupper()或isdigit()。

答案 4 :(得分:0)

为什么你使用一组15个字符长的密码我不能很好,但我想你的标准只是其中一个密码,而不是其他密码:你想要检查密码有要求被视为&#34;好&#34;密码;这是我的理解。然后...

函数gets相当不安全。避免使用它。

想法是要求输入密码,检查密码并在不符合条件的情况下循环。当然,没有一种方法可以做到。

// include files for I/O funcs
#include <stdio.h>

for(;;)
{
   printf("insert pwd: ");
   gets(buffer); // argh I've said: don't use this
   if ( !pass_criteria(buffer) ) {
       printf("criteria are ....\n");
   } else break;
}

然后pass_criteria可能类似于

// include files for strlen and is* funcs
#include <ctype.h>
#include <string.h>

int pass_criteria(const char *buf)
{
    int upcount, lowcount, numcount;

    if (strlen(buf) < minimum_pass_len ||
        strlen(buf) > max_pass_len) return 0; // 0 being false

    for (int i = 0; i < strlen(buf); ++i) {
       if (isdigit(buf[i]) numcount++;
       if (isupper(buf[i]) upcount++;
       if (islower(buf[i]) lowcount++;
    }
    return numcount > 0 && upcount > 0 && lowcount > 0;
}

很容易改变标准,例如如果你想要至少2个数字(数字),请放numcount > 1等等。

而不是获取

获取缓冲区溢出是危险的。尝试使用例如像这样的fgets:

   fgets(buffer, buffer_size, stdin);

其中buffer_size是缓冲区的大小(在您的情况下为15,但请避免使用文字常量;请使用正确的#define或使用sizeof,例如sizeof (password[0])另请注意,fgets不会丢弃最终换行符。