Условные циклы в языке C

CCBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном занятии вы научитесь реализовывать условные циклы в программировании на языке C. Вы начнете с понимания основ циклов while, а затем изучите использование директив break и continue для управления выполнением циклов. Кроме того, вы научитесь фильтровать элементы массива с использованием условных операторов и оптимизировать эффективность циклов различными директивами. К концу этого лабораторного занятия вы будете иметь твердое понимание условных циклов и их практических применений в программировании на языке C.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL c(("C")) -.-> c/ControlFlowGroup(["Control Flow"]) c(("C")) -.-> c/CompoundTypesGroup(["Compound Types"]) c(("C")) -.-> c/UserInteractionGroup(["User Interaction"]) c(("C")) -.-> c/BasicsGroup(["Basics"]) c(("C")) -.-> c/FunctionsGroup(["Functions"]) c/BasicsGroup -.-> c/operators("Operators") c/ControlFlowGroup -.-> c/if_else("If...Else") c/ControlFlowGroup -.-> c/for_loop("For Loop") c/ControlFlowGroup -.-> c/while_loop("While Loop") c/ControlFlowGroup -.-> c/break_continue("Break/Continue") c/CompoundTypesGroup -.-> c/arrays("Arrays") c/FunctionsGroup -.-> c/math_functions("Math Functions") c/UserInteractionGroup -.-> c/user_input("User Input") c/UserInteractionGroup -.-> c/output("Output") subgraph Lab Skills c/operators -.-> lab-438260{{"Условные циклы в языке C"}} c/if_else -.-> lab-438260{{"Условные циклы в языке C"}} c/for_loop -.-> lab-438260{{"Условные циклы в языке C"}} c/while_loop -.-> lab-438260{{"Условные циклы в языке C"}} c/break_continue -.-> lab-438260{{"Условные циклы в языке C"}} c/arrays -.-> lab-438260{{"Условные циклы в языке C"}} c/math_functions -.-> lab-438260{{"Условные циклы в языке C"}} c/user_input -.-> lab-438260{{"Условные циклы в языке C"}} c/output -.-> lab-438260{{"Условные циклы в языке C"}} end

Понимание циклов while

На этом этапе вы узнаете основы циклов while в программировании на языке C. Циклы while — это мощные управляющие структуры, которые позволяют повторять блок кода, пока определенное условие остается истинным.

Создадим простую программу на языке C, чтобы продемонстрировать базовый синтаксис цикла while. Откройте редактор VSCode и создайте новый файл с именем while_loop_example.c в директории ~/project.

cd ~/project
touch while_loop_example.c
#include <stdio.h>

int main() {
    int count = 1;

    while (count <= 5) {
        printf("Current count: %d\n", count);
        count++;
    }

    return 0;
}

Разберем код на части:

  • int count = 1; инициализирует переменную-счетчик.
  • while (count <= 5) создает цикл, который продолжается, пока значение count меньше или равно 5.
  • printf() выводит текущее значение count.
  • count++ увеличивает счетчик на каждой итерации.

Скомпилируйте и запустите программу:

gcc while_loop_example.c -o while_loop_example
./while_loop_example

Пример вывода:

Current count: 1
Current count: 2
Current count: 3
Current count: 4
Current count: 5

Вот еще один пример, демонстрирующий цикл while с вводом данных от пользователя:

#include <stdio.h>

int main() {
    int number;

    printf("Enter numbers (enter 0 to stop):\n");

    number = 1;  // Initialize to non-zero value
    while (number!= 0) {
        printf("Enter a number: ");
        scanf("%d", &number);

        if (number!= 0) {
            printf("You entered: %d\n", number);
        }
    }

    printf("Loop ended. Goodbye!\n");

    return 0;
}

В этом примере показано, как циклы while можно использовать для интерактивного ввода данных, продолжая выполнение до тех пор, пока не будет выполнено определенное условие (ввод 0).

Применение директивы break в циклах while

