Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на языке Си. Билеты и ответы

.pdf
Скачиваний:
317
Добавлен:
10.09.2019
Размер:
761.78 Кб
Скачать

Обработка данных

Вывод данных

void array_processing(int * arr, int n){

void output_array(int * arr, int n){

int i;

int i;

for (i = 0; i < n; i++)

for (i = 0; i < n; i++)

arr[i] = arr[i] * arr[i];

printf("%d ", arr[i]);

}

}

 

 

Вместо int * arr можно было бы написать int arr[5], что ввело бы ограничение на размер (5 элементов).

ЗАДАЧА: НАПИСАТЬ ФУНКЦИЮ, ВОЗВРАЩАЮЩУЮ ЧИСЛО ЭЛЕМЕНТОВ ОДНОМЕРНОГО МАССИВА, КРАТНЫХ 3. ПРОДЕМОНСТРИРОВАТЬ ЕЁ ИСПОЛЬЗОВАНИЕ В ПРОГРАММЕ.

СИ

#include <stdio.h>

///Функция, возвращающая число элементов одномерного массива, кратных 3

///arr — массив, n — количество строк в массиве

///Сложность алгоритма: T(n) = O(n)

int bilet10(int *arr, int n){ int i, k = 0;

for (i = 0; i < n; i++)

if ((arr[i] % 3) == 0) /// Если число кратно 3 k++; /// Увеличиваем счетчик

return k;

}

int main() {

int arr[5] = {-1, 3, 4, -9, -6}; /// Массив из 5 элементов printf("%d\n", bilet10(arr, 5)); /// 3

return 0;

}

БИЛЕТ №11.

ТЕОРЕТИЧЕСКИЙ ВОПРОС: ОБРАБОТКА ДВУМЕРНЫХ МАССИВОВ.

Двумерный массив — это массив одномерных массивов, последовательно расположенных в памяти. Двумерный массив представляет собой матрицу размером n (строк) на m (столбцов).

Далее представлены способы работы со статическим массивом в функции.

Способы работы с двумерным статическим массивом в функции (ввод, обработка, вывод)

СТАТИЧЕСКИЙ МАССИВ: int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

Первый способ передачи

Второй способ передачи

(с указанием кол-ва строк и длины строки)

(только с указанием длины строки)

func(arr); /// 2-й и 3-й параметры известны

func(arr, 3); /// 3-й параметр уже известен

void func(int arr[3][3]){

void func(int arr[][3], int n){

int i, j;

int i, j;

for (i = 0; i < 3; i++) {

for (i = 0; i < n; i++) {

for (j = 0; j < 3; j++)

for (j = 0; j < 3; j++)

printf("%d ", arr[i][j]);

printf("%d ", arr[i][j]);

/// ввод: scanf("%d", &arr[i][j]);

/// ввод: scanf("%d", &arr[i][j]);

printf("\n");

printf("\n");

}

}

arr[2][2] = 0; /// Изменит элемент массива

arr[2][2] = 0; /// Изменит элемент массива

}

}

Простой подход

Простой подход

Имеются ограничения на кол-во строк и длину

Имеется ограничение на длину строки

строки

 

Третий способ передачи

Четвертый способ передачи

(в начале — кол-во строк и длина каждой строки)

(работаем как с одномерным массивом)

 

 

func(3, 3, arr);

func(&arr[0][0], 3, 3)

void func(int n, int m, int arr[n][m]){

/// int arr[] можно заменить на int *arr

void func(int arr[], int n, int m){

int i, j;

int i, j;

for (i = 0; i < n; i++) {

for (i = 0; i < n; i++) {

for (j = 0; j < m; j++)

for (j = 0; j < m; j++)

printf("%d ", arr[i][j]);

printf("%d ", arr[i * m + j]);

/// ввод: scanf("%d", &arr[i][j]);

/// ввод: scanf("%d", &arr[i * m + j]);

printf("\n");

printf("\n");

}

}

arr[2][2] = 0; /// Изменит элемент массива

arr[2 * m + 2] = 0; /// Изменит элемент массива

}

}

 

Нестандартный подход

Арифметический подход

Имеется универсальность

Имеется универсальность

 

 

Универсальный способ работы с двумерным динамическим массивом в функции

ДИНАМИЧЕСКИЙ МАССИВ:

///n — количество строк, m — количество столбцов int **arr = (int **)malloc(n * sizeof(int *)); for (i = 0; i < n; i++)

