В C существует три цикла: for
, while
, и do-while
. Каково различие между ними?
Например, это кажется почти всеми while
операторы могут быть заменены for
операторы, правильно? Затем что использует преимущество while
?
Между for и while: while
не требует ни инициализации, ни оператора обновления, поэтому он может выглядеть лучше, более элегантно; для
может иметь отсутствующие операторы, один, два или все, поэтому это наиболее гибкий и очевидный вариант, если вам нужна инициализация, условие цикла и «обновление» перед циклом. Если вам нужно только условие цикла (проверено в начале цикла), то , а
более элегантно.
Между for / while и do-while : в do-while
условие оценивается в конце цикла. Удобнее, если цикл нужно выполнить хотя бы один раз.
Все они одинаковы в своей работе. Вы можете делать то же самое, используя любой из них. Но по удобочитаемости, удобству использования, удобству и т. Д. Они различаются.
Одна из особенностей do while
заключается в том, что для завершения процесса вам необходимо поставить точку с запятой после while. Это часто используется в макроопределениях, чтобы выполнить несколько операторов только один раз, ограничивая при этом влияние макроса. Если макросы определены как блоки, могут возникать некоторые ошибки синтаксического анализа.
A for
предлагают фиксированную итерацию с использованием индекса или варианты этой схемы.
A while
и do... while
- это конструкции, которые используются, когда есть условие, которое должно проверяться каждый раз (кроме некоторых конструкций, похожих на индекс, см. выше). Они различаются тем, когда выполняется первое выполнение проверки условия.
Вы можете использовать любую из этих конструкций, но они имеют свои преимущества и недостатки в зависимости от вашего случая использования.
Разница между while и do-while заключается в том, что while проверяет условие цикла, и если оно истинно, выполняется тело, а условие проверяется снова. Do-while проверяет условие после выполнения тела, поэтому с do-while тело выполняется по крайней мере один раз.
Конечно, вы можете написать цикл while как do-while и vv, но это обычно требует некоторого дублирования кода.
Вы должны использовать такой цикл, который наиболее полно соответствует вашим потребностям. Например:
for(int i = 0; i < 10; i++)
{
print(i);
}
//or
int i = 0;
while(i < 10)
{
print(i);
i++;
}
Очевидно, что в такой ситуации "for" выглядит лучше, чем "while". А "do while" следует использовать, когда некоторые операции должны быть выполнены еще до того момента, когда будет проверено условие цикла.
Извините за мой плохой английский).
Помните, что цикл 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 в начальный оператор.
Цикл while
более понятен, когда вы не выполняете стандартный шаблон увеличения. Например:
int x = 1;
while( x != 10 ) {
if ( some condition )
x = 10;
else
x += 5;
}
Если вы хотите, чтобы цикл выполнялся, пока условие истинно, а не в течение определенного количества итераций, это гораздо легче понять другому:
while (cond_true)
чем что-то вроде этого:
for (; cond_true ; )
Они все взаимозаменяемы; вы могли бы выбрать один тип и использовать только его, но обычно один из них более удобен для данной задачи. Это как сказать: "Зачем нужен switch, можно просто использовать кучу операторов if" - верно, но если это обычный шаблон для проверки переменной на набор значений, то будет удобно и гораздо легче читать, если для этого есть языковая функция
.A цикл while всегда будет сначала оценивать условие.
while (condition) {
//gets executed after condition is checked
}
Цикл do / while всегда будет выполняться
код в сделать {}
блок первым
а затем оцените состояние.
do {
//gets executed at least once
} while (condition);
цикл for позволяет вам инициировать переменную счетчика, условие проверки и способ увеличения счетчика в одной строке.
for (int x = 0; x < 100; x++) {
//executed until x >= 100
}
В конце концов, все они по-прежнему являются циклами, но они предлагают некоторую гибкость в том, как они выполняются.
Вот отличное объяснение аргументов , стоящих за использованием каждого отдельного типа цикла, которое может помочь прояснить ситуацию. Спасибо clyfe
Основное отличие
для
и, а
- это вопрос прагматика: мы обычно используемвместо
, когда известно количество итераций, и используйте конструкцииwhile
, когда количество итераций неизвестно в продвигать., а
vsделают ...а
вопрос также в прагматике, второй выполняет инструкции один раз в начале, а потом ведет себя так же, как и простое while.
Циклы For особенно удобны, потому что они лаконичны. Чтобы этот цикл for
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 он просто перескакивает, чтобы повторно оценить условие цикла.
Они практически одинаковы, за исключением цикла do-while
. Цикл for
хорош, когда у вас есть переменная типа counter
. Это делает его очевидным. Цикл while
имеет смысл в случаях, когда проверяется флаг, как показано ниже :
while (!done) {
if (some condtion)
done = true;
}
Циклы For (по крайней мере, с учетом C99) превосходят циклы while, поскольку они ограничивают область действия увеличиваемой переменной (переменных).
Циклы Do while полезны, когда условие зависит от некоторых входных данных. Из трех типов петель они используются наиболее редко.
WHILE более гибкий. FOR является более кратким в тех случаях, когда он применяется.
FOR отлично подходит для циклов, у которых есть какой-то счетчик, например
for (int n=0; n<max; ++n)
Вы, конечно, можете выполнить то же самое с WHILE, как указывали другие, но теперь инициализация, проверка и приращение прерываются через три строки. Возможно три широко разделенных строки, если тело цикла большое. Из-за этого читателю сложнее увидеть, что вы делаете. В конце концов, хотя «++ n» - очень распространенная третья часть FOR, это, конечно, не единственная возможность. Я написал много циклов, в которых я пишу «n + = increment» или какое-нибудь более сложное выражение.
FOR, конечно же, может прекрасно работать с другими вещами, кроме счетчика. Как
for (int n=getFirstElementFromList(); listHasMoreElements(); n=getNextElementFromList())
И т. Д.
Но 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 ())» или что-то в этом роде).
Если есть серьезные опасения по поводу скорости и производительности, лучший подход - проверить код, созданный компилятором, на уровне сборки.
Например, следующий код показывает, что «do-while» немного быстрее. Это потому, что инструкция «jmp» не используется в цикле «do-while».
Кстати, в этом конкретном примере наихудший случай дается циклом for. :))
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":
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":
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":
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);
Одно из распространенных недоразумений с while
/ для циклов
, которое я видел, заключается в том, что их эффективность различается. Циклы while
и for
одинаково эффективны . Я помню, как мой учитель по информатике из старшей школы сказал мне, что циклы for более эффективны для итераций, когда вам нужно увеличивать число. Это не относится к делу.
Циклы For
просто синтаксически подслащены циклами while
и ускоряют запись итерационного кода.
Когда компилятор берет ваш код и компилирует его, он переводит его в форму, более простую для понимания и выполнения компьютером на более низком уровне (сборка). Во время этого перевода тонкие различия между синтаксисами и
и для
теряются, и они становятся точно такими же.