В C есть три петли: for
, while
и do-while
. Какая разница между ними?
Например, кажется, что почти все операторы while
могут быть заменены операторами for
, правильно? Тогда какое преимущество имеет использование while
?
В C есть три петли: for
, while
и do-while
. Какая разница между ними?
Например, кажется, что почти все операторы while
могут быть заменены операторами for
, правильно? Тогда какое преимущество имеет использование while
?
A while цикл всегда будет сначала оценивать условие.
while (condition) {
//gets executed after condition is checked
}
A do/while цикл всегда будет выполняться сначала код в блоке do{}
а затем оцените условие.
do {
//gets executed at least once
} while (condition);
A для цикла позволяет вам инициировать переменную счетчика, условие проверки и способ увеличить ваш счетчик в одной строке.
for (int x = 0; x < 100; x++) {
//executed until x >= 100
}
В конце концов, все они все еще петли, но они предлагают некоторую гибкость в отношении того, как они выполняются.
Вот отличное объяснение причин использования каждого типа цикла, который может помочь прояснить ситуацию. Спасибо clyfe
Основное различие между
for
's иwhile
- вопрос прагматика: мы обычно используемfor
, когда существует известное количество итераций, и используйте конструкцииwhile
, когда количество итераций, неизвестных в авансовый.while
vsdo ... while
проблема также связана с прагматикой, второй выполняет инструкции один раз в начале, а затем ведет себя как и просто.
Для петель особенно приятно, потому что они кратки. Для этого для цикла
for (int x = 0; x < 100; x++) {
//executed until x >= 100
}
который должен быть записан как цикл while, вам нужно будет сделать следующее.
int count = 0;
while (count < 100) {
//do stuff
count++;
}
В этом случае есть еще что-то, что можно было бы не отставать, и count++;
может потеряться в логике. Это может привести к неприятностям в зависимости от того, где count
получает прирост, и следует ли его увеличивать до или после логики цикла. С помощью цикла for
ваша счетная переменная всегда увеличивается до следующей итерации цикла, что добавляет некоторую однородность в ваш код.
Для полноты, вероятно, имеет смысл говорить о инструкциях break
и continue
, которые пригождаются при обработке цикла.
break мгновенно завершает текущий цикл и больше не будет выполняться итераций.
//will only run "do stuff" twice
for (int x = 0; x < 100; x++) {
if (x == 2) {
break;
}
//do stuff
}
continue завершает текущую итерацию и переходит к следующей.
//will run "do stuff" until x >= 100 except for when x = 2
for (int x = 0; x < 100; x++) {
if (x == 2) {
continue;
}
//do stuff
}
Обратите внимание, что в цикле for 'continue' оценивает выражение 'part3' 'for (part1; part2; part3)'; напротив, в цикле while он просто перескакивает, чтобы переоценить условие цикла.
Если есть серьезная обеспокоенность в отношении скорости и производительности, наилучшим подходом является проверка кода, созданного компилятором на уровне сборки.
Например, следующий код показывает, что "делать-пока" немного быстрее. Это потому, что команда "jmp" не используется циклом "do-while".
Кстати, в этом конкретном примере наихудший случай задается циклом "для".:))
int main(int argc, char* argv[])
{
int i;
char x[100];
// "FOR" LOOP:
for (i=0; i<100; i++ )
{
x[i] = 0;
}
// "WHILE" LOOP:
i = 0;
while (i<100 )
{
x[i++] = 0;
}
// "DO-WHILE" LOOP:
i = 0;
do
{
x[i++] = 0;
}
while (i<100);
return 0;
}
// "FOR" LOOP:
010013C8 mov dword ptr [ebp-0Ch],0
010013CF jmp wmain+3Ah (10013DAh)
for (i=0; i<100; i++ )
{
x[i] = 0;
010013D1 mov eax,dword ptr [ebp-0Ch] <<< UPDATE i
010013D4 add eax,1
010013D7 mov dword ptr [ebp-0Ch],eax
010013DA cmp dword ptr [ebp-0Ch],64h <<< TEST
010013DE jge wmain+4Ah (10013EAh) <<< COND JUMP
010013E0 mov eax,dword ptr [ebp-0Ch] <<< DO THE JOB..
010013E3 mov byte ptr [ebp+eax-78h],0
010013E8 jmp wmain+31h (10013D1h) <<< UNCOND JUMP
}
// "WHILE" LOOP:
i = 0;
010013EA mov dword ptr [ebp-0Ch],0
while (i<100 )
{
x[i++] = 0;
010013F1 cmp dword ptr [ebp-0Ch],64h <<< TEST
010013F5 jge wmain+6Ah (100140Ah) <<< COND JUMP
010013F7 mov eax,dword ptr [ebp-0Ch] <<< DO THE JOB..
010013FA mov byte ptr [ebp+eax-78h],0
010013FF mov ecx,dword ptr [ebp-0Ch] <<< UPDATE i
01001402 add ecx,1
01001405 mov dword ptr [ebp-0Ch],ecx
01001408 jmp wmain+51h (10013F1h) <<< UNCOND JUMP
}
// "DO-WHILE" LOOP:
i = 0;
. 0100140A mov dword ptr [ebp-0Ch],0
do
{
x[i++] = 0;
01001411 mov eax,dword ptr [ebp-0Ch] <<< DO THE JOB..
01001414 mov byte ptr [ebp+eax-78h],0
01001419 mov ecx,dword ptr [ebp-0Ch] <<< UPDATE i
0100141C add ecx,1
0100141F mov dword ptr [ebp-0Ch],ecx
01001422 cmp dword ptr [ebp-0Ch],64h <<< TEST
01001426 jl wmain+71h (1001411h) <<< COND JUMP
}
while (i<100);
Для удобства чтения
Все они взаимозаменяемы; вы можете выбрать один тип и использовать ничего, кроме этого навсегда, но обычно один из них более удобен для данной задачи. Это как сказать "почему есть переключатель, вы можете просто использовать кучу операторов if" - true, но если это общий шаблон для проверки переменной для набора значений, удобнее и гораздо легче читать, если есть функция языка сделать это
Если вы хотите, чтобы цикл выполнялся, когда условие истинно, а не для определенного количества итераций, намного легче понять кому-то другому:
while (cond_true)
чем-то вроде этого:
for (; cond_true ; )
Помните, что цикл for
по существу представляет собой причудливый цикл while
. Это одно и то же.
while <some condition is true> {
// do some stuff
// possibly do something to change the condition
}
for ( some var, <some condition is true>; increment var ) {
}
Преимущество цикла for заключается в том, что сложнее случайно выполнить бесконечный цикл. Вернее, это более очевидно, когда вы делаете это, потому что вы обычно ставите цикл var в исходный оператор.
ЦиклA while
более понятен, если вы не выполняете стандартный инкрементный шаблон. Например:
int x = 1;
while( x != 10 ) {
if ( some condition )
x = 10;
else
x += 5;
}
Вы должны использовать такой цикл, который наиболее полно соответствует вашим потребностям. Например:
for(int i = 0; i < 10; i++)
{
print(i);
}
//or
int i = 0;
while(i < 10)
{
print(i);
i++;
}
Очевидно, что в такой ситуации "для" выглядит лучше, чем "пока". И "делать пока" следует использовать, когда некоторые операции должны выполняться уже до того момента, когда будет проверено состояние вашего цикла.
Извините за мой плохой английский).
A for
предлагают фиксированную итерацию с использованием индекса или вариантов на этой схеме.
A while
и do... while
- это конструкции, которые вы используете, когда есть условие, которое необходимо проверять каждый раз (кроме некоторой конструкции с индексом, см. выше). Они отличаются тем, что выполняется первое выполнение проверки состояния.
Вы можете использовать любую конструкцию, но у них есть свои преимущества и недостатки в зависимости от вашего варианта использования.
Одно общее недоразумение с циклами while
/for
, которые я видел, заключается в том, что их эффективность отличается. Циклы while
и for
являются одинаково эффективными. Я помню, что мой учитель из высшего учебного заведения сказал мне, что для циклов более эффективны для итерации, когда вам нужно увеличивать число. Это не так.
for
- это просто синтаксически sugared while
петли и сделать код итерации быстрее для записи.
Когда компилятор принимает ваш код и компилирует его, он преобразует его в форму, которая легче понять и выполнить компьютер на более низком уровне (сборка). Во время этого перевода тонкие различия между синтаксисами while
и for
теряются, и они становятся точно такими же.
Я заметил некоторое время назад, что цикл For обычно генерирует еще несколько машинных команд, чем цикл while. Однако, если вы внимательно посмотрите на примеры, которые отражают мои наблюдения, разница в двух или трех машинных инструкциях вряд ли стоит особо рассмотреть.
Заметьте также, что инициализатор цикла WHILE можно исключить, выпекая его в код, e. г:.
static int intStartWith = 100;
Статический модификатор выпекает начальное значение в коде, сохраняя (барабанную ручку) одну инструкцию MOV. Большее значение, отмечая переменную как статическую, перемещает ее за рамки стека. При разрешении выравнивания по переменной он может также создавать немного меньший код, так как команда MOV и ее операнды занимают больше места, чем, например, целочисленное, логическое или символьное значение (ANSI или Unicode).
Однако, если переменные выровнены по 8-байтным границам, общий параметр по умолчанию, int, bool или TCHAR, испеченный в код, стоит столько же байтов, сколько инструкция MOV.
Они все одинаковы в своей работе. Вы можете делать то же самое, используя любой из них. Но для удобства чтения, удобства использования, удобства и т.д. Они отличаются.
Разница между while и do-while заключается в том, что при проверке условия цикла и если это правда, тело выполняется и условие снова проверяется. Выполнение проверки выполняется после выполнения тела, поэтому с помощью do-while тело выполняется хотя бы один раз.
Конечно, вы можете написать цикл while как do-while и vv, но для этого обычно требуется дублирование кода.
Одна из особенностей do while
заключается в том, что вам нужно получить полдюжины после завершения. Он часто используется в определениях макросов для выполнения нескольких операторов только один раз, ограничивая влияние макроса. Если макросы, определенные как блоки, могут возникать некоторые ошибки синтаксического анализа.
Для циклов (по крайней мере, учитывая C99) лучше, чем в цикле while, потому что они ограничивают область увеличиваемой переменной (ов).
В то время как циклы полезны, когда условие зависит от некоторых входов. Они наиболее часто используются для трех типов циклов.
Между тем и временем: while
не требуется инициализация или инструкция обновления, поэтому она может выглядеть лучше, более элегантно; for
может иметь отсутствующие утверждения, два или все, поэтому он является наиболее гибким и очевидным, если вам нужно инициализировать, зацикливать условие и "обновить" перед циклом. Если вам нужно только условие цикла (проверено в начале цикла), то while
является более элегантным.
Между параметрами for/while и do-while: in do-while
условие оценивается в конце цикла. Более комфортно, если цикл должен выполняться хотя бы один раз.
Они почти одинаковы, за исключением цикла do-while
. Цикл for
хорош, если у вас есть переменная типа counter
. Это делает его очевидным. Цикл while
имеет смысл в случаях, когда флаг проверяется как показано ниже:
while (!done) {
if (some condtion)
done = true;
}
WHILE более гибкий. FOR более кратким в тех случаях, когда он применяется.
FOR отлично подходит для циклов, у которых есть счетчик какого-то типа, например
for (int n=0; n<max; ++n)
Вы можете сделать то же самое с WHILE, конечно, как указывали другие, но теперь инициализация, тест и приращение разбиваются на три строки. Возможно, три широко разделенные линии, если тело петли велико. Это затрудняет для читателя, что вы делаете. В конце концов, хотя "++ n" является очень распространенной третьей частью FOR, это, конечно, не единственная возможность. Я написал много циклов, где пишу "n + = increment" или более сложное выражение.
FOR также может отлично работать с вещами, отличными от счетчика, конечно. Как
for (int n=getFirstElementFromList(); listHasMoreElements(); n=getNextElementFromList())
Etc.
Но FOR ломается, когда логика "в следующий раз через цикл" усложняется. Рассмотрим:
initializeList();
while (listHasMoreElements())
{
n=getCurrentElement();
int status=processElement(n);
if (status>0)
{
skipElements(status);
advanceElementPointer();
}
else
{
n=-status;
findElement(n);
}
}
То есть, если процесс продвижения может отличаться в зависимости от условий, возникающих при обработке, выражение FOR непрактично. Да, иногда вы можете заставить его работать с достаточно сложными выражениями, использовать тернарный?: Оператор и т.д., Но это обычно делает код менее читаемым, а не читаемым.
На практике большинство моих циклов либо проходят через массив или структуру какого-либо типа, и в этом случае я использую цикл FOR; или читают файл или результирующий набор из базы данных, и в этом случае я использую цикл WHILE ( "while (! eof())" или что-то в этом роде).
/* while loop
5 долларов
1 шоколад = 1 бакс
while my money is greater than 1 bucks
select chocolate
pay 1 bucks to the shopkeeper
money = money - 1
end
приходите домой и не можете пойти во время магазина, потому что мои деньги = 0 баксов */
#include<stdio.h>
int main(){
int money = 5;
while( money >= 1){
printf("inside the shopk and selecting chocolate\n");
printf("after selecting chocolate paying 1 bucks\n");
money = money - 1 ;
printf("my remaining moeny = %d\n", money);
printf("\n\n");
}
printf("dont have money cant go inside the shop, money = %d", money);
return 0;
}
бесконечные деньги
while( codition ){ // condition will always true ....infinite loop
statement(s)
}
пожалуйста, посетите это видео для лучшего понимания https://www.youtube.com/watch?v=eqDv2wxDMJ8&t=25s
/* для цикла
5 долларов
for my money is greater than equal to 1 bucks 0 money >= 1
select chocolate
pay 1 bucks to the shopkeeper
money = money - 1 1-1 => 0
end
*/
#include<stdio.h>
int main(){
int money = 5;
for( ; money >= 1; ){ 0>=1 false
printf("select chocolate \n");
printf("paying 1 bucks to the shopkeeper\n");
money = money - 1; 1-1 = 0
printf(" remaining money =%d\n", money);
printf("\n\n");
}
return 0;
}
Для лучшего понимания посетите https://www.youtube.com/watch?v=_vdvyzzp-R4&t=25s
Я добавлю одно, что я думаю, что люди, которые выше меня, не сказали, while
занимает больше памяти for
do
while
и for
могут использоваться как для циклического программирования. Это зависит от программиста относительно того, используется ли цикл цикла while
или for
. Некоторые из них удобны с использованием цикла while
, а некоторые - с циклом for
.
Используйте любой цикл, который вам нравится. Тем не менее, цикл do...while
может быть несколько сложным в программировании на C.