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

Программирование на языке Си. Учебное пособие для СПО

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
for(n=1; k; n++) { k=0; for(j=0; j<N-n; j++) if(m[ind[j]] > m[ind[j+1]]) { k=1; t= ind[j]; ind[j]=ind[j+1]; ind[j+1]=t; } }
for(i=0;i<N; i++) printf("%5d",m[i]); puts("\n"); for(i=0;i<N; i++) printf("%5d",m[ind[i]]); }
Пример сортировки с помощью массива указателей
int main(){ int i, k=1, *t, j, n; int m[N], *a[N];
for(i=0; i<10; i++) { m[i]=rand() %100; a[i]=m+i; }
for(n=1; k; n++) { k=0; for(j=0; j<N-n; j++) if(*a[j] > *a[j+1]) { k=1; t= a[j]; a[j]=a[j+1]; a[j+1]=t; }
}
for(i=0;i<N; i++) printf("%5d",m[i]); puts("\n"); for(i=0;i<N; i++) printf("%5d",*a[i]); }
Передача массива в качестве параметра функции
Если в качестве параметра передается массив, то в функцию попадает не
его копия, а адрес начала массива. Следовательно, изменение массива в
функции привет к изменению соответствующего фактического параметра.
Примеры:
void f1(int a[10], int n); //размер массива указывать в квадратных скобках можно, но смысла в этом нет, так как новая память не выделяется. void f2(int a[], int n);// a – указатель константа void f2(int* a, int n); // a – указатель переменная
61
void in(int a[], int n) { for(int i=0; i<n; i++) a[i]=rand()%1000; } void print(int *a, int n) { for(int i=0; i<n; i++) printf("%4d",a[i]); printf("\n"); } int main(){ int m1[10]; int *m2=new int [20]; in(m1,10); in(m2,20); print(m1,10); print(m2,20); print(m2,10); print(m2+10,10); }
Возврат значений из функции через параметры
Можно использовать указатели.
void swap(*x, *y) { int t; t=*x; *x=*y; *y=t; }
int a=1, b=2; swap(&a, &b);
В С++ можно использовать передачу параметров по ссылке
void swap(int &x, int &y) { int t; t=x; x=y; y=t; } swap(a,b)
Пример рекурсивного создания динамического массива из элементов, вводимых с клавиатуры до ввода 0.
void f(int i, int *&p) { int x; scanf("%d",&x); if(x==0) { p=new int [i+1]; p[i]=x; return;} f(i+1,p); p[i]=x; }
62
00
01
02
10
11
12
20
21
22
30
31
32
40
41
42
main() { int *p; f(0,p); for(int i=0; p[i]; i++) printf("%d\n",p[i]); }
Многомерные динамические массивы
В статическом массиве элементы в памяти расположены последовательно, причем в первую очередь меняется последний индекс.
int m[5][3];
Элементы в памяти будут храниться в следующем порядке:
m – адрес начала массива m[0] – адрес начала строки с индексом 0 m[0][0] то же что и **m m[1][2] то же что и *(*(m+1)+2)
Варианты создания динамических двумерных массивов
1. Если известна длина строки
typedef int str[3]; str *a2; a2= new str[n]; или int (*a2)[3]; a2=(int (*)[3]) malloc(sizeof(int)*3*n);
2. Если известно количество строк
int *a3[5]; for(i=0; i<5; i++ ) { a3[i] = new int[m]; или a3[i]=(int *) malloc(m*sizeof(int)); }
3. Если не известно ни количество строк, ни количество столбцов.
typedef int *pint; int **a4; или pint *a4;
63
a4= (int **) malloc(n*sizeof(int *)); a4 = new pint[n]; или a4=new int*[n] for(i=0; i<n; i++ ) { a4[i]=(int *) calloc(m,sizeof(int)); или a4[i] = new int[m]; }
удаление – в обратном порядке, сначала памяти под строки, потом под массив указателей а.
for(i=0; i<n; i++) { free(a[i]); } free(a);
можно выделить память отдельно под матрицу, и отдельно под массив
указателей.
int i,n=5, m=20; char **a5; a5 = (char **) malloc(n*sizeof(int *)); a[0] = (char *) malloc(n*m); for(i=1; i<n; i++) a5[i]=a5[i-1]+m; for(i=0; i<n; i++) for(j=0; j<m; j++) { scanf("%d",a5[i][j]); }
Свободный массивы – это массив, длина строк которого может быть различной.
Пример
int main(){ int i,n,l; char st[80], **a6; printf("n="); scanf("%d",&n); a6 = (char **) malloc(n*sizeof(int *)); for(i=0; i<n; i++) { scanf("%s",st); l=strlen(st); a6[i]=(char *) malloc(l+1); strcpy(a[i], st); } for(i=0;i<n; i++) { printf("%s\n",a6[i]); }
}
64
Передача многомерных массивов как параметров функции
int a[N][N] – известна длина строки
f(int a[][N]); f(int (*a)[N]);
int a[5][4]; void f1(int a[][4], int n, int m) { printf("\n"); for(int i=0;i<n; i++) { for(int j=0;j<m; j++) printf("%5d",a[i][j]); printf("\n"); } }
f1(a,5,4) – вызов
int **a или *a[N] – длина строки заранее не определена
f(int **a) f(int *a[])
int **a; void f2(int **a, int n, int m) { for(int i=0;i<n; i++) { for(int j=0;j<m; j++) printf("%5d",a[i][j]); printf("\n"); } }
f2(a,5,4) – вызов
Классы памяти
Каждый объект в программе принадлежит определенному классу памяти,
определяющему его время жизни и видимость. Класс памяти задается либо по месту описания объекта, либо с помощью спецификатора.
Автоматические (auto)
Объект описанный внутри функции или блока – автоматический (локальный).
Область видимости и время жизни ограничены блоком, в котором они описаны. Память под них выделяется автоматически, в стеке, и так же автоматически
освобождается.
65
Внешние (extern)
Объект описанный вне функции – внешний, или глобальный. Область видимости и время жизни – вся программа. Пример
int d=4; void f(int a) { int b=1; cout<<" a="<<a<<" b="<<b<<" d="<<d<<endl; } int main(){ int c=3; f(2); cout<<" c="<<c<<" d="<<d<<endl; }
Статические (static)
Область видимости – как у автоматических, время жизни – как у глобальных. Пример
int f(int a) { static int b=0; //значение переменной b будет сохраняться на протяжении работы всей // программы. b+=a; cout<<" a="<<a<<" b="<<b<<endl; return b; } int main(){ int c; for(int i=0; i<10; i++) c=f(i); cout<<" c="<<c<<endl; }
Реализация генератора случайных чисел в языке С.
#define RAND_MAX 32767
static unsigned long int next = 1;
int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % RAND_MAX; }
66
void srand(unsigned int seed) { next = seed; }
Регистровые
Только для локальных переменных. Указывает, что объект желательно
разместить в регистре микропроцессора.
Доступ к глобальным объектам перекрытым локальными
Для доступа к глобальной переменной х , перекрытой локальной, можно использовать следующую конструкцию ::x
cout<<d<<::d<<endl;
Контрольные вопросы
Где хранятся адреса динамических переменных? Как выделить память под простую динамическую переменную? Как выделить память под одномерный динамический массив? Как выделить память под двумерный динамический массив? Как освободить динамическую память? Какое значение будет иметь указатель после освобождения памяти?
67
9. Структуры и объединения
Часто приходиться работать с информацией различного типа,
сгруппированной в пределах одной записи – например, элемент базы данных.
Рассмотрим структуру данных записная книжка – каждая запись содержит имя, фамилию (строки), дата рождения (целые числа), телефон, электронная почта (строки). Для хранения этой информации массив не подходит – у него все элементы одного типа. В этом случае можно использовать структуры.
Структура – это тип данных, который может включать в себя несколько полей – элементов различных типов (в том числе и другие структуры).
Поскольку структура – это новый тип данных, его надо предварительно объявить.
struct zap { char fam[20]; char name[15]; unsigned char d; unsigned char m; unsigned char y; char tel[12]; char email[20]; };
для создания записи описанного выше типа:
zap a;
zap – это тип, a – объект типа zap.
при описании структуры можно стразу присвоить нач значения.
zap a={"petrova","irina",15,3,1980,"2665522","petrova@mail.ru"};
Для обращения ко всей структуре используется ее имя. Для обращения к конкретному полю – к имени структуры добавляется имя поля через точку.
a.y=1981; strcpy(a.fam,”Ivanova”);
При вводе с клавиатуры и выводе на экран с полями структуры работают
отдельно.
scanf("%s %d",a.fam, &a.y); printf("%s %s %d %d %d %s %s\n", a.fam, a.name, a.d, a.m, a.y, a.tel, a.email);
Присваивать все поля одной структуры другой можно одним оператором
zap b; b=a; это аналогично копированию по полям.
Полем структуры может быть другая структура.
struct dat {
68
unsigned char d; unsigned char m; int y; } ; struct zap { char fam[20]; char name[15]; dat d; char tel[12]; char email[20]; }b; b.d.d = 31;
Массивы структур
Часто используются массивы структур. zap m[10]; for(i=0; i<10; i++) { scanf(“%s”, m[i].fam);
Указатели на структуру
zap *c; c= new zap; для доступа к полям (*c).tel или с->tel
Объединения
Объединения используются для размещения в одной и той же области памяти
данных различных типов.
union kont { char tel[12]; char email[20]; }; struct zap { char fam[20]; char name[15]; char tag; kont k; }b; printf("tel/email 1/0 "); scanf("%d",&a.tag); if (a.tag) {printf("tel "); scanf("%s",a.k.tel); } else {printf("email "); scanf("%s",a.k.email); }
69
размер структуры – сумма размеров полей, размер объединения – размер наибольшего поля.
Справочник – используется для хранения повторяющихся значений
char name[K][15]={“Иван”,”Петр”,”Павел”} struct zap { char fam[20]; int n; dat d; char tel[12]; char email[20]; }a[N];
cout<<name[a[i].n];
количество людей с различными именами (группировка по именам)
for(i=0; i<K; i++) { for(s=j=0;j<N;j++) if(i==a[j].n) s++; printf("%s %d\n",name[i],s); }
Сортировка массивов структур
Для сортировки выбирается одно из полей структуры, оно называется
ключевым полем или просто ключом. Структуры расставляются в определенном
порядке по значению ключевого поля, содержимое всех остальных полей
игнорируется. Часто для сортировки создают индексные массивы и сортируют их – это быстрее, и индексных массивов может быть несколько.
#define N 4 #define K 3 int main(){ int i, j, t,s; struct zap { char fam[15]; char n; char tel[13]; }b; char name[K][15]={"Ivan","Pavel","Petr"}; zap a[N]={{"Petrov",0,"2665522"},{"Ivanov",1,"9139204512"}, {"Sidorov",2,"2123456"},{"Popov",1,"3656565"}}; int n[N], f[N];
70
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]