На этом этапе вы узнаете о директиве break в программировании на языке C, которая позволяет досрочно выйти из цикла, когда выполняется определенное условие. Оператор break предоставляет способ немедленно завершить текущий цикл и продолжить выполнение программы с оператора, следующего за циклом.

Создадим новый файл с именем break_loop_example.c в директории ~/project, чтобы продемонстрировать использование директивы break:

cd ~/project
touch break_loop_example.c
#include <stdio.h>

int main() {
    int number;

    printf("Enter numbers to find the first multiple of 10:\n");

    while (1) {  // Infinite loop
        printf("Enter a number: ");
        scanf("%d", &number);

        if (number % 10 == 0) {
            printf("Found a multiple of 10: %d\n", number);
            break;  // Exit the loop when a multiple of 10 is found
        }

        printf("Not a multiple of 10. Try again.\n");
    }

    printf("Loop terminated after finding a multiple of 10.\n");

    return 0;
}

Разберем код на части:

  • while (1) создает бесконечный цикл, который будет продолжаться до тех пор, пока не встретится оператор break.
  • Когда пользователь вводит число, делящееся на 10, оператор break немедленно завершает цикл.
  • Если число не делится на 10, цикл продолжает запрашивать ввод.

Вот еще один пример, демонстрирующий использование break в более сложной ситуации:

#include <stdio.h>

int main() {
    int sum = 0;
    int count = 0;
    int input;

    printf("Enter numbers (enter a negative number to stop):\n");

    while (1) {
        printf("Enter a number: ");
        scanf("%d", &input);

        if (input < 0) {
            break;  // Exit the loop if a negative number is entered
        }

        sum += input;
        count++;
    }

    if (count > 0) {
        printf("Average of entered numbers: %.2f\n", (float)sum / count);
    } else {
        printf("No numbers were entered.\n");
    }

    return 0;
}

В этом примере показано, как можно использовать директиву break для:

  • Прекращения сбора ввода, когда выполняется определенное условие.
  • Вычисления среднего значения введенных чисел.
  • Предоставления гибкости при завершении цикла.

Скомпилируйте и запустите программы, чтобы увидеть, как работает директива break:

gcc break_loop_example.c -o break_loop_example
./break_loop_example

Использование директивы continue в циклах while

На этом этапе вы узнаете о директиве continue в программировании на языке C, которая позволяет пропустить текущую итерацию цикла и перейти к следующей. Оператор continue предоставляет способ выборочно выполнять или пропускать части цикла на основе определенных условий.

Создадим новый файл с именем continue_loop_example.c в директории ~/project, чтобы продемонстрировать использование директивы continue:

cd ~/project
touch continue_loop_example.c
#include <stdio.h>

int main() {
    int number;
    int sum_even = 0;
    int count_even = 0;

    printf("Enter 10 numbers to calculate the sum and count of even numbers:\n");

    int i = 0;
    while (i < 10) {
        printf("Enter number %d: ", i + 1);
        scanf("%d", &number);

        // Skip odd numbers
        if (number % 2!= 0) {
            printf("Skipping odd number: %d\n", number);
            continue;  // Move to the next iteration
        }

        sum_even += number;
        count_even++;

        i++;
    }

    if (count_even > 0) {
        printf("Sum of even numbers: %d\n", sum_even);
        printf("Count of even numbers: %d\n", count_even);
        printf("Average of even numbers: %.2f\n", (float)sum_even / count_even);
    } else {
        printf("No even numbers were entered.\n");
    }

    return 0;
}

Разберем код на части:

  • Программа запрашивает у пользователя ввод 10 чисел.
  • if (number % 2!= 0) проверяет, является ли число нечетным.
  • continue пропускает остаток текущей итерации для нечетных чисел.
  • Только четные числа суммируются и подсчитываются.

Вот еще один пример, демонстрирующий использование continue с более сложными условиями:

#include <stdio.h>

