为什么 for/while/do-while 在执行相同的任务时被放置在 c/c++ 中
Why for/while/do-while were placed in c/c++ when they perform same task
为什么在 c/c++ 中需要 3 个不同的循环:"while"、"do-while"和"for",尤其是当它们中的每一个都让你有能力做其他 2 个几乎可以做的任何事情时?其他语言缺少其中一种。
它只是为了易于使用还是为了使代码在案例中看起来更好,或者是否有任何特殊目的,其中任何一个专门服务于其他两个无法轻松完成?如果是,那么请提及。
附言:一般来说,一种语言是否支持许多迭代语法只是为了增强可读性?
它不仅仅是可读性,它也是密切相关但独特的可维护性、简洁性和范围(尤其是文件、锁、智能指针等(和性能......
如果我们考虑for
循环,它:
-
允许在
for
循环自己的范围内定义一些变量并初始化, -
每次进入循环之前测试控制表达式(包括第一次(,以及
有一个语句,该 语句在每次迭代之后和重新测试控制表达式之前执行,假设没有
break
/return
/throw
/exit
/失败assert
等,也不管是执行了主体中的最后一个语句还是执行了continue
语句; 该语句传统上保留用于逻辑"推进"某些状态"通过"处理, 这样,控件表达式的下一个测试是有意义的。
这是非常灵活的,并且考虑到更本地化的作用域的实用性来确保更早的析构函数调用,可以帮助确保锁、文件、内存等尽早释放 - 在离开循环时隐式释放。
如果我们考虑一个while
循环...
while (expression to test)
...
。它在功能上完全等同于...
for ( ; expression to test; )
...
。但是,这也向程序员暗示,没有控制变量应该是循环局部的,并且控件"要测试的表达式"本质上"进展"通过有限次数的迭代,如果测试表达式是硬编码的,则永远循环true
,或者更复杂的"进度"管理必须由while
控制的语句自己控制和协调。
换句话说,程序员看到while
会自动意识到他们需要更仔细地研究控件表达式,然后可能更广泛地查看周围的范围/函数和包含的语句,以了解循环行为。
那么,do
- while
?好吧,编写这样的代码是痛苦的,效率较低:
bool first_time = true;
while (first_time || ...)
{
first_time = false;
...
}
// oops... first_time still hanging around...
。相比...
do
...
while (...);
例子
而循环:
int i = 23;
while (i < 99)
{
if (f(i)) { ++i; continue; }
if (g(i)) break;
++i;
}
// oops... i is hanging around
对于循环:
for (int i = 23; i < 99; ++i)
{
if (f(i)) continue;
if (g(i)) break;
}
好吧,C++有goto
,你可以用它来实现所有三个循环,但这并不意味着应该删除它们。实际上,它只是增加了可读性。当然,您可以自己实现其中任何一个。
有些循环用for
最容易写,有些用while
最容易写,有些用do
-while
最容易写。 因此,该语言提供了所有三个。
出于同样的原因,我们有像+=
运算符这样的东西; +=
不会做任何你不能用普通+
做的事情,但使用它(在适当的情况下(可以使你的代码更具可读性。
通常,当呈现实现类似目的的不同语言结构时,您应该选择更清楚地传达您正在编写的代码的预期目的的语言结构。C 提供了四种不同的结构化迭代设备供使用,这是一个好处,因为它提供了很高的机会,您可以清楚地传达预期目的。
for (
初始化;
条件;
迭代步骤)
体这种形式传达了循环将如何开始,它将如何为下一次迭代调整内容,以及保持循环中的条件是什么。这种结构自然适合在N
时候做某事。
for (int i = 0; i < N; ++i) {
/* ... */
}
身体)
while (
状况
此表单仅传达您希望在条件保持为真时继续执行循环。对于迭代步骤隐含到循环工作方式的循环,它可以是传达代码意图的更自然的方式:
while (std::cin >> word) {
/* ... */
}
do
身体while (
状况)
此窗体表示循环体将至少执行一次,然后在条件保持为真时继续执行。这对于您已经确定需要执行正文的情况很有用,因此您可以避免多余的测试。
if (count > 0) {
do {
/* ... */
} while (--count > 0);
} else {
puts("nothing to do");
}
第四个迭代设备是...递归!
递归是另一种形式的迭代,它表示相同的函数可用于处理原始问题的较小部分。这是一种自然的方式来表达对问题的分而治之策略(如二分搜索或排序(,或者处理自我引用的数据结构(如列表或树(。
struct node {
struct node *next;
char name[32];
char info[256];
};
struct node * find (struct node *list, char *name)
{
if (list == NULL || strcmp(name, list->name) == 0) {
return list;
}
return find(list->next, name);
}
- 有没有任务栏API可以立即应用注册表更改
- 如何创建线程序列以按照启动顺序执行任务?
- C++一个线程如何正确通信其任务已完成?
- 在线程之间拆分任务总是值得的吗?
- 递归求和任务的错误答案
- "main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
- C++ 任务流库入门
- Pisarze - 来自波兰奥林匹克信息学的数据分析任务
- 在程序运行时监视 VxWorks 中的任务 CPU 利用率
- 编写一个读取五个整数并执行一些任务的C++程序
- 任务内部的 OpenMP 任务循环
- 不知道如何在家庭作业任务中实现一件事
- 如何安全地停止 IOCP WSARecv() 任务,并释放 WSAOVERLAPED 结构?
- 为什么我的 FreeRTOS 任务看不到类成员?
- 当前步骤:构建任务.json 文件
- 命令模式 - 使用"weight"执行任务的命令
- 无法删除EXE崩溃后,即使进程未显示在任务管理器中
- 需要帮助来理解我的任务的 QRegularExpression
- xSemaphoreTake 在调用 xSemaphoreGive 后不会恢复任务
- 如果互斥锁被锁定,则安全地跳过任务