В Си возможны функции с переменным числом параметров. Примером таких функций являются библиотечные функции printf() и scanf()

Рекурсивные определения функций. В языках Си/Си++ допускается рекурсивное определение функций. Проиллюстрируем определение рекурсивной функции на классическом примере вычисления факториала целого положительного числа.

long Factor(int n)

{ if (n<0) return 0;

if (n==0) return 1;

return n*Factor(n-1);

}

В случае если при вызове функции будет задан отрицательный аргумент, то функция вернет нулевое значение – признак неверного обращения.

Классы памяти.Под всякую переменную, используемую в программе, должно быть выделено место в памяти ЭВМ. Выделение памяти может происходить либо на стадии компиляции (компоновки) программы, либо во время ее выполнения. Существуют 4 класса памяти, выделяемой под переменные:

- автоматическая (ключевое слово auto),

- внешняя (extern),

- статическая (static),

- регистровая (register).

Под глобальные переменные выделяется место во внешней памяти (не нужно думать, что речь идет о магнитной памяти; это оперативная память класса extern). Глобальную переменную можно объявить либо вне программных блоков, либо внутри блока с ключевым словом exter. Обычно это делается в тех случаях, когда программный модуль хранится в отдельном файле и, следовательно, отдельно компилируется.

Пусть, например, основная и вспомогательная функции хранятся в разных файлах:

Пример 3.

Файл 1:Файл 2:

…….

int var void func()

void main() { extern int var;

{var=5; var=10*var;

func(); }

cout<<var;

}

Здесь обмен значениями между основной и вспомогательной функцией func() происходит через общую глобальную переменную var, для которой во время компиляции выделяется место во внешнем разделе памяти. В результате выполнения данной программы на экран выведется число 50.

Локальные переменные, объявленные внутри блоков, распределяются в автоматической памяти, работающей по принципу стека. Выделение памяти происходит при входе выполнения программы в блок, а при выходе из блока память освобождается. Ключевое слово auto писать не обязательно (подразумевается по умолчанию).

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

f()

{static int schet=10; …}

Инициализация статической переменной происходит только при первом вхождении в блок. Если инициализация явно не указана, то переменной автоматически присваивается нулевое начальное значение. Статические переменные можно использовать, например, для организации счетчика числа вхождений в блок.

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

Наконец, рассмотрим пример, в котором используются различные способы описания переменных.

Пример 4.

int var //описана внешняя переменная var

main()

{extern int var; // та же внешняя переменная var

}

func1()

{extern int var1;//новая внешняя переменная var1

… //внешняя var здесь также видна

}

func2()

{… //здесь переменная var видна, а переменная

} // var1 – не видна

int var1; //Глобально описана переменная var1

func3()

{ int var; //здесь var – локальная переменная,

… //видна внешняя переменная var1

}

func4()

{auto int var1; //здесь var1 – локальная переменная,

… //видна внешняя глобальная var

Упражнения

1. Определить результат выполнения программы:

#include <iostream.h>

void mul(int, int);

int S;

void main()

{int a=2, b=3;

mul(a,b); a=2*S; mul(a,b);

cout<<S;

}

void mul(int x, int y)

{S=x*y;}

2. Составить функцию, определяющую, является ли ее целый аргумент простым числом. Использовать эту функцию для подсчета количества простых чисел в последовательности из десяти целых чисел, вводимых с клавиатуры.

3. Даны натуральные числа n и m; найти НОД(n,m). Составить рекурсивную функцию вычисления НОД, основанную на соотношении НОД(n, m) = НОД(m, r), где r –– остаток от деления n на m (n>m).

Массивы

Массивы - это группа элементов одинакового типа (double, float, int и т.п.). Из объявления массива компилятор должен получить информацию о типе элементов массива и их количестве.

Формат описания массива следующий:

<тип_элементов> <имя> [<константное_выражение>]

Константное выражение определяет размер массива, т.е. число элементов этого массива. Например, согласно описанию

int a[100];

char b[20];

float d[50];

В первой строке объявлен массив а из 100 элементов целого типа: а[0], а[1], ..., а[99] (индексация всегда начинается с нуля). Во второй строке элементы массива b имеют тип char, а в третьей - float.. Имя массива — константа указатель.

Размер массива может явно не указываться, если при его объявлении производится инициализация значений элементов. Например:

int p[]={2, 4, 6, 10, 1};

В этом случае создается массив из пяти элементов со следующими значениями:

p[0]=2, p[1]=4, p[2]=6, p[3]=10, p[4]=1.

Количество элементов в массиве в этом случае можно определить так:

n=sizeof(p)/sizeof(int);

В результате следующего объявления массива

int M[6]={5, 3, 2};

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

Пример 1. Сортировка массива методом пузырька.

//Сортировка массива

#include <iostream.h>

#include<conio.h>

void main()

{ int X[]={6,4,9,3,2,1,5,7,8,10};

int i=0,j,n,A,P=1;

clrscr();

n=sizeof(X)/sizeof(X[0]);

while (P)

{ P=0;

for(j=0; j<n-1-i; j++)

if(X[j]>X[j+1]) {A=X[j]; X[j]=X[j+1]; X[j+1]=A; P=0}

i++;

}

for(i=0; i<n; i++) cout<<X[i]<<" ";

}

В результате выполнения этой программы на экран выведется упорядоченная числовая последовательность:

1 2 3 4 5 6 7 8 9 10.

Чтобы сделать программу универсальной по отношению к размеру массива, память под массив можно выделять динамически.

Пример 2.

//Сортировка массива, вариант 2

#include <stdlib.h>

#include <stdio.h>

Void main()

{int *X;

int i=0,j,n,A,P=1;

clrscr();

printf("\n n-?"); scanf("%d",&n);//количество элементов

// выделение динамической памяти

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

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

{ printf("%d:",i); scanf("%f",&X[i]);}

while (P)//сортировка

{ P=0;

for(j=0; j<n-1-i; j++)

if(X[j]>X[j+1]) {A=X[j]; X[j]=X[j+1]; X[j+1]=A; P=0}

i++;

}

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

printf("%6d ",X[i]);

Наши рекомендации