arr[i] = (int *)malloc(m * sizeof(int));

func(arr, n, m)

///int **arr можно заменить на int *arr[]

void func(int **arr, int n, int m){ int i, j;

for (i = 0; i < n; i++) { for (j = 0; j < m; j++)

printf("%d ", arr[i][j]);

/// ввод: scanf("%d", &arr[i][j]); printf("\n");

}

arr[2][2] = 0; /// Изменит элемент массива

}

В конце не забываем освобождать выделенную память функцией free()

Возможно, есть и другие способы работы с двумерными массивами, но мы разобрали основные.

ЗАДАЧА: НАПИСАТЬ ФУНКЦИЮ, МЕНЯЮЩУЮ МЕСТАМИ УКАЗАННЫЕ В КАЧЕСТВЕ ПАРАМЕТРОВ СТРОКИ ДВУМЕРНОГО МАССИВА. ПРОДЕМОНСТРИРОВАТЬ ЕЁ ИСПОЛЬЗОВАНИЕ В ПРОГРАММЕ.

СИ

#include <stdio.h>

///Функция, меняющая местами указанные в качестве параметров строки двумерного массива

///arr — массив, m — длина строки, xn и xk — индексы строк массива

///Сложность алгоритма: T(n) = O(n)

void bilet11(char *arr, int m, int xn, int xk){ int i; char ch;

for (i = 0; i < m; i++){ ch = arr[xn*m + i];

arr[xn*m + i] = arr[xk*m + i]; arr[xk*m + i] = ch;

}

}

int main()

{

int i, j;

/// 4 строки с 6-тью символами

char arr[4][6] = {{"str_1"}, {"str_2"}, {"str_3"}, {"str_4"}};

///6-ой символ — \0 bilet11(&arr[0][0], 6, 1, 3); for (i = 0; i < 4; i++) {

for (j = 0; j < 5; j++) printf("%c", arr[i][j]);

printf(" ");

}

///В результате: str_1 str_4 str_3 str_2 return 0;

}

БИЛЕТ №12.

ТЕОРЕТИЧЕСКИЙ ВОПРОС: УКАЗАТЕЛИ, РАБОТА С ДИНАМИЧЕСКОЙ ПАМЯТЬЮ.

УКАЗАТЕЛЬ Указатель — переменная, содержащая адрес объекта. Указатель не несет информации о содержимом объекта,

а содержит сведения о том, где размещен объект.

Указатель — это переменная, которая размещается в памяти. Она имеет адрес, а ее значение является адресом некоторой другой переменной. Переменная, объявленная как указатель, занимает 4 байта в оперативной памяти (в случае 32-битной версии компилятора).

Объявление указателя: <type> *<name> = <adress>;

Венгерская нотация. Имя <name> начинается с символа "p" (pointer — указатель). Пример: int *p1, *pN; Тип указателя — это тип переменной, адрес которой он содержит.

Для работы с указателями в Си определены две операции:

Операция * (звездочка) — позволяет получить значение объекта по его адресу — определяет значение переменной, которое содержится по адресу, содержащемуся в указателе;

Операция & (амперсанд) — позволяет определить адрес переменной.

Пример

#include <stdio.h> int main()

{

int i = 0; /// простая переменная

int *p = NULL; /// ни на что не указывает p = &i; /// значение p — адрес i

*p = 5; /// то, на что указывает теперь будет равно 5 printf("%d", i); /// 5

///Т. Е.:

///при изменении *p на самом деле происходит изменение i

///при изменении p происходит изменение значения p return 0;

}

РАБОТА С ДИНАМИЧЕСКОЙ ПАМЯТЬЮ Заголовочный файл <stdlib.h>.

1.Функция void* malloc(size_t size) только выделяет память (блок памяти). Если память выделилась успешно, то функция возвращает указатель на первый байт (элемент), в противном случае возвращает нулевой указатель NULL.

2.Функция void* calloc(size_t num, size_t size) выделяет память (блок памяти) для массива из num объектов размера size, а также инициализирует все байты в выделенном хранилище нулями. Если память выделилась успешно, то функция возвращает указатель на первый байт (элемент), в противном случае возвращает нулевой указатель NULL.

3.Функция void* realloc(void *ptr, size_t new_size) расширяет (или сужает, или перераспределяет) ранее выделенный блок памяти.

