Телом цикла может может быть любой оператор, в том числе им может быть тоже оператор цикла или составной оператор, в котором могут быть операторы цикла. Если в теле цикла есть еще какой-то оператор цикла, мы имеем дело с ситуацией, которая называется вложенные циклы (nested loops) – один оператор цикла оказывается вложен в другой.
В качестве примеров мы рассмотрим печать некоторых так называемых псевдографических изображений. Псевдографика (pseudographics или ASCII-art) – это графические изображения, состоящие из текстовых символов.
Пусть, например, нам надо написать программу, которая для введённого целого числа n должна напечатать треугольник из символов * такого вида:
n = 0
n = 1
*
n = 2
*
**
n = 7
*
**
***
****
*****
******
*******
(аналогично для других значений n
).
Решение:
Итак, программа должна напечатать n
текстовых строчек, причём, если считать строчки сверху вниз (то
есть в порядке их печати) по возрастанию, начиная с номера 1, то в строчке с номером i
должно быть i
символов *
.
Разберёмся вначале, как должен выглядеть фрагмент программы, который i
раз напечатает символ *
(в одну
«линию»).
Самый, пожалуй, очевидный способ такой:
for (int j = 1; j <= i; ++j) {
printf("*");
}
printf("\n");
Но нам нужна не одна такая строчка, а n
строчек, значит, этот цикл необходимо выполнять несколько, а
точнее – n
раз, для этого поместим его в другой цикл.
В результате мы получаем такую программу:
#include <stdio.h>
int main(void) {
printf("n = ");
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) { // цикл по строчкам, i – номер строчки
for (int j = 1; j <= i; ++j) { // цикл по символам в строчке, j – позиция символа в ней
printf("*");
}
printf("\n"); // печать перехода на новую строчку
}
return 0;
}
Обратите внимание, что если не напечатать символ перехода на новую строчку, то все напечатанные символы окажутся расположенными на одной строчке!
Дополнительный вопрос к этому примеру: А как напечатать квадрат со стороной n символов?
Попробуем теперь написать программу, которая будет печатать треугольник немного другого вида:
n = 5
*
**
***
****
*****
Решение:
Так же, как и в предыдущей программе, в этом случае в i
-й строке (если считать строки сверху вниз,
начиная с номера 1) должно печататься i
символов *
. Но в начале каждой строки нужно напечатать ещё
нужное число пробелов. Нетрудно заметить :-), что в i
-й строке их должно быть n - i
штук.
Пользуясь этими соображениями, программу можно написать так:
#include <stdio.h>
int main(void) {
printf("n= ");
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n - i; ++j) { // в этом цикле печатаем пробелы
printf(" ");
}
for (int j = 1; j <= i; ++j) { // в этом цикле печатаем звёздочки
printf("*");
}
printf("\n");
}
return 0;
}
Можно написать программу, которая напечатает то же самое, и несколько иным способом – исходя, например, из нумерации строк сверху вниз по убыванию (в этом примере последней строке будет соответствовать номер 0; номера позиций в строчке для разнообразия здесь тоже нумеруются, начиная с 0):
#include <stdio.h>
int main(void) {
printf("n= ");
int n;
scanf("%d", &n);
for (int i = n - 1; i >= 0; --i) {
for (int j = 0; j < i; ++j) {
printf(" ");
}
for (int j = 0; j < n - i; ++j) {
printf("*");
}
printf("\n");
}
return 0;
}
Дополнительные вопросы к этому примеру:
Придумайте другие способы написания программы для решения этой же задачи.
Можно ли написать такую программу, используя в ней только один-единственный цикл for
?