Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Раздел 1.doc
Скачиваний:
10
Добавлен:
22.08.2019
Размер:
266.24 Кб
Скачать

Пример: печать n первых простых чисел

Рассмотрим пример, использующий захват динамической памяти. Требуется ввести целое цисло n и напечатать n первых простых чисел. (Простое число - это число, у которого нет нетривиальных делителей.) Используем следующий алгоритм: последовательно проверяем все нечетные числа, начиная с тройки (двойку рассматриваем отдельно). Делим очередное число на все простые числа, найденные на предыдущих шагах алгоритма и не превосходящие квадратного корня из проверяемого числа. Если оно не делится ни на одно из этих простых чисел, то само является простым; оно печатается и добавляется в массив найденных простых.

Поскольку требуемое количество простых чисел n до начала работы программы неизвестно, невозможно создать массив для их хранения в статической памяти. Выход состоит в том, чтобы захватывать пространство под массив в динамической памяти уже после ввода числа n. Вот полный текст программы:

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

int main() {

int n; // Требуемое количество простых чисел

int k; // Текущее количество найденных простых чисел

int *a; // Указатель на массив найденных простых

int p; // Очередное проверяемое число

int r; // Целая часть квадратного корня из p

int i; // Индекс простого делителя

bool prime; // Признак простоты

printf("Введите число простых: ");

scanf("%d", &n);

if (n <= 0) // Некорректное значение =>

return 1; // завершаем работу с кодом ошибки

// Захватываем память под массив простых чисел

a = (int *) malloc(n * sizeof(int));

a[0] = 2; k = 1; // Добавляем двойку в массив

printf("%d ", a[0]); // и печатаем ее

p = 3;

while (k < n) {

// Проверяем число p на простоту

r = (int)( // Целая часть корня

sqrt((double) p) + 0.001

);

i = 0;

prime = true;

while (i < k && a[i] <= r) {

if (p % a[i] == 0) { // p делится на a[i]

prime = false; // => p не простое,

break; // выходим из цикла

}

++i; // К следующему простому делителю

}

if (prime) { // Если нашли простое число,

a[k] = p; // то добавляем его в массив

++k; // Увеличиваем число простых

printf("%d ", p); // Печатаем простое число

if (k % 5 == 0) { // Переход на новую строку

printf("\n"); // после каждых пяти чисел

}

}

p += 2; // К следующему нечетному числу

}

if (k % 5 != 0) {

printf("\n"); // Перевести строку

}

// Освобождаем динамическую память

free(a);

return 0;

}

8) Массивы. Определение. Примеры инициализации одно- и двух- мерных массивов.

Как известно, массив - это конечная совокупность данных одного типа. Можно говорить о массивах целых чисел, массивов символов и.т.д. Мы можем даже определить массив, элементы которого - массивы( массив массивов), определяя, таким образом, многомерные массивы. Любой массив в программе должен быть описан: после имени массива добавляют квадратные скобки [], внутри которых обычно стоит число, показывающее количество элементов массива. Например, запись int x[10]; определяет x как массив из 10 целых чисел. В случае многомерных массивов показывают столько пар скобок , какова размерность массива, а число внутри скобок показывает размер массива по данному измерению. Например, описание двумерного массива выглядит так: int a[2][5];. Такое описание можно трактовать как матрицу из 2 строк и 5 столбцов. Для обращения к некоторому элементу массива указывают его имя и индекс, заключенный в квадратные скобки(для многомерного массива - несколько индексов , заключенные в отдельные квадратные скобки): a[1][3], x[i] a[0][k+2]. Индексы массива в Си всегда начинаются с 0, а не с 1, т.е. описание int x[5]; порождает элементы x[0], x[1], x[2], x[3], x[4], x[5]. Индекс может быть не только целой константой или целой переменной, но и любым выражением целого типа. Переменная с индексами в программе используется наравне с простой переменной (например, в операторе присваивания, в функциях ввода- вывода). Начальные значения массивам в языке Си могут быть присвоены при компиляции только в том случае, если они объявлены с классом памяти extern или static, например:

         static int a[6]={5,0,4,-17,49,1};

обеспечивает присвоения a[0]=5; a[1]=0; a[2]=4 ... a[5]=1. Как видите, для начального присвоения значений некоторому массиву надо в описании поместить справа от знака = список инициирующих значений, заключенные в фигурные скобки и разделенные запятыми. Двумерный массив можно инициировать так:

     static int matr[2][5] = {{3,4,0,1,2},{6,5,1,4,9}};  

Матрица хранится в памяти построчно, т.е. самый правый индекс в наборе индексов массива меняется наиболее быстро.    Пусть, например, в заданном массиве из 10 целых чисел надо изменить порядок следования его элементов на обратный без привлечения вспомагательного массива. Соответствующая прорамма приведена на примере:

/*обращение массива*/ #include <stdio.h> main() { int p,i=0; static a[10]={10,11,12,13,14,    15,16,17,18,19}; while(i<10/2) { p=a[i]; a[i]=a[9-i]; a[9-i]=p; i++; } i=0; while(i<10)       printf(" %d",a[i++]); }