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

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

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

БИЛЕТ №7.

ТЕОРЕТИЧЕСКИЙ ВОПРОС: ПОДПРОГРАММЫ, ПРАВИЛА ПЕРЕДАЧИ ПАРАМЕТРОВ.

ПОДПРОГРАММЫ В СИ Функция — это самостоятельная единица программы, которая спроектирована для реализации конкретной

подзадачи.

Подпрограмма — поименованная или иным образом идентифицированная часть компьютерной программы, содержащая описание определённого набора действий. Подпрограмма может быть многократно вызвана из разных частей программы.

Функция является подпрограммой, которая может содержаться в основной программе, а может быть создана отдельно (в библиотеке). Каждая функция выполняет в программе определенные действия.

«Процедуры» в СИ — функции, не возвращающие значение (тип — void, что переводится как «пустота»).

Функция

1.Описание функции (сигнатура/прототип функции) определяет правила использования функции.

Описание необязательно, если стоит перед функцией main().

<type> <name> (<parameters>);

Пример: int max (int, int);

2.Определение функции (семантика функции) представляет собой описание инструкций, выполняемых функцией (тело функции).

<type> <name> (<parameters>) {<body>}

Пример:

int max (int a, int b) { return (a > b) ? a : b;

}

3.Вызов функции.

<name>(<parameters>);

Пример: max(4, 5); /// 5

ФАКТИЧЕСКИЕ И ФОРМАЛЬНЫЕ ПАРАМЕТРЫ Фактические параметры — параметры, указываемые при вызове подпрограммы. Формальные параметры — параметры, указываемые при описании подпрограммы.

Т. е. фактические параметры — те, что передаются в функцию, а формальные параметры — те, что находятся в описании (заголовке) функции.

Список фактических параметров подпрограммы должен совпадать по количеству и типам со списком формальных параметров.

ПЕРЕДАЧА ПАРАМЕТРОВ В ФУНКЦИЮ

В языке СИ точного разделения на параметры-значения и параметры-переменные нет (в ЯП Pascal

есть разделение).

Однако знать, что это и как это понимается в языке СИ, надо.

Параметры-значения используются только для передачи (копирования) в функцию исходных данных из основной программы.

Параметры-переменные используются для того, чтобы изменять исходные данные основной программы в функции.

Различные способы передачи параметров в СИ позволяют организовать и тот, и другой тип передачи, но в немного другом понимании.

Передача параметров в функцию

Передача по значению

Передача по указателю

Передача по ссылке

(C, C++)

(C, C++)

(только C++)

 

 

 

 

#include <stdio.h>

#include <cstdio> /// аналог <stdio.h>

#include <stdio.h>

void swap (int *a, int *b){

void swap (int &a, int &b){

int c;

int c;

int max (int a, int b){

c = *a; /// но не c = a!

c = a;

return (a > b) ? a : b;

*a = *b; /// но не a = b!

a = b;

}

*b = c; /// но не b = c!

b = c;

int main()

}

}

{

int main()

int main()

int a = 3, b = 5, c;

{

{

c = max(a, b);

int a = 3, b = 5;

int a = 3, b = 5;

/// Максимум

swap(&a, &b);

swap(a, b);

printf("max: %d\n", c);

/// Меняем местами

/// Тоже меняем местами

return 0;

printf("%d %d\n", a, b);

printf("%d %d\n", a, b);

}

return 0;

return 0;

 

 

}

}

Следует знать то, что в СИ имя массива без индекса обозначает указатель на первый (нулевой по

индексу) элемент этого массива.

 

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

СИ

#include <stdio.h>

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

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

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

void bilet7(double *arr, int n, int m){ int i; double d;

int wm1 = m - 1; int wm2 = m - 2; for (i = 0; i < n; i++){

d = arr[i*m + wm1];

arr[i*m + wm1] = arr[i*m + wm2]; arr[i*m + wm2] = d;

}

}

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 x 4 (3 строки, 4 столбца) bilet7(&arr[0][0], 3, 4); /// Обработка

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

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

}

return 0;

}

БИЛЕТ №8.

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

СТАТИЧЕСКИЕ И АВТОМАТИЧЕСКИЕ ПЕРЕМЕННЫЕ

static. Статические переменные — это локальные переменные, которые создаются при первом входе в подпрограмму и не уничтожаются при выходе из неё.

Статическая переменная, описанная вне любой функции, становится внешней статической. Разница между внешней переменной и внешней статической переменной заключается в области их действия. Обычная внешняя переменная может использоваться функциями в любом файле, а внешняя статическая переменная может использоваться только функциями того файла, в котором объявлена, причем после определения переменной.

auto. Автоматические переменные — это локальные переменные, которые создаются каждый раз при входе в подпрограмму и уничтожаются при выходе из неё.

Обратите внимание на то, что все создаваемые переменные по умолчанию — автоматические.

Статические переменные

 

Автоматические переменные

static

 

auto

#include <stdio.h>

 

#include <stdio.h>

int main()

 

int main()

{

 

{

int i;

 

int i;

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

 

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

static int n = 0;

 

int n = 0; /// то же, что и "auto int n = 0"

printf("%d ", ++n); /// 1 2 3 4 5

 

printf("%d ", ++n); /// 1 1 1 1 1

}

 

}

return 0;

 

return 0;

}

 

}

 

КОНСТАНТЫ

1.Ключевое слово const.

Использование: const <type> <name> = <value>;

2.Директива препроцессора #define.

Использование: #define <name> <value>

Преимущества использования const:

Явное указание типа величины.

Имеется возможность создавать константы с различной областью видимости.

 

const

 

#define

#include <stdio.h>

#include <stdio.h>

int main()

 

#define n 5

 

