使用用户名和密码约束创建登录和注册并将数据保存在文件中。 (C++)

Creating a Login and Register with username and password constraints and saving the data in a file. (C++)

我是编码和学习 C++ 的初学者。我刚刚写了一段代码,要求用户登录、注册或退出。 我认为通过功能来做会更容易。在检查注册用户名和密码的限制(此处称为“Rusr”和“Rpwd”)时,我编写的代码用于检查小写、大写和数字是否不起作用。我也尝试用字符数组来做,但这没有用。真的很感激一些帮助。 下面是我的代码以供进一步参考:

#include <fstream>
#include <iostream>
#include <string.h>

using namespace std;

bool isvalidName(string Rusr)
{
    if(Rusr.length() > 5 && Rusr.length() < 20) // length constraint
        return true;
    else
        cout << "Invalid username" << endl;

    {
        for(int i = 0; i < Rusr.length(); i++) // check if digits are present
        {
            if(isdigit(Rusr[i]) == true) 
            return true;
            if(true)
                break;
            else
                cout << "Invalid username";
        }
    }

    {
        for(int i = 0; i < Rusr.length(); i++) // check for lowercase
        {
            if(islower(Rusr[i])) {
                return true;
            }
            if(true)
                break;
            else
                cout << "Invalid username";
        }
    }

    {
        for(int i = 0; i < Rusr.length(); i++) // check for uppercase
        {
            if(isupper(Rusr[i])) return true;
            if(true)
                break;
            else
                cout << "Invalid username";
        }
    }
}

int isvalidPwd(string Rpwd) {
    {
        if(Rpwd.length() > 8 && Rpwd.length() < 20)
            return true;
        else
            cout << "Invalid password " << endl;
    }

    {
        for(int i = 0; i < Rpwd.length(); i++) {
            if(isdigit(Rpwd[i]) == true) return true;
            if(true)
                break;
            else
                cout << "Invalid password";
        }
    }

    {
        if(!((Rpwd.find("@") == string::npos) ||
             (Rpwd.find("#") == string::npos) ||
             (Rpwd.find("!") == string::npos) ||
             (Rpwd.find("$") == string::npos) ||
             (Rpwd.find("%") == string::npos) ||
             (Rpwd.find("^") == string::npos) ||
             (Rpwd.find("&") == string::npos) ||
             (Rpwd.find("*") == string::npos) ||
             (Rpwd.find("(") == string::npos) ||
             (Rpwd.find(")") == string::npos) ||
             (Rpwd.find("_") == string::npos) ||
             (Rpwd.find("+") == string::npos) ||
             (Rpwd.find("|") == string::npos) ||
             (Rpwd.find(">") == string::npos) ||
             (Rpwd.find("<") == string::npos) ||
             (Rpwd.find("?") == string::npos) ||
             (Rpwd.find("/") == string::npos) ||
             (Rpwd.find("~") == string::npos) ||
             (Rpwd.find(".") == string::npos) ||
             (Rpwd.find(",") == string::npos)))
            return true;

        else
            cout << "should contain special characters" << endl;
    }

    for(int i = 0; i < Rpwd.length(); i++) {
        if(islower(Rpwd[i])) return true;
        if(true)
            break;
        else
            cout << "should contain lower case";
    }

    {
        for(int i = 0; i < Rpwd.length(); i++) {
            if(isupper(Rpwd[i])) return true;
            if(true)
                break;
            else
                cout << "Should contain upper case";
        }
    }
}

