Skip to content

Вложенные циклы

Yuriy Syrovetskiy edited this page Dec 27, 2017 · 2 revisions

Телом цикла может может быть любой оператор, в том числе им может быть тоже оператор цикла или составной оператор, в котором могут быть операторы цикла. Если в теле цикла есть еще какой-то оператор цикла, мы имеем дело с ситуацией, которая называется вложенные циклы (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?

Clone this wiki locally