首页 > 解决方案 > C++ | For Loop Efficiency?

问题描述

I've been learning C++ and obviously before hitting loops, the tuition manual I've been reading provided me with this scenario:

Expand the password checking program from earlier in this chapter and make it take multiple usernames, each with their own password, and ensure that the right username is used for the right password. Provide the ability to prompt users again if the first login attempt failed. Think about how easy (or hard) it is to do this for a lot of usernames and passwords.

Without any knowledge yet of loops and whatnot that'll repeat any incorrect values prompting the user to input the correct information until they do so, I've attempted to complete the task and ended up with this code here:

#include < iostream >

using namespace std;

int main()
{

    int inputCodeOne, inputCodeTwo = 0;

    bool correctPassOne=false,correctPassTwo;

    cout << "Please enter your first Code: ";
    cin >> inputCodeOne;

    if(inputCodeOne==1111||inputCodeOne==2222||inputCodeOne==3333)
    {
        correctPassOne = true;
    }
    if (correctPassOne)
    {
        cout << "Please enter your second Code: ";
        cin >> inputCodeTwo;

        if (inputCodeOne == 1111 && inputCodeTwo == 100)
        {
            cout << "Password Correct! Welcome back David";
            return 0;
        }
        else if (inputCodeOne == 2222 && inputCodeTwo == 200)
        {
            cout << "Password Correct! Welcome back Darren";
            return 0;
        }
        else if (inputCodeOne == 3333 && inputCodeTwo == 300)
        {
            cout << "Password Correct! Welcome back Jake";
            return 0;
        }
        correctPassTwo = false;
        if(!correctPassTwo)
        {
            cout << "Please re-enter your second Code: ";
            cin >> inputCodeTwo;
            if (inputCodeOne == 1111 && inputCodeTwo == 100)
            {
                cout << "Password Correct! Welcome back David";
                return 0;
            }
            else if (inputCodeOne == 2222 && inputCodeTwo == 200)
            {
                cout << "Password Correct! Welcome back Darren";
                return 0;
            }
            else if (inputCodeOne == 3333 && inputCodeTwo == 300)
            {
                cout << "Password Correct! Welcome back Jake";
                return 0;
            }
            cout << "ACCESS DENIED";
            return 0;
        }
    }
    else
    {
        cout << "Please re-enter your first Code: ";
        cin >> inputCodeOne;

        if (inputCodeOne == 1111 && inputCodeTwo == 100)
        {
            cout << "Password Correct! Welcome back David";
            return 0;
        }
        else if (inputCodeOne == 2222 && inputCodeTwo == 200)
        {
            cout << "Password Correct! Welcome back Darren";
            return 0;
        }
        else if (inputCodeOne == 3333 && inputCodeTwo == 300)
        {
            cout << "Password Correct! Welcome back Jake";
            return 0;
        }
        else
        {
            cout << "Please enter your second Code: ";
            cin >> inputCodeTwo;

            if (inputCodeOne == 1111 && inputCodeTwo == 100)
            {
                cout << "Password Correct! Welcome back David";
                return 0;
            }
            else if (inputCodeOne == 2222 && inputCodeTwo == 200)
            {
                cout << "Password Correct! Welcome back Darren";
                return 0;
            }
            else if (inputCodeOne == 3333 && inputCodeTwo == 300)
            {
                cout << "Password Correct! Welcome back Jake";
                return 0;
            }
            correctPassTwo = false;
            if (!correctPassTwo)
            {
                cout << "Please re-enter your second Code: ";
                cin >> inputCodeTwo;
                if (inputCodeOne == 1111 && inputCodeTwo == 100)
                {
                    cout << "Password Correct! Welcome back David";
                    return 0;
                }
                else if (inputCodeOne == 2222 && inputCodeTwo == 200)
                {
                    cout << "Password Correct! Welcome back Darren";
                    return 0;
                }
                else if (inputCodeOne == 3333 && inputCodeTwo == 300)
                {
                    cout << "Password Correct! Welcome back Jake";
                    return 0;
                }
                else
                {
                    cout << "ACCESS DENIED";
                    return 0;
                }
            }
        }
    }   
}

Apologies for how messy the code probably is, but I wanted to know if there were any ways to make this more space efficient whilst providing the same result.

标签: c++visual-c++

解决方案


优化——第一次通过

创建标识符或命名常量

这使您可以避免重复和拼写错误。还允许编译器进行更多优化。