int main() {
    string Lusr, Lpwd, Rusr, Rpwd, name, pwd;

    while(1) {
        cout << "___________________________________" << endl;
        cout << "Chose 1 to Register or 2 to Login" << endl;
        cout << "___________________________________" << endl;
        cout << "1.Register" << endl;
        cout << "2.Login" << endl;
        cout << "3.Exit" << endl;
        cout << "___________________________________" << endl;
        int choice;
        cin >> choice;

        if(choice == 1) // register
        {
            ofstream of("register.txt");
            if(!of.is_open()) {
                cout << "file not exist" << endl;
            }

            do {
                cout << "Username should contain capital,small letters and "
                        "numbers. "
                     << endl;
                cout << "______________________________________" << endl;
                cout << "Enter new username:" << endl;
                cin.ignore();
                getline(cin, Rusr);
                isvalidName(Rusr);
            } while(isvalidName(Rusr) == true);

            do {
                cout << "Password should contain capital,small letters,special "
                        "characters and numbers. "
                     << endl;
                cout << "_______________________________________" << endl;
                cout << "Enter new passsword:" << endl;
                getline(cin, Rpwd);

                isvalidPwd(Rpwd);
            } while(isvalidPwd(Rpwd) == true);

            of << Rusr;
            of << '\n';
            of << Rpwd;
            of.close();
        }

        else if(choice == 2) {
            ifstream f("register.txt");
            if(!f.is_open()) {
                cout << "file not open" << endl;
            }
            getline(f, name, '\n');
            getline(f, pwd, '\n');

            f.close();

            cout << "Enter username:" << endl;
            cin.ignore();
            getline(cin, Lusr);
            cout << "Enter passsword:" << endl;
            getline(cin, Lpwd);

            if(Lpwd == pwd && Lusr == name) {
                cout << "Welcome " << Lusr << endl;
                ;
                break;
            }

            cout << "Wrong name and  password" << endl;
        }

        else if(choice == 3) {
            return 1;
        } else {
            cout << "Invalid input!Try again." << endl;
        }
       
    }
    return 0;
}

你的两个函数都未能return你声明的值,它们应该在所有分支中return,所以你的程序有undefined behavior

另外,逻辑有问题。示例:

bool isvalidName(string Rusr) {
    if(Rusr.length() > 5 && Rusr.length() < 20) // length constraint
        return true;
    else
        cout << "Invalid username`enter code here`" << endl;

    // .. the rest ...
}

在这里检查长度是否为 [6, 19] 个字符长 - 并且 return true; - 这就是获得 Rusr 批准所需的全部。如果名称具有批准的长度,None 函数中的其他测试将被执行。

您的代码充满了类似的错误。

        for(int i = 0; i < Rusr.length(); i++) // check if digits are present
        {
            if(isdigit(Rusr[i]) == true) return true;

您遇到的第一个数字是 isvalidName return true - 所以现在您的名称包含一个数字,但长度无效 - 已批准!

以下类似问题。包含小写字母的非法长度、无数字的名称将立即获得批准:

        for(int i = 0; i < Rusr.length(); i++) // check for lowercase
        {
            if(islower(Rusr[i])) {
                return true;

最后,如果名称的长度不合法、没有数字、没有小写字母且包含大写字母,则通过:

        for(int i = 0; i < Rusr.length(); i++) // check for uppercase
        {
            if(isupper(Rusr[i])) return true;

如果上述 none 适用 - 你没有 return 任何东西(导致 未定义的行为 )。

您的第二个函数遵循此模式。

根据您的代码,您的某些逻辑是错误的。当你这样说时

if(Rusr.length() > 5 && Rusr.length() < 20) // length constraint
        return true;
    else
        cout << "Invalid username`enter code here`" << endl;

任何介于 5 到 20 个字符之间的字符串都将被接受为有效的用户名。要解决此问题,您需要完成所有要求,然后 return 为真。如果任何要求失败,return false。这使得用户名有效的唯一方法是它是否已经通过所有要求。

    bool isvalidName(string Rusr)
    {
        if(Rusr.length() < 5 || Rusr.length() > 20) // length constraint
        {
            std::cout << "invalid username length" << std::endl;
            return false;
        }

        for(int i = 0; i < Rusr.length(); i++) // check if digits are present
        {
            if(isdigit(Rusr[i]))  // if a digit is present, continue
            {
                break;
            }

            if(i == Rusr.length() - 1) // No digits were found
            {
                return false;
            }
        }

        for(int i = 0; i < Rusr.length(); i++) // check for lowercase
        {
            if(islower(Rusr[i])) {
                break;
            }

            if(i == Rusr.length() - 1) // No lowercase letters were found
            {
                cout << "Invalid username";
                return false;
            }
                
        }
 
        for(int i = 0; i < Rusr.length(); i++) // check for uppercase
        {
            if(isupper(Rusr[i]))
            {
                break;
            }

            if(i == Rusr.length() - 1) // No uppercase letters were found
            {
                cout << "Invalid username";
                return false;
            }
        }

        return true;
    }

这样,您 return true 的唯一方法就是克服所有限制。

对于密码,您可能希望遵循此模型并根据这些限制进行调整。

其他一些需要注意的事项是您提供的额外牙套。最佳做法是不要将作用域更改得比您需要的更远,因此几乎在所有情况下都应避免使用大括号。