int main() {
    int number;
    int positive_count = 0;
    int negative_count = 0;

    printf("Enter numbers (enter 0 to stop):\n");

    while (1) {
        printf("Enter a number: ");
        scanf("%d", &number);

        // Exit the loop if 0 is entered
        if (number == 0) {
            break;
        }

        // Skip zero
        if (number == 0) {
            continue;
        }

        // Count positive and negative numbers
        if (number > 0) {
            positive_count++;
        } else {
            negative_count++;
        }
    }

    printf("Positive numbers count: %d\n", positive_count);
    printf("Negative numbers count: %d\n", negative_count);

    return 0;
}

В этом примере показано, как можно использовать директиву continue для:

  • Пропуска определенных значений.
  • Выборочной обработки чисел на основе условий.
  • Предоставления более гибкого управления циклом.

Скомпилируйте и запустите программы, чтобы увидеть, как работает директива continue:

gcc continue_loop_example.c -o continue_loop_example
./continue_loop_example

Фильтрация элементов массива с использованием условных операторов

На этом этапе вы узнаете, как фильтровать элементы массива с использованием условных операторов и циклов в программировании на языке C. Фильтрация позволяет выбирать определенные элементы из массива на основе определенных условий.

Создадим новый файл с именем array_filtering.c в директории ~/project, чтобы продемонстрировать фильтрацию элементов массива:

cd ~/project
touch array_filtering.c
#include <stdio.h>

#define MAX_SIZE 10

int main() {
    int numbers[MAX_SIZE];
    int filtered_even[MAX_SIZE];
    int filtered_count = 0;

    // Input array elements
    printf("Enter %d numbers:\n", MAX_SIZE);
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("Enter number %d: ", i + 1);
        scanf("%d", &numbers[i]);
    }

    // Filter even numbers
    printf("\nFiltered Even Numbers:\n");
    for (int i = 0; i < MAX_SIZE; i++) {
        if (numbers[i] % 2 == 0) {
            filtered_even[filtered_count] = numbers[i];
            filtered_count++;
            printf("%d ", numbers[i]);
        }
    }

    printf("\n\nTotal even numbers: %d\n", filtered_count);

    return 0;
}

Разберем процесс фильтрации:

  • Мы создаем два массива: numbers для хранения введенных данных и filtered_even для хранения отфильтрованных элементов.
  • Первый цикл считывает 10 чисел от пользователя.
  • Второй цикл использует условный оператор для фильтрации четных чисел.
  • if (numbers[i] % 2 == 0) проверяет, является ли число четным.
  • Соответствующие элементы сохраняются в массиве filtered_even.

Вот более сложный пример с несколькими условиями фильтрации:

#include <stdio.h>

#define MAX_SIZE 10

int main() {
    int numbers[MAX_SIZE];
    int prime_numbers[MAX_SIZE];
    int prime_count = 0;

    // Input array elements
    printf("Enter %d numbers:\n", MAX_SIZE);
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("Enter number %d: ", i + 1);
        scanf("%d", &numbers[i]);
    }

    // Filter prime numbers
    printf("\nFiltered Prime Numbers:\n");
    for (int i = 0; i < MAX_SIZE; i++) {
        // Skip numbers less than 2
        if (numbers[i] < 2) continue;

        int is_prime = 1;
        for (int j = 2; j * j <= numbers[i]; j++) {
            if (numbers[i] % j == 0) {
                is_prime = 0;
                break;
            }
        }

        // Add prime numbers to filtered array
        if (is_prime) {
            prime_numbers[prime_count] = numbers[i];
            prime_count++;
            printf("%d ", numbers[i]);
        }
    }

    printf("\n\nTotal prime numbers: %d\n", prime_count);

    return 0;
}

В этом примере показано:

  • Фильтрация простых чисел из входного массива.
  • Использование вложенных циклов для проверки простоты числа.
  • Сохранение отфильтрованных элементов в отдельном массиве.

Скомпилируйте и запустите программы:

gcc array_filtering.c -o array_filtering
./array_filtering

Пример ввода и вывода:

