W języku C istnieją trzy główne konstrukcje cykliczne: for, while i do-while. Ich pojawienie się wiąże się z koniecznością realizacji powtarzalnych obliczeń, ułatwieniem przeszukiwania struktur danych i automatyzowaniem przetwarzania tablic. Po raz pierwszy składnia pętli pojawiła się w wczesnych językach programowania (Algol, Fortran) i została dostosowana do składni C w celu zwiększenia czytelności i kontroli przepływu.
Historia pytania
Początkowo programiści używali etykiet i instrukcji goto do organizacji powtarzających się działań, co szybko prowadziło do zawiłego kodu (spaghetti code). Wprowadzenie strukturalnych pętli (w C — od 1972 roku) pozwoliło zuniwersalizować podejście do powtarzania i opisywania logiki programów.
Problem
Głównym zadaniem pętli jest określenie, ile razy powinno być powtórzone określone działanie, i w jaki sposób kontrolować wyjście z pętli. Ważne jest, aby prawidłowo wybierać typ pętli w zależności od tego, czy liczba powtórzeń jest znana z góry, czy wymagana jest co najmniej jedna iteracja ciała, oraz czy należy wcześniej obliczyć warunek wyjścia.
Rozwiązanie
Przykład kodu:
#include <stdio.h> int main() { int i = 0; // Przykład pętli while while (i < 3) { printf("while: %d\n", i); i++; } // Przykład pętli for for (int j = 0; j < 3; j++) { printf("for: %d\n", j); } // Przykład pętli do-while int k = 0; do { printf("do-while: %d\n", k); k++; } while (k < 3); return 0; }
Kluczowe cechy:
Czym różni się while(1) od for(;;) i która z nich jest lepsza do stosowania w nieskończonej pętli?
Odpowiedź: Obie opcje tworzą nieskończoną pętlę i są tłumaczone na ten sam kod maszynowy, różnicy w wydajności nie ma. Zazwyczaj używa się for(;;), aby wyraźnie pokazać, że nie oczekuje się ani inicjalizacji, ani warunku wyjścia, ani kroku.
for(;;) { // nieskończona pętla } // lub while(1) { // nieskończona pętla }
Czy można zmieniać zmienną pętli wewnątrz ciała for i co się stanie?
Odpowiedź: Zmiana zmiennej licznika (np. i++) w ciele pętli for prowadzi do nieprzewidywalnej liczby iteracji. Takie zmiany mylą czytających i utrudniają debugowanie.
for (int i = 0; i < 10; i++) { printf("%d\n", i); i += 2; // nietypowa zmiana kroku! }
Co się stanie, jeśli ciało pętli pozostanie puste? W jakich przypadkach ma to sens?
Odpowiedź: Puste ciało pętli jest dozwolone i używane do oczekiwania na wystąpienie zdarzenia lub przygotowania danych:
while(*src++ = *dst++); // kopiowanie stringu do znaku '\0'
Negatywny przypadek
W projekcie używano for z zmianą zmiennej licznika w ciele, co doprowadziło do nieprawidłowej liczby przetworzonych elementów, błędów i trudności w debugowaniu.
Zalety:
Wady:
Pozytywny przypadek
Użycie for do przeszukiwania tablicy o stałej długości bez zmiany licznika z zewnątrz:
Zalety:
Wady: