试图制作一个程序来检查密码是不是包含大写字母和 c 中的数字

Posted

技术标签:

【中文标题】试图制作一个程序来检查密码是不是包含大写字母和 c 中的数字【英文标题】:Trying to make a program that checks if a password contains uppercase letter and a number in c试图制作一个程序来检查密码是否包含大写字母和 c 中的数字 【发布时间】:2020-02-14 10:38:42 【问题描述】:

我正在尝试制作一个程序来检查创建的密码是否包含大写字母和数字。如果只编写其中一个而没有另一个循环,则两个 for 循环都可以正常执行(如果我注释掉另一个循环,一个循环可以正常工作),但是如果我将它们一起键入,则只有第二个 for 循环(这与检查是否存在一个数字与否)有效,另一个无效。

因此,使用下面的书面代码,如果我输入的密码既不包含大写字母也不包含数字,我会收到“请确保您的密码包含数字并重试”。只发消息。

注意:

我尝试在第一个循环之后将整数 i 分配为零,并在第二个循环中使用它而不是 x,但我得到了相同的结果。

我正在使用 code::blocks 编译器。

谁能指出我哪里做错了?

抱歉,如果问题不够清楚,这是我在 *** 中的第一个问题,提前致谢。

代码:

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

int main()



    char password[25];

    int i;

    int x;

    printf("Create a strong password (must contain an uppercase letter and a number, and must be at least 8 characters) :\n");
    scanf(" %s", password);



    for (i = 0; i <= 25; i++)
    

        if ( isupper(password[i]) == 1 )
        
            break;
        

        if (i == 25)
        
            printf("\nPlease make sure that your password contains an uppercase letter and try again.\n");
        


    


      for (x = 0; x <= 25; x++)
    

        if (isdigit(password[x]) == 1)
        
            break;
        

        if ( x == 25 )
        
             printf("\nPlease make sure that your password contains a number and try again.\n");
        

    

    return 0;

【问题讨论】:

一个主要问题是循环for (i = 0; i &lt;= 25; i++) 超出范围。它还将忽略字符串的结尾(如果它少于 24 个字符)。 isupper 不会专门返回 1,而是返回一个 非零 值,即 true。所以if(isupper(password[i]) == 1) 应该是if(isupper(password[i])) if (isupper((unsigned char)password[i])) /* ... */; 允许密码具有,例如,'π' 字符 遇到\0(空)字符后也应该停止阅读。 isupper() 当参数是大写字母时返回非零整数 ( x > 0 ),当参数不是大写字母时返回 0。另一种方法是与 ASCII 值进行比较。 if(密码[i] >= 65 && 密码[i] 【参考方案1】:

您的代码中存在许多问题,我将在此处尝试解决。

首先,正如 cmets 中所述,您的两个 for 循环将(很可能)“超出范围”,因为 C 中的数组索引从 zero 开始并以“n - 1"(其中“n”是数组的大小)。

其次,isupper()isdigit() 函数不会(必然)返回“1”以获得“肯定结果”——specification 仅声明它们返回非零。因此,我们可以将返回值测试为“布尔”值(零将等同于“假”,任何非零将等同于“真”)。

最后,无需为整个 password 缓冲区运行 for 循环,您只需运行直到找到终止 nul 字符 - 此时您将知道所需的大写字母或数字不是包括在字符串中。

这是您代码的“工作”版本,在我进行更改的地方添加了 cmets:

int main()

    char password[25];
    int i;
    int x;
    printf("Create a strong password (must contain an uppercase letter and a number, and must be at least 8 characters) :\n");
    scanf(" %s", password);
    for (i = 0; i < 25; i++)  // password[24] is the last possible element - NOT password[25].
        if (isupper(password[i]))  // "isupper()" will return NON-ZERO (but not necessarily 1!)
            break;
        
        else if (password[i] == '\0')  // we've reached the end of the string and not found an uppercase...
            printf("\nPlease make sure that your password contains an uppercase letter and try again.\n");
            break;
        
    
    for (x = 0; x < 25; x++)  // as before, use "x < 25" rather than "x <= 25"
        if (isdigit(password[x]))  // "isdigit()" will return NON-ZERO (but not necessarily 1!)
            break;
        
        else if (password[x] == '\0')  // we've reached the end of the string and not found a digit...
            printf("\nPlease make sure that your password contains a number and try again.\n");
            break;
        
    
    return 0;

【讨论】:

也许scanf(" %24s", password); for (i = 0; password[i]; i++) 可能是更好的条件(你只需要确保scanf() 中的转换之前成功。但这需要更多的更改......【参考方案2】:

这里有一个简单的函数:

int isCapitalAndDigit(const char *pwd, int minsize)

    int isCapitalLetter = 0, isDigit = 0;
    size_t len = 0;

    while(*pwd && (!(isDigit && isCapitalLetter) || len < minsize) )
    
        if(isdigit(*pwd)) isDigit = 1;
          else if(isalpha(*pwd) && !islower(*pwd)) isCapitalLetter = 1;
        pwd++;
        len++;
    
    return isDigit && isCapitalLetter && (len >= minsize);

https://godbolt.org/z/53XrhW

【讨论】:

您的代码会将这些:+=&amp;*£$(以及更多)视为“大写字母”! 是的,但现在你有了isalpha(*pwd) &amp;&amp; !islower(*pwd),这是一种非常奇怪的重新编码isupper(*pwd)的方式——不是吗? 感谢您的帮助,但我仍在学习 C,还没有学习如何创建自己的函数。这是我的错,我在输入问题时忘记提及它。一旦我了解了创建函数,我将确保查看您的答案。再次感谢!【参考方案3】:

这是使用正则表达式的 c++ 代码(需要做一些工作,这在 C 中应该可以做到?)

#include <iostream>
#include <iterator>
#include <string>
#include <regex>

int main()

    std::string s = "tkfgfff3gf";


    std::regex word_regex("(\[[:upper:]])");    


    auto words_begin = 
        std::sregex_iterator(s.begin(), s.end(), word_regex);
    auto words_end = std::sregex_iterator();

    int count =std::distance(words_begin, words_end);

    if(count == 0)
    
        std::cout<<"Please make sure that your password contains an uppercase letter and try again";
    

    std::regex number_regex("(\[0-9])");

    auto number_begin = 
        std::sregex_iterator(s.begin(), s.end(), number_regex);
    auto number_end = std::sregex_iterator();

    count =std::distance(number_begin, number_end);

    if(count == 0)
    
        std::cout<<"Please make sure that your password contains a number and try again";
    

    return 0;


 

【讨论】:

感谢您的帮助,但我仍在学习 C,还没有学习任何有关 C++ 的知识。这是我的错,我忘了在问题中提及。 是的,我没想到你会使用这个,这更多是为了向你展示使用 reg 表达式是多么容易。 感谢您的帮助,无论如何,伙计。非常感谢!

以上是关于试图制作一个程序来检查密码是不是包含大写字母和 c 中的数字的主要内容,如果未能解决你的问题,请参考以下文章

如何制作正则表达式以查看字符串是不是包含某个字母

检查密码,验证,然后再次循环

正则表达式,用于包含至少8个字符和至少1个非字母数字字符的密码

如何在 Flutter 中制作密码验证动画

如何检查输入的小写字母数量的密码?

如何检查是不是有人尝试共享您的程序