a.Расширение или сжатие существующей области, на которую указывает ptr (если это возможно). Если область расширяется, содержимое новой части массива не определено.

b.Выделение нового блока памяти размером new_size байт, перемещение данных старого блока в новый и освобождение старого блока. Если памяти недостаточно, то старый блок памяти не освобождается и возвращается нулевой указатель NULL.

4.Функция void free(void *ptr) освобождает ранее выделенную память. Если ptr — нулевой указатель,

функция ничего не делает. При других вариантах возможно неопределенное поведение.

Если size равен нулю или new_size равен нулю, то поведение определяется реализацией (может быть возвращен нулевой указатель NULL).

Одномерный массив

Пример работы с malloc(), calloc(), realloc(), free()

#include <stdio.h>

#include <stdlib.h> /// для работы с malloc, calloc, realloc… const int N = 2;

int main()

{

///Объявление одномерного массива из N элементов

///При помощи функции malloc()

int *A = (int *)malloc( N * sizeof(int) );

/// При помощи функции calloc()

int *B = (int *)calloc( N, sizeof(int) );

/// Работа с элементами массива одинакова

A[0] = 1; A[1] = 2; printf("%d\n", A[1]); /// 2 B[0] = 1; B[1] = 2; printf("%d\n", B[1]); /// 2

///Увеличиваем размер массива A на 1 функцией realloc() A = (int *)realloc(A, (N + 1) * sizeof(int));

///Уменьшаем размер массива B на 1 функцией realloc() B = (int *)realloc(B, (N - 1) * sizeof(int));

///Снова работаем

A[2] = 3; printf("%d\n", A[2]); /// 3 B[0] = 0; printf("%d\n", B[0]); /// 0

/// Обязательно освобождаем память free(A);

free(B); return 0;

}

Двумерный массив

Пример работы с malloc(), calloc(), realloc(), free()

#include <stdio.h>

#include <stdlib.h> /// для работы с malloc, calloc, realloc… const int N = 2;

const int M = 3; int main()

{

int i;

///Объявление двумерного массива из N строк и M столбцов

///При помощи функции malloc()

int **A = (int **)malloc(

N * sizeof(int *) );

for (i = 0; i < N; i++)

 

 

A[i] = (int *)malloc(

M * sizeof(int) );

/// При помощи функции calloc()

int **B = (int **)calloc(

N,

sizeof(int *) );

for (i = 0; i < N; i++)

 

 

B[i] = (int *)calloc(

M,

sizeof(int) );

///Дальше работа как с двумерным массивом…

///A[0][0] = 3… B[0][0] = 4…

///Освобождение памяти для каждого столбца i-той строки for (i = 0; i < N; i++) {

free(A[i]); free(B[i]);

}

free(A); /// Освобождение памяти для строк free(B); /// Освобождение памяти для строк return 0;

}

ЗАДАЧА: НАПИСАТЬ ФУНКЦИЮ, МЕНЯЮЩУЮ МЕСТАМИ УКАЗАННЫЕ В КАЧЕСТВЕ ПАРАМЕТРОВ СТОЛБЦЫ ДВУМЕРНОГО МАССИВА. ПРОДЕМОНСТРИРОВАТЬ ЕЁ ИСПОЛЬЗОВАНИЕ В ПРОГРАММЕ.

СИ

#include <stdio.h>

///Функция, меняющая местами указанные в качестве параметров столбцы двумерного массива

///arr — массив, n — количество строк, m — количество столбцов,

///xn — индекс одного столбца, xk — индекс другого столбца

///Сложность алгоритма: T(n) = O(n)

void bilet12(double *arr, int n, int m, int xn, int xk){ int i; double k;

for (i = 0; i < n; i++){ /// Меняем местами столбцы, двигаясь по строкам k = arr[i*m + xn];

arr[i*m + xn] = arr[i*m + xk]; arr[i*m + xk] = k;

}

}

int main()

{

int i, j;

double arr[3][4] = {{-1.5, 3.9, 4.2, 41.0}, {-5.4, -1.0, 56.6, 42.2}, {-3.8, 1.9, 6.2, 96.8}};

/// Массив из 3 строк и 4 столбцов bilet12(&arr[0][0], 3, 4, 0, 2); /// Обработка for (i = 0; i < 3; i++) {

for (j = 0; j < 4; j++)

printf("%lf ", arr[i][j]); /// Вывод printf("\n");

}

return 0;

}