Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Программирование на языке Си

..pdf
Скачиваний:
15
Добавлен:
12.11.2023
Размер:
17.16 Mб
Скачать

122'

Программирование на языке Си

файле stdlib.h, который включается в начало текста программы препроцессорной директивой.

Пример результатов выполнения программы:

Сторона а=2.О Сторона Ь=3.О Сторона с=4.О

Площадь треугольника: 2.904737

Скалярное произведение векторов. Выше была определена функция Scalar_Product() для вычисления скалярного произве­ дения векторов, в которой параметрами являлись массивы. Следующая программа использует эту функцию:

/* Скалярное произведение векторов */ #include <stdio.h>

#define MAX_INDEX 5 void main( )

{

/* Прототип функции: */

float Scalar_Product(int, float[ ], float[ ]); int n,i;

float x[MAX_INDEX] ,y[MAX_INDEX] ; printf("\n Размерность векторов n= "); scanf("%d",&n);

if(n < 1 || n >MAX_INDEX)

{

printf("\n Ошибка в данных!"); return; /* Аварийное завершение */

)

printf("Введите %d координ. х: ",п); for (i=0; i<n; i++)

scanf("%f",&x[i]); printf("Введите %d координ. у: ",n); for (i=0; i<n; i++)

scanf("%f",&y[i]); printf("\n Результат: %7.3f", Scalar_Product(n,x ,у ));

)

/* Определение функции scalar: */

float Scalar_Product(int n, float a[],float b[]) /* Скалярное произведение n-мерных векторов */

Глава 2. Введение в программирование на языке Си

123

/*

п - размерность пространства векторов */

/*

а[ ],Ь[

] - массивы координат векторов */

{ int i ;

 

/* Параметр цикла */

 

double z;

/*

Формируемая сумма

*/

 

for (i=0,z=0.0;

i < n; i++)

 

 

z += a[i]*b[i];

 

)

return z;

/* Возвращаемый результат

*/

 

 

 

 

В начале программы с помощью ^define введена препроцессорная константа MAX_INDEX. Далее определены массивы, у которых пределы изменения индексов заданы на препроцессорном уровне. Именно эти пределы проверяются после ввода размерности векторов (п). В теле функции m ain() приведен прототип функции Scalar_Product(). Обратите внимание, что в прототипе отсутствуют имена формальных параметров. Тот факт, что два параметра являются одномерными массивами, отображен спецификацией float[].

Результаты выполнения программы:

Размерность векторов п=2 Введите 2 координ. х : 1 3.1 Введите 2 координ. у : 1 2.1 Результат: 7.510

Другая попытка выполнить программу:

Размерность векторов п=0 Ошибка в данных!

Диаметр множества точек. Как еще один пример использо­ вания функций с массивами в качестве параметров рассмотрим программу определения диаметра множества точек в многомер­ ном евклидовом пространстве. Напомним, что диаметром назы­ вается максимальное расстояние между точками множества, а расстояние в евклидовом пространстве между точками дс={ г, } ;

