visual C++|循环效率

visual C++ | For Loop Efficiency?

本文关键字:效率 循环 C++ visual      更新时间:2023-10-16

我一直在学习C++,显然在循环之前,我一直在阅读的教学手册为我提供了这样的场景:

展开本章前面的密码检查程序,使其采用多个用户名,每个用户名都有自己的密码,并确保正确的用户名用于正确的密码。提供在第一次登录尝试失败时再次提示用户的功能。想想对于很多用户名和密码来说,这样做是多么容易(或困难)。

在没有任何循环知识的情况下,循环会重复任何错误的值,提示用户输入正确的信息,直到他们输入为止,我试图完成任务,最终得到了以下代码:

#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;
}
}
}
}   
}

很抱歉代码可能有多乱,但我想知道是否有任何方法可以在提供相同结果的同时提高空间效率。

优化--第一遍

创建标识符或命名常量

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

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.write替换另一个std::cout <<,就像上面的代码一样。

优化--第四遍

不要使用std::cout

std::cout可能会携带额外的行李。您可以使用其他选择来节省一些代码空间。

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

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

正如Jesper所评论的,是的,有很多方法。我鼓励你先了解循环,然后再重新审视它。

循环只允许你再次做同样的事情,从根本没有时间(循环不运行)到永远(无限循环)。

每当您发现自己再次键入相同的内容或复制粘贴时,使用循环(或将代码移动到函数、类等中)将是更好的选择的可能性非常高。

此外,您的代码似乎没有按预期运行。如果您最初键入的输入不正确,correctPassOne为false,您将进入第一个else并提示"重新输入您的第一个代码:"。

  1. 第一组if-else语句永远不会通过。它检查inputCodeTwo是否正确,但此时用户从未给出

您似乎认识到了这一点,并将else语句放在后面,然后提示输入CodeTwo。

  1. 现在的问题是,如果inputCodeOne第二次不正确,那么inputCodeTwo无关紧要。因此,您将提示输入CodeTwo,但没有成功的机会。

  2. 在第103、104行,键入

correctPassTwo = false; if(!correctPassTwo) { } 如果曾经达到104,那么也将达到103,因此不需要赋值false和条件。

  1. 如果inputCodeOne两次不正确,则不需要此代码块。您现在提示用户两次给出第二个代码,但没有成功的机会。因为inputCodeOne仍然是错误的

有了循环,你可以做这样的事情:

要求输入CodeOne的次数可以选择,直到它正确或达到极限。

如果达到限制,打印"ACCESS DENIED"并结束程序。如果密码正确,您可以进入inputCodeTwo。

同样的事情,要求输入CodeTwo的次数可以是你想要的次数。如果这两个代码匹配,请打印您的密码正确消息。否则,在尝试了一定次数后,您可以终止程序。

您可以使用25%的初始代码来完成此操作。