Enter 10 numbers:
Enter number 1: 5
Enter number 2: 12
Enter number 3: 7
Enter number 4: 15
...

Filtered Prime Numbers:
5 7

Total prime numbers: 2

Оптимизация эффективности циклов с использованием директив

На этом этапе вы узнаете техники по оптимизации эффективности циклов в программировании на языке C с использованием различных директив и стратегий. Мы рассмотрим различные подходы для улучшения производительности и читаемости циклов.

Создадим файл с именем loop_optimization.c в директории ~/project, чтобы продемонстрировать техники оптимизации:

cd ~/project
touch loop_optimization.c
#include <stdio.h>
#include <time.h>

#define ARRAY_SIZE 10000

// Function to calculate sum using traditional loop
int traditional_sum(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// Function to calculate sum using optimized loop
int optimized_sum(int arr[], int size) {
    int sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;

    // Loop unrolling technique
    int i;
    for (i = 0; i + 4 < size; i += 4) {
        sum1 += arr[i];
        sum2 += arr[i + 1];
        sum3 += arr[i + 2];
        sum4 += arr[i + 3];
    }

    // Handle remaining elements
    for (; i < size; i++) {
        sum1 += arr[i];
    }

    return sum1 + sum2 + sum3 + sum4;
}

int main() {
    int arr[ARRAY_SIZE];
    clock_t start, end;
    double cpu_time_used;

    // Initialize array
    for (int i = 0; i < ARRAY_SIZE; i++) {
        arr[i] = i + 1;
    }

    // Traditional sum
    start = clock();
    int traditional_result = traditional_sum(arr, ARRAY_SIZE);
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("Traditional Sum: %d\n", traditional_result);
    printf("Traditional Loop Time: %f seconds\n", cpu_time_used);

    // Optimized sum
    start = clock();
    int optimized_result = optimized_sum(arr, ARRAY_SIZE);
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("Optimized Sum: %d\n", optimized_result);
    printf("Optimized Loop Time: %f seconds\n", cpu_time_used);

    return 0;
}

Вот еще один пример, демонстрирующий несколько техник оптимизации:

#include <stdio.h>

#define MAX_SIZE 1000

int main() {
    int numbers[MAX_SIZE];
    int even_sum = 0, odd_sum = 0;

    // Efficient initialization and summation
    for (int i = 0; i < MAX_SIZE; i++) {
        numbers[i] = i + 1;

        // Conditional sum with minimal branching
        even_sum += (numbers[i] % 2 == 0) * numbers[i];
        odd_sum += (numbers[i] % 2!= 0) * numbers[i];
    }

    printf("Sum of Even Numbers: %d\n", even_sum);
    printf("Sum of Odd Numbers: %d\n", odd_sum);

    return 0;
}

Основные демонстрируемые техники оптимизации:

  1. Развертывание цикла (loop unrolling) для уменьшения накладных расходов цикла.
  2. Минимизация предсказаний ветвлений.
  3. Комбинирование инициализации и обработки.
  4. Использование умножения для условного суммирования.

Скомпилируйте и запустите программы с флагами оптимизации:

## Compile with basic optimization
gcc -O2 loop_optimization.c -o loop_optimization
./loop_optimization

## Compile with advanced optimization
gcc -O3 loop_optimization.c -o loop_optimization
./loop_optimization

Дополнительные советы по оптимизации:

  • Используйте флаги компилятора -O2 или -O3.
  • Минимизируйте вызовы функций внутри циклов.
  • Используйте подходящие типы данных.
  • Избегайте ненужных вычислений.
  • Рассмотрите возможность перемещения инвариантного кода цикла.

Резюме

В этом практическом занятии вы узнаете основы циклов while в программировании на языке C, в том числе, как использовать директивы break и continue для управления потоком выполнения цикла. Вы также изучите техники фильтрации элементов массива с использованием условных операторов и оптимизации эффективности циклов с помощью различных директив. К концу этого практического занятия вы получите твердую базу знаний о том, как реализовывать условные циклы на языке C для решения различных задач программирования.