У ={у ( } i=l,...,n, определяется как

124

Программирование на языке Си

Введем

ограничения на размерность

пространства:

N_MAX<=10 и количество точек К_МАХ<=100. Текст про­ граммы может быть таким:

#±nclude <stdio.h>

#include <math.h> /* для функции sqrt( ) */ /* Функция для вычисления

расстояния между двумя точками */

float distance(float х[ ], float у[ ], int n)

{

int i ;

float r,s=0.0; for(i=0;i<n;i++)

{

r=y[i]-x[i]; s+=r*r;

}

s=sqrt(s); return s;

}

#define K_MAX 100 #define N_MAX 10 void main( )

{

float dist, dist_max,d;

int i , j , ijnax, m_max, n , k , m ; float a[K_MAX][N_MAX];

/* a[][] - Массив фиксированных размеров */ while(1)

{

printf("\n Количество точек k="); scanf("%d", &k);

printf("Размерность пространства n="); scanf("%d", &n);

if(k>0 && k<=K_MAX && n>0 && n<=N_MAX) break; printf("ОШИБКА В ДАННЫХ!");

}

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

{/* Никл ввода координат точек */ printf("Введите %d координ. "

"точки %d:\n",n,i+l); for(j=0;j<n;j++)

/* Цикл ввода координат одной точки */

Глава 2. Введение в программирование на языке Си

125

scanf("%f",&a[i][j]);

}

dist_max=0.0; i_max=0;

m_max=0; for(i=0;i<k-l;i++)

{/* Цикл сравнения точек */ for(m=i+l;m<k;m++)

{

dist=distance(a[i],a[m],n); if(dist>dist_max)

{

dist_max=dist; i_max=i;

m_max=m;

}

>

} /* Конец цикла no i */ printf("Результат:\nflnaMeTp=%f",dist_max); printf("\n Номера точек : %d,%d",

i_max+l,m_max+l);

}

Результаты выполнения программы:

Количество

точек к=4

п=3

Размерность

пространства

Введите

3

координ. точки 1:

1

1

1

 

 

Введите

3

координ .- точки 2:

-1

-1

 

 

-1

 

Введите

3

координ. точки 3:

2

2

3

 

2

4:

Введите

координ. точки

- 2

- 2

 

 

- 2

 

Результат: Диаметр = 6.928203 Номера точек: 3, 4

В программе особый интерес представляет обращение к функции distance( ), где в качестве фактических параметров ис­ пользуются индексированные элементы a[i], а[ш]. Каждый из них по определению есть одномерный массив из п элементов,

126

Программирование на языке Си

что и учитывается в теле функции. Для задания размеров масси­ ва а[ ][] и предельных значений переменных к и п используются препроцессорные константы К_МАХ и N_MAX. Их нельзя оп­ ределить как переменные, т.е. ошибочной будет последователь­ ность:

int К_МАХ=100; N_MAX=10; float а[К MAX][N_MAX];

При определении массивов их размеры можно задавать толь­ ко с помощью константных выражений.

2.6. П ереклю чатели

Основным средством для организации мультиветвления слу­ жит оператор-переключатель, формат которого имеет вид:

switch{выражение)

{case константа!: операторы_1; case константа2: операторы_2;

default: операторы,-

}

В этом операторе используются три служебных слова: switch, case, default. Первое из них идентифицирует собственно оператор-переключатель. Служебное слово case с последующей константой является в некотором смысле меткой. Константы могут быть целыми или символьными и все должны быть раз­ личными (чтобы метки были различимы). Служебное слово default также обозначает отдельную метку. При выполнении оператора (рис. 2.6, а) вычисляется выражение, записанное по­ сле switch, и его значение последовательно сравнивается с кон­ стантами, которые помещены вслед за case. При первом же совпадении выполняются операторы, помеченные данной мет­ кой. Если выполненные операторы не предусматривают какоголибо перехода (т.е. среди них нет ни goto, ни return, ни exit( ), ни break), то далее выполняются операторы всех следующих

Глава 2. Введение в программирование на языке Си

127

вариантов, пока не появится оператор перехода или не закон­ чится переключатель.

Операторы вслед за default выполняются, если значение вы­ ражения в скобках после switch не совпало ни с одной констан­ той после case. Метка default может в переключателе отсутствовать. В этом случае при несовпадений значения выра­ жения с константами переключатель не выполняет никаких дей­ ствий. Операторы, помеченные меткой default, не обязательно находятся в конце (после других вариантов переключателя). Уточним, что default и "case константа" не являются метками в обычном смысле. К ним, например, нельзя перейти с помощью оператора goto.

На рис. 2.6 приведены схемы переключателя (рис. 2.6, а) и оператора альтернативного выбора или селектора (рис. 2.6 , б), отсутствующего в языке Си.

Рис. 2.6. Переключатель (а) и альтернативный выбор (б): а - если выражение равно МК, то выполняются операторы

Sк , Sк+1- . S„,S;

б - если выражение равно LK, то выполняются только операторы S

128

Программирование на языке Си

На рис. 2.7 изображена схема альтернативного выбора, реа­ лизованная при помощи переключателя и дополнительных опе­ раторов, введенных в Sb S2, ..., Sn .

Рис. 2.7. Альтернативный выбор с использованием переключателя. В число операторов каждой группы Sfc добавлен оператор

выхода из переключателя

Для иллюстрации работы переключателя рассмотрим про­ грамму, которая читает любую десятичную цифру и выводит на экран ее название:

Глава 2. Введение в программирование на языке Си

129

#include <stdio.h> void main( )

{

int i; while(1)

{

printf("\n Введите десятичную цифру: "); scanf("%d",&i);

printf("\t\t"); switch( i )

{

case 1: printf("%d -один \n",i); break;

case 2: printf("%d - два \ц” ,i); break;

case 3: printf("%d - три \n",i); break;

case 4: printf("%d - четыре \n",i); break; .

case 5: printf("%d - пять \n",i); break;

case 6: printf("%d - шесть \n",i); break;

case 7: printf("%d - семь \n",i); break;

case 8: printf("%d - восемь \n",i); break;

case 9: printf("%d - девять \n",i); break;

case 0: printf("%d - нуль \n",i); break;

default: printf("%d - это не цифра! \n",i); return;

}/* Конец переключателя */

}/* Конец цикла */

}

Пример результатов выполнения программы:

Введите десятичную цифру: 3

3 - три Введите десятичную цифру: 8

8 - восемь

g - S ’24

130

Программирование на языке Си

Введите десятичную цифру:

-7

-7 - это

не цифра!

Программа прекращает выполнение, как только будет введен символ, отличный от цифры. Завершение программы обеспечи­ вает оператор return; который в данном случае передает управ­ ление операционной системе, так как выполняет выход из функции m ain().

Переключатель вместе с набором операторов break реализу­ ет в этой программе альтернативный выбор (см. рис. 2.7). Если удалить все операторы break, то работа переключателя в этой программе будет соответствовать схеме рис. 2.6, а.

Несколько "меток" case с разными значениями констант мо­ гут помечать один оператор внутри переключателя, что позво­ ляет еще больше разнообразить схемы построения операторов switch.

Глава 3

ПРЕПРОЦЕССОРНЫЕ СРЕДСТВА

В предыдущих главах мы познакомились с некоторыми базо­ выми понятиями и основными средствами (может быть, не са­ мыми эффективными) программирования языка Си. Начиная с данной главы, начнем подробное изучение тех особенностей и возможностей, которыми Си отличается от других языков про­ граммирования и которые принесли ему заслуженную популяр­ ность и любовь профессиональных программистов.

Несколько нетрадиционно для пособий по языку Си начнем дальнейшее изложение материала с возможностей препроцессо­ ра. Это позволит в следующих главах продемонстрировать эф­ фективность препроцессорных средств и их применимость при решении разнородных задач. Откладывать, как часто принято, изучение препроцессора на конец курса по языку Си, по нашему мнению, не совсем удачно. Даже в начальных (вступительных) главах 1 и 2 пришлось затронуть некоторые важные вопросы препроцессорной обработки. Введены константы, определяемые директивой ^define, проиллюстрированы некоторые правила включения в программу текстов заголовочных файлов для связи со стандартной библиотекой компилятора. Этих сведений впол­ не достаточно, чтобы программировать на языке Си, вводить с помощью ^define собственные обозначения констант и не ис­ пытывать затруднений в использовании стандартных библиотек.

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

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

9

Соседние файлы в папке книги