Структуры, вложенные друг в друга
Создаем прямоугольник, заданный координатами двух своих углов. Пусть pt1-левый верхний угол, pt2-правый нижний угол.
pt1 a
pt2
Найти размер стороны а.
struct rectangle
{struct point pt1;
struct point pt2;};
struct rectangle poly;
int r;
r=poly.pt2.x-poly.pt1.x;
Массивы структур
Пример 11.10
/*Список студентов с результатами экзаменов*/
# define KST 35
struct list
{char *fio; int r_l;
int math; int phys;};
struct list group[KST];
Элементам таблицы можно придать значение следующими способами:
· ввести поэлементно;
· присвоить поэлементно;
· инициализировать массив структур.
Второй вариант объявления таблицы:
struct list gr[]=
{{“Андреев”,5,5,5},
{“Большаков”,5,5,4},
…
{“Якишенко”,5,4,5}}:
11.8 Оператор sizeof.
В Си вычисление размера любого объекта
-) sizeof <обьект>;
-) sizeof(<имя_типа>);
Результат:целое,которое равно размеру в байтах указанного объекта или типа.
Объект:
-)массив;
-)структура.
Имя типа:
-)имя базового типа(int,char,float);
-)имя произвольного типа(структура и указатель).
#define kst (sizeof group) sizeof(struct list) или
#define kst(size group)sizeof(group[0])
11.9 Декларация typedef
Такя декларация позволяет давать новые имена типам данных
Синтаксис:
tupedef <старое имя типа> <новое имя типа>;
Использование:
<тип объявления в typedef> <список объектов>;
Внимание:typedef не создает новый тип,а только синоним для существуещего типа!!!
Пример 11.12
typedef int Exz;
typedef char*String;
typedef struct list
{ Sting fio;
Ekz math;
Ekz phys;
Ekz r_l;
} Liststud;
Liststud group[kst];
Причины использования typedef:
1)“Эстетическая”-одним именем заменяется сложная декларация.
2) Стремление к ясности
struct list*pstr;-указатель на структуру типа struct list
typedef structlist*Plist;
Plist pstr;
Принято имена-синонимы объявлять в typedef с заглавной буквы!!!
3)Машинно-независимые программы.
От реализации зависят:
-)chort,
-)int,
-)long,
-)double,
-)long double.
При переносе на другие ЭВМ(или другую платформу)достаточно будет изменять только размеры с помощью typedef.
12 ФУНКЦИИ И СТРУКТУРА ПРОГРАММЫ
Вспомогательным подзадачам на этапе разработки метода
решения задачи соответствуют вспомогательные алгоритмы.
В языке Си вспомогательным алгоритмам соответствует понятие
функция.
12.1 Определение функции
Синтаксис
<тип_результата> <имя_функции>
([<декларации_аргументов>])
{
<декларации> \ <тело
<иструкции> \ функции>
}
Могут быть опущены:
<тип_результат>~int
<декларация_аргументов>~()
<декларации> в <теле_функции>~нет локальных
переменных
<инструкции>~нет вычисления результатов
пример12.1
/*минимальная функция*/
dummy() {}
12.2 Функции вызывающие и вызываемые
main () a() b()
{ { {
.......... ......... ..........
a() b() }
.......... .........
b() }
}
Опр.
Функция, которая отдаёт управление другой называется
вызывающей, а которая управление получает называется
вызываемой.
В исходном файле Си программы функции могут следовать в
любом порядке.
12.3 Связь между функциями.
Связь между функциями реализуется одним из тех способов:
1. Через аргументы.
2. Через возвращаемые значения.
3. Через внешние переменные.
Через возвращаемые переменные
12.3.1
Вызов функции
<имя функции>(<список аргументов>)
Пример 12.3
/* Вызов printf */
Вызов функции есть выражение , поэтому оно может быть также
использовано в операторах
if (res==printf("как выражение"))
dummy();
else
exit(-1); /*Выход в MS-DOS*/
12.3.2 Инструкция возврата return
Использование
-возвращение результата из вызываемой в вызвавшую
Синтаксис
return <выражение>
return (<выражение>)
Так как это инструкция в конце надо писать ;.
Семантика
Выполняется приведение типа результата вычисляемого
функцией к типу заданному в вызывающей функции
-вызывающая функция может игнорировать то значение ,
которое возвращается из вызываемой функции.
-<выражение> может отсутствовать , тогда функция не
возвращает результата
-return может отсутствовать, тогда функция завершает работу по
достижению символа }
- допускается несколько инструкций возврата, если все они
возвращают значение одного типа.
- если разные return возвращают значения разного типа , то
программа нереентабельна
12.4 АППАРАТ ФОРМАЛЬНИХ І ФАКТИЧНИХ АРГУМЕНТІВ
Приклад 12.4
Завдання. Знайти максимальний із трьох елементів.
#include<stdio.h>
int max_int (int a, int b)
{ return (a>b) ? a : b; /*для 2-х перемінних*/
}
main()
{ int x,y,z;
int m1,m2;
scanf(“%d,%d,%d”,&x,&y,&z);
/*максимум із x,y,z*/
m1=max_int(x, y);
m2=max_int(m1, z);
printf(“\nmax(%d,%d,%d)”,x,y,z;m2);
}
Ім'я функції | Тип аргументу | Імена аргументів |
main | Фактичні | x,y,m1,z |
Printf | Фактичні | “”(ФОРМАТНИЙ РЯДОК) x,y,z,m2 |
max_int | Формальні Фактичні | a,b x,y,m1,z |
Scanf | Фактичні | “”(ФОРМАТНИЙ РЯДОК) x,y,z |
Аргументи поділяють на трьох типу:
-вхідні;
-вихідні; що
-обновлюються.
Аргументи, що приходять у функцію, не змінюють своїх значень і використовуються для формування інших значень називаються вхідними.
Аргументи, що одержують свої значення і повертають їх із функції називаються вихідними.
Ті аргументи, що є одночасно вхідними і вихідними називаються що обновляються.
функція | вхідні аргументи | вихідні аргументи |
max_int | a,b | ------------------ |
scanf | форматний рядок | x,y,z |
Printf | x,y,z,m2 форматний рядок | ------------------ |
12.5 ОПИС ПРОТОТИПУ ФУНКЦІЇ
Тому що в «СИ» усі функції незалежні друг від друга, те обов'язково у функції , що викликає , описувати прототипи що викликаються функцій.
Для опису синтаксису прототипу існує два засоби:
1.
<тип результату> <ім'я функції >( );
2. (повний)
<тип результату> <ім'я функції > <деклорація типів аргументів>( );
Приклад 12.5
Варіант 1 : int max_int(int, int);
Варіант 2 : int max_int();
Варіант 3 : int max_int( int a1, int a2)
Припускається використання будь-якого з варіантів.
13 ПЕРЕДАЧА АРГУМЕНТОВ
13.1 Способы передачи аргументов
-по значению;
-по имени (по наименованию);
-по ссылке.
13.1.1 По значению.
Пример 13.1
#include<stdio.h>
int int max_int(int a, int b)
{return a>b ? a:b;}
main()
{ int max_int(int a, int b);
m1,l;
m1=max_int(5,9);
l=strlen("по значению");
В качестве фактических аргументов передаются либо изображения констант, либо выражения.
Этот способ используется для передачи входных аргументов.
Формальный | Фактический |
имя скалярной переменной | Изображение константного выражения |
-имя массива символов -имя литерного указателя |
13.1.2 Передача аргументов по имени
Пример 13.2
int max_int(int a, int b)
{return a>b ? a:b;}
main()
{ int max_int(int a, int b);
int a,b,m1;
int x[]={-1,10,-200,-9};
int m2,l1,l2,l3;
char s[]="пл наименованию";
char *ms[]={"Белеет","парус"};
int *px;
char *pms;
int i;
scanf("%d",&a);
/*значение а вводит пользователь*/
b=25;
m1=max_int(a,b);
/*max_int вызывается и ей передаётся значение*/
px=x;
for(i=0;i<3;i++)
{m2=max_int(*px++,x[i+1]);
printf("m2=%d",m2);
}
l1=strlen(s);
pms=ms;
for(i=0;i<2;i++)
{l2=strlen(ms[i]);
l3=strlen(*pms++);
printf("l2=%d l3=%d",l2,l3);
}
}
Этот способ используется только(!!!) для передачи входных аргументов.
Формальный | Фактический |
-имя скалярной переменной; | -имя скалярной переменной; -имя элемента массива; -указатель на элемент массива; |
-имя структуры; | -имя структуры; -имя элемента массива структур; -указатель на элемент массива структур; |
-имя массива; | -имя массива; |
Строки: -имя массива символов; -имя литерного указателя; | -имя массива символов; -имя литерного указателя; -имя элемента массива символов; -имя элемента массива литерных указателей; |
13.1.3 Передача аргумента по ссылке
Пример 13.3
/*так нельзя!!!!!!!!!!*/
void obmen(int a,int b)
{ int r;
r=a;
a=b;
b=r;
}
Пример 13.4
/*нужно только так!!!!*/
…………
void obmen(int *a,int *b)
{ int r;
r=*a;
*a=b;
*b=r;
}
main()
{
int x,y;
void obmen(int *,int *);
scanf("%d %d",&x,&y);
printf("x=%d y=%d",x,y);
obmen(&x,&y);
printf("x=%d y=%d",x,y);
}
Формальный | Фактический |
-имя указателя на скалярную переменную; | -адрес скалярной переменной; -адрес элемента массива; |
-имя массива; | -имя массива; |
-имя указателя на структуру; | -адрес структуры; |
Этот способ используется для передачи выходных и обновляемых аргументов.
!!! Количество, типы и порядок следования формальных и фактических аргументов должны совпадать.
13.2 Особенности передачи аргументов функций в языке С
Все аргументы передаются по значению: вызываемой функции-копии.
!!! Вызываемая функция не может непосредственно изменить переданные ей параметры.
Пример 13.5
/*возведение x в степень n*/
/*вариант 1*/
int power 1(int x, int n)
{
int i, p;
p=1;
for(i=0; i<=n; i++)
p=p*x;
return p;
}
Пример 13.6
/*вариант 2*/
int power 2(int x, int n)
{
int p;
for(p=1; n>0; --n)
p=p*x;
return p;
}
Чтобы функция могла изменить переменную в вызывающей функции, формальный параметр должен быть передан по ссылке,
а фактический по адресу.
Механизм передачи аргументом массива иной: элементы массива не копируются, так как аргументами передаётся адрес массива.
13.3 Особые случаи передачи аргументов.
13.3.1 Передача аргументом одномерного массива
формальный | тело |
массив переменных, граница опущена | переменные с индексом |
указатель на переменную | указатели |
13.3.2Передача аргументом многомерного массива
Замечание.При передаче многомерного массива обязательна передача количества элементов по первому измерению, остальные можно опустить.
Пример.
main()
{double xyz[10][15][7];
f(double[][15][7]);
...
}
f(double a[][15][7])
{...}
Для двумерного массива обязательно объявление количества столбцов,
а строк- необязательно.
Пример.
f1(int mpr[2][9]) {...};
f2(int mpr[][9]) {...};
f3(int(*pmpr)[9]) {...};
13.3.3 ПЕРЕДАЧА АРГУМЕНТОВ СТРУКТУРЫ
В общем случае над структурами допустимы следующие операции:
-копирование ~передача аргументов
-присваивание ~возврат функции как -взятие адреса результата
-доступ к ее членам
-инициализация
Существует 3 подхода к передаче структур в функцию и возврата из нее:
-передача ее членов по отдельности
-как единого целого
-указателя на структуру
Обьекты типа:
“точка” “прямоугольник”
struct point struct rect
{ int x; { struct point1;
int y; struct point2;
} }
Пример 13.9
/*Формирование точки по ее компонентам X и Y*/
struct point makepoint (int x, int y)
{ struct point temp;
temp.x=x;
temp.y=y;
return temp;
}
(0;0) 640
Обьекты “экран” и “середина экрана”
Пример 13.10
#define MAXX 639
#define MAXY 349
#define MINX 0
#define MINY 0
...
struct rest screen;
struct point middle;
struct point makepoint(int,int);
screen.pt1=makepoint(MINX,MINY);
screen.pt2=makepoint(MAXX,MAXY);
middle=makepoint ((screen.pt1.x+screen.pt2.x)/2
screen.pt1.y+screen.pt2.y)/2);
Пример 13 11
/*Сложение двух точек*/
struct point addp(struct point pl, struct point p2)
/*функция возвращает результатом структуру и получает аргументами структуру*/
{ pl.x+=p2.x;
pl.y+=p2.y;
return pl;
}
Пример13.13
struct point * ps;
struct point t;
struct point makepoint(int, int);
t=makpoint(15, 25);
ps=&t;
/* *ps - структура t
(*ps).x - =15
(*ps).y - =25 */
printf (“ Это t: (%d, %d)”, (*ps). x, (*ps).y);
!!! prio(.)>prio(*)
Оператор®
Синтаксис
< указатель на структуру >®
< имя члена структуры >
Семантика
Если p -указатель на структуру, то
p®<член структуры> есть ее член.
Бинарный, левоассоциотивный оператор, имею- щий высший приоритет.
Для 13.13
printf (“Это t: (%d,%d)”,ps®x, ps®y);
Пример 13.14
struct rect2, *pr;
pr=&r;
/* Эквивалентно */
1) r.pt1.x
2) pr®pt1.x
3) (r.pt1).x
4) (pr®pt1).x
Пример 13.15
/* Передается аргументом по ссылке */
main()
{
struct point p;
struct makepoint (int, int);
void put(struct point * );
p=makepoint(10, 12);
put (&p);
}
void put (struct point *p) ;
{
printf (“х=%d, y=%d”, *p®x, *p®y);
}
Пример 13.16
/* Учет приоритета оператора*/
struct
{
int len;
char *str;
}*p;
++p®len; /* len++, а не p++*/
++(p®len);
(++p)®len; /* 1) ++p; 2) len* */
(p++)®len; /* 1) len; 2) p++*/
p++®len;
*p®str; /* то, на что ссылается str */
*(p®str);
*p®str++; /*1)то, на что ссылается str; 2)str++*/
(*p®str)++; /* то, на что ссылается str и его ++*/
*p++®str; /* 1)на что ссылается str; 2) p++*/
* Если в методе требуются вспомогательные переменные, их описывают после метода в том же синтаксисе, что и исходные данные.
Дата добавления: 2015-12-29; просмотров: 784;