Є три петлі в C: for
, while
і do-while
. Яка різниця між ними?
Наприклад, здається, майже всі while
твердження можна замінити for
твердженнями, так? Тоді, в чому перевага while
?
Є три петлі в C: for
, while
і do-while
. Яка різниця між ними?
Наприклад, здається, майже всі while
твердження можна замінити for
твердженнями, так? Тоді, в чому перевага while
?
loop
інструкцію (віднімання, порівняння та перехід в одній інструкції), ніж компілюючий while
в loop
інструкцію? чи компілятори нинішнього часу компілюються for
в loop
інструкцію?
Відповіді:
У той час як петля завжди буде оцінювати стан першого.
while (condition) {
//gets executed after condition is checked
}
Робити / в той час як цикл завжди буде виконувати код в do{}
блоці першого , а потім оцінити стан.
do {
//gets executed at least once
} while (condition);
Цикл дозволяє ініціювати змінний лічильник, умова перевірки, і спосіб , щоб збільшити ваш лічильник все в одному рядку.
for (int x = 0; x < 100; x++) {
//executed until x >= 100
}
Зрештою, вони все ще є петлями, але вони пропонують певну гнучкість щодо того, як вони виконуються.
Ось чудове пояснення міркувань щодо використання кожного іншого типу циклу, що може допомогти прояснити ситуацію. Спасибі clyfe
Основна різниця між
for
's іwhile
' s полягає у питаннях прагматики: ми зазвичай використовуємо,for
коли існує відома кількість ітерацій, і використовуємоwhile
конструкції, коли кількість ітерацій невідомо заздалегідь. Випускwhile
vsdo ... while
також стосується прагматики, другий виконує інструкції один раз при запуску, а згодом він поводиться так само, як і простий час.
Бо петлі особливо приємні, оскільки вони лаконічні. Для цього для циклу 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 він просто перескакує, щоб переоцінити стан циклу.
for's
і while's
є питанням прагматики: ми зазвичай використовуємо, for
коли існує відома кількість ітерацій , і використовуємо while
конструкції, коли кількість ітерацій невідомо заздалегідь . Випуск while
vs do ... while
також стосується прагматики, другий виконує інструкції один раз при запуску, а згодом він поводиться так само, як і простий 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;
}
// "ЗА" ЦИКЛ:
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
}
// "ПОКА" ЛОП:
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
}
// "ЗАКРІПЛЕННЯ":
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" - правда, але якщо це звичайний шаблон перевірки змінної на набір значень, це зручно і набагато легше читати, якщо є мовна функція для цього
do {if(!cond) break; /* do stuff */ } while(cond);
. Некрасиво і повторюється, але це свого роду міркування про те, чому існують варіації :)
/* do stuff */
частину, якщо cond
вона хибна
Якщо ви хочете, щоб цикл виконувався, якщо умова є істинним, а не для певної кількості ітерацій, комусь іншому набагато легше зрозуміти:
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 у початковий оператор.
while
Цикл більш ясно , коли ви не робите стандартний шаблон инкрементирование. Наприклад:
int x = 1;
while( x != 10 ) {
if ( some condition )
x = 10;
else
x += 5;
}
for
петлі, ймовірно, були введені як зручність та продуктивні методи.
Ви повинні використовувати такий цикл, який найбільш повно відповідає вашим потребам. Наприклад:
for(int i = 0; i < 10; i++)
{
print(i);
}
//or
int i = 0;
while(i < 10)
{
print(i);
i++;
}
Очевидно, що в такій ситуації "for" виглядає краще, ніж "while". І "робити поки" слід використовувати, коли деякі операції повинні бути зроблені вже до того моменту, коли стан вашого циклу буде перевірено.
Вибачте за мою погану англійську).
Одне з поширених непорозумінь із while
/ for
циклами, яке я бачив, полягає в тому, що їх ефективність відрізняється. While
петлі та for
петлі однаково ефективні . Пам’ятаю, мій учитель комп’ютера з середньої школи сказав мені, що цикли ефективніші для ітерації, коли доводиться збільшувати число. Це не так.
For
цикли - це просто синтаксично зацукровані while
цикли і роблять код ітерації швидшим для запису.
Коли компілятор бере ваш код і компілює його, він переводить його у форму, яку комп'ютеру легше зрозуміти та виконати на нижчому рівні (збірка). Під час цього перекладу тонкі відмінності між синтаксисами while
та та for
втрачаються, і вони стають абсолютно однаковими.
for (i = 0 i < limit ; i++)
.
A for
Передбачає фіксовані ітерації з використанням індексу або варіантами за цією схемою.
А while
іdo... while
є конструкції використовується , коли є умова , яка повинна бути перевірено кожен раз ( за винятком деякого індексу Двійник конструкції, см . Вище) Вони відрізняються тим, коли виконується перше виконання перевірки стану.
Ви можете використовувати будь-яку конструкцію, але вони мають свої переваги та недоліки залежно від вашого випадку використання.
Я помітив деякий час тому, що цикл For зазвичай генерує на кілька машинних інструкцій більше, ніж цикл while. Однак, якщо ви уважно придивитеся до прикладів, які відображають мої спостереження, різниця полягає в двох-трьох машинних інструкціях, навряд чи варта великого розгляду.
Також зауважте, що ініціалізатор циклу WHILE можна усунути, вписавши його в код, наприклад:
static int intStartWith = 100;
Статичний модифікатор виписує початкове значення в коді, зберігаючи (удар барабана) одну інструкцію MOV. Більше значення має позначення змінної як статичної, що переміщує її за рамки стека. Дозволяє вирівнювання за змінним, він також може виробляти дещо менший код, оскільки інструкція MOV та її операнди займають більше місця, ніж, наприклад, ціле число, булеве значення або значення символу (або ANSI, або Unicode).
Однак, якщо змінні вирівняні за межами 8 байтів, загальний параметр за замовчуванням, int, bool або TCHAR, запечений у коді, коштує таку ж кількість байт, як інструкція MOV.
Вони однакові в роботі, яку виконують. Ви можете робити ті самі речі, використовуючи будь-яку з них. Але щодо читабельності, зручності використання, зручності тощо вони відрізняються.
Різниця між while і do-while полягає в тому, що while перевіряє стан циклу, і якщо це відповідає дійсності, тіло виконується і умова перевіряється знову. Do-while перевіряє стан після виконання тіла, тому з do-while тіло виконується принаймні один раз.
Звичайно, ви можете написати цикл while як do-while та vv, але це зазвичай вимагає певного копіювання коду.
Однією особливістю do while
є те, що вам потрібно через деякий час ставити двокрапку для завершення. Він часто використовується у визначеннях макросів для виконання декількох операторів лише один раз, обмежуючи вплив макросу. Якщо макроси визначені як блоки, можуть виникнути помилки аналізу.
do-while
існує
do-while
, він просто використовується, тому що трапляється, щоб створити блок і все одно вимагає крапки з комою в кінці
Для циклів (принаймні, враховуючи C99) перевершують цикли while, оскільки вони обмежують область збільшених змінних.
Цикли do while корисні, коли умова залежить від деяких входів. Вони найчастіше використовуються з трьох типів циклів.
Між тим і на час: while
не потребує ініціалізації та оператора оновлення, тому може виглядати краще, елегантніше; for
може мати відсутні оператори, один два або всі, тому це найбільш гнучке і очевидне, якщо вам потрібна ініціалізація, умова циклу та "оновлення" перед циклічним виконанням. Якщо вам потрібні лише умови циклу (перевірено на початку циклу), то while
це більш елегантно.
Між for / while та do-while : in do-while
обчислюється в кінці циклу. Більш зручним, якщо цикл потрібно виконати хоча б один раз.
В той час, як є більш гнучким. FOR є більш стислим у тих випадках, коли він застосовується.
FOR чудово підходить для петель, які мають якийсь лічильник, наприклад
for (int n=0; n<max; ++n)
Ви можете виконати те ж саме за допомогою WHILE, звичайно, як вказували інші, але зараз ініціалізація, тест і збільшення розбиті на три рядки. Можливо три широко розділені лінії, якщо тіло петлі велике. Це ускладнює читачеві розуміння того, що ви робите. Зрештою, хоча "++ n" є дуже поширеним третім фрагментом FOR, це, звичайно, не єдина можливість. Я написав багато циклів, де пишу "n + = приріст" або якийсь більш складний вираз.
Звичайно, 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
циклу. for
Петля хороша , коли у вас є counter
такі змінний. Це робить це очевидним. while
цикл має сенс у випадках, коли перевіряється прапор, як показано нижче:
while (!done) {
if (some condtion)
done = true;
}
while
і for
оператори можуть бути використані для циклічного програмування. Це буде залежати від програміста щодо того, чи використовується while
цикл чи for
цикл. Комусь зручно користуватися while
циклом, а хтось із for
циклом.
Використовуйте будь-яку вподобану петлю. Однак do...while
цикл може бути дещо складним у програмуванні на Сі .
while
, do while
і for
петлі. Погляньте на верхню відповідь, і ви їх знайдете.
/ * while циклу
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
GOTO
цикл. Хоча люди не сприймають це як цикл, я вважаю, що всі цикли по суті компілюються до циклів умовного GOTO.