{

 

int main()

 

int i;

 

{

 

const int n = 5;

int i;

 

for (i

= 1; i <= n; i++) {

for (i

= 1; i <= n; i++) {

printf("%d ", i); /// 1 2 3 4 5

printf("%d ", i); /// 1 2 3 4 5

}

 

}

 

return

0;

return

0;

}

 

}

 

ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ

Глобальные объекты — объекты, объявление которых дано вне функции (вне main и других). Они доступны (видимы) во всем файле, в котором они объявлены. В течение всего времени выполнения программы с глобальным объектом ассоциирована некоторая ячейка памяти. Например, можно объявить int a = 4; вне функции main.

Локальные объекты — объекты, объявление которых дано внутри блока или функции. Эти объекты доступны только внутри того блока, в котором они объявлены. Объектам с локальным временем жизни выделяется новая ячейка памяти каждый раз при осуществлении описания внутри блока. Когда выполнение блока завершается, память, выделенная под локальный объект, освобождается, и объект теряет своё значение.

Модификатор extern предназначен для использования в одном программном модуле объекта, который объявлен в другом программном модуле. Пример работы модификатора приведен в 17 билете.

Модификатор register предназначен для того, чтобы поместить переменную в один из регистров общего назначения центрального процессора при наличии свободного регистра. Благодаря этому повышается скорость

работы с данными, однако получить адрес такой переменной не получится, так как она хранится не в оперативной памяти (ОЗУ), а в регистре процессора (ЦП). Это необходимо для создания управляющих

программ, где требуется высокая скорость обработки данных. Пример: register int a = 4. Дальше работаем почти как с обычной переменной.

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

СИ

#include <stdio.h>

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

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

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

double bilet8(double *arr, int n){ int i, wn = n - 2;

double sum = arr[0]; /// Первый элемент for (i = 2; i < wn; i++)

sum += arr[i]; /// Между вторым и предпоследним sum += arr[n-1]; /// Последний элемент

return sum;

}

int main()

{

double arr[7] = {-1.5, 3.9, 4.2, 0.3, 1.5, 41.0, 6.1}; /// 7 элементов printf("%lf\n", bilet8(arr, 7)); /// 10.600000

return 0;

}

БИЛЕТ №9.

ТЕОРЕТИЧЕСКИЙ ВОПРОС: ОПЕРАТОРЫ RETURN, BREAK, CONTINUE.

ОПЕРАТОР RETURN

Оператор return (возврат) завершает выполнение функции, в которой он задан, и возвращает управление в вызывающую функцию, в точку, непосредственно следующую за вызовом.

ОПЕРАТОР BREAK

Оператор break (разрыв) вызывает немедленный выход из циклов, организуемых с помощью операторов for, while, do-while, а также прекращение оператора switch.

ОПЕРАТОР CONTINUE

Оператор continue (продолжить) тоже предназначен для прерывания циклического процесса, организуемого операторами for, while, do-while. Но в отличии от оператора break, он не прекращает дальнейшее выполнение цикла, а только немедленно переходит к следующей итерации того цикла, в теле которого он оказался.

ПРИМЕРЫ

 

return

break

continue

#include <stdio.h>

#include <stdio.h>

#include <stdio.h>

int main()

 

int main()

int main()

{

 

{

{

int i;

 

int i;

int i;

for (i

= 1; i <= 10; i++) {

for (i = 1; i <= 10; i++) {

for (i = 1; i <= 10; i++) {

printf("%d ", i);

printf("%d ", i);

if (i % 5 == 0)

/// 1 2 3 4 5

/// 1 2 3 4 5

continue;

if

(i % 5 == 0)

if (i % 5 == 0)

printf("%d ", i);

 

return 0;

break;

/// 1 2 3 4 6 7 8 9

}

 

}

}

printf("I = %d", i);

printf("I = %d", i);

printf("I = %d", i);

/// не

выведется

/// I = 5

/// I = 11

return

0;

return 0;

return 0;

}

 

}

}

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

СИ

#include <stdio.h>

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

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

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

double bilet9(double *arr, int n){ int i, wn = n - 6;

double p = arr[n-1]; /// Последний элемент for (i = n - 2; i > wn; i--)

p *= arr[i]; return p;

}

int main()

{

double arr[7] = {-1.5, 3.0, 2.0, 2.0, 2.0, 2.0, 2.0}; /// 7 элементов printf("%lf\n", bilet9(arr, 7)); /// 32.000000

return 0;

}

БИЛЕТ №10.

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

МАССИВ Массив — это непрерывный участок памяти, содержащий последовательность объектов одинакового типа,

обозначаемый одним именем.

<type> <name> [<dimension>] = {<value1>, <value2>…}; // (dimension — размерность)

Указывать размерность необязательно, если указаны значения <value> в фигурных скобках. Указать размерность необходимо, если значения <value> в скобках не указаны.

Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.

Каждый элемент массива характеризуется:

Адресом элемента — адресом начальной ячейки памяти, в которой расположен этот элемент;

Индексом элемента (порядковым номером элемента в массиве);

Значением элемента.

Адрес массива — адрес начального элемента массива.

Имя массива — идентификатор, используемый для обращения к элементам массива. Размер массива — количество элементов массива.

Размер элемента — количество байт, занимаемых одним элементом массива.

ПЕРЕДАЧА МАССИВА В ФУНКЦИЮ. ВВОД ДАННЫХ, ОБРАБОТКА ДАННЫХ, ВЫВОД ДАННЫХ

Главная функция

Ввод данных

#define N 5

 

int main()

 

{

void input_array(int * arr, int n){

int arr[N];

int i;

input_array(arr, N);

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

array_processing(arr, N);

scanf("%d", &arr[i]);

output_array(arr, N);

}

return 0;

 

}