const int PASSWORD1a = 1111;
const int PASSWORD2a = 2222;
const int PASSWORD3a = 3333;
const int PASSWORD1b = 100;
const int PASSWORD2b = 200;
const int PASSWORD3b = 300;

将密码组合在一起。

将密码配对在一起将使该过程更加通用。
您可以使用现有的std::pair或创建自己的:

struct Password_Entry
{
    int first;
    int second;
};

接下来,创建一个有效密码对表:

const Password_Entry  valid_passwords[] =
{
    {PASSWORD1a, PASSWORD1b},
    {PASSWORD2a, PASSWORD2b},
    {PASSWORD3a, PASSWORD3b},
};
const size_t quantity_valid_passwords =
    sizeof(valid_passwords) / sizeof(valid_passwords[0]);

在表格中搜索有效密码

int inputCode1;
int inputCode2;
bool passwords_are_valid = false;
std::cout << "Enter first password: ";
std::cin >> inputCode1;
for (unsigned int index = 0; index < quantity_valid_passwords; ++index)
{
    if (inputCode1 == valid_passwords[i].first)
    {
        std::cout << "Enter second password: ";
        std::cin >> inputCode2;
        if (inputCode2 == valid_passwords[i].second)
        {
            passwords_are_valid = true;
        }
    }
}

概括

上面的代码是表格驱动的。搜索表的代码是通用的,取决于表中的数据。无需修改剩余代码即可更改条目数量。

在一个结构中将第一个密码与第二个密码配对,可以实现更优化的数据存储和代码空间。

使用命名常量允许只指定一次值。如果您需要更改该值,您只需进行一次更改。在进行更改时,您不会冒跳过一个或多个的风险。

优化——第二遍

人名

可以通过在结构中添加另一个字段或成员来优化人名的打印:

struct Password_Entry
{
    int first;
    int second;
    char * name;
};

该表现在变为:

const Password_Entry  valid_passwords[] =
{
    {PASSWORD1a, PASSWORD1b, "David"},
    {PASSWORD2a, PASSWORD2b, "Darren"},
    {PASSWORD3a, PASSWORD3b, "Jake"},
};
const size_t quantity_valid_passwords =
    sizeof(valid_passwords) / sizeof(valid_passwords[0]);

搜索/验证代码更改为:

    std::cout << "Enter second password: ";
    std::cin >> inputCode2;
    if (inputCode2 == valid_passwords[i].second)
    {
        passwords_are_valid = true;
        std::cout << "Password Correct! Welcome Back "
                  << valid_passwords[i].name
                  << "!\n";
    }

优化——第三遍

合并重复文本

有重复的文字,意味着可以挤出更多的空间:

char const * const text_enter[] = "Enter ";
char const * const text_password[] = "password";

代码可以改成:

std::cout << text_enter << "first " << text_password << ": ";
//...
std::cout << text_enter << "second " << text_password << ": ";
//...
std::cout << "Correct " << text_password << "! Welcome Back "
          << valid_passwords[index].name << "\n";

块写入

可以通过块写入而不是使用格式化写入来压缩一些代码空间。所有的输出都是文本,所以不需要格式化;文本可以直接输出。您必须比较此优化之前和之后的汇编语言列表以测量空间差异。

这种技术也可能显示出一些速度改进。

使用以下内容:

std::cout.write(text_enter, sizeof(text_enter) - 1U); // -1 so the terminating nul is not output.
std::cout.write(text_password, sizeof(text_password) - 1U);
std::cout.write(": ", 2);

同样,将另一个替换为std::cout <<上面std::cout.write的代码。

优化——第四遍

不要使用std::cout.

std::cout可以随身携带额外的行李。您可以使用替代方案来节省一些代码空间。

替换std::coutfwrite(stdout, /*...*/)。该fwrite函数包含写入给定流的最少代码。没有额外的代码来格式化或转换。简单明了,将数据写入流。
一些编译器可能很懒惰并插入“一刀切”的库,而不仅仅是fwrite.

您可以通过直接访问操作系统的低级驱动程序来挤出更多的代码空间。您的程序足够小,不需要缓冲以及来自 C++ 和 OS 流的其他一些开销。在这一点上,节省的空间与实现这一目标所花费的开发时间相比可以忽略不计。取决于你的平台。在内存受限的系统上,这可能是值得的尝试。在大多数桌面系统上,这不值得您花时间开发,因为它们比受限系统拥有更多的内存。


推荐阅读