Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Введение в программирование на С.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
930.82 Кб
Скачать

6.3 Функция realloc()

Void * realloc(void *ptr ,unsigned size)

Функция realloc изменяет размер динамически выделенной памяти, на которую указывает ptr на новый размер - size байтов. Т.е для того чтобы можно было изменить размер памяти его необходимо обязательно динамически выделить с помощь функции malloc или функции calloc и при изменении размера выделяется новая память, а не меняется размер выделенной памяти следовательно необходимо переадресовывать указатель. Рассмотрим пример использования функции realloc.

void main(){

int *p1, *p2;

p1= (int *)malloc(5*sizeof(int));

if(!p1){

printf(“Error!!!!”);

exit(1);}

……………………

p2=(int *)realloc(p1,10*sizeof(int));//10 это новый размер массива, т.е. добавляется //еще 5 елементов

if(p2)//если память выделилась

p1=p2;//переадресация указателя

else{

printf(“Error!!!!”);

exit(1);}

…………………………

}

Задача: Вести размер массива и динамически выделить память. Заполнить элементы массива и удалить все 5 находящиеся в массиве.

#include<stdio.h>

#include<stdlib.h>

void vvod_mas(int *,const int);

void vivod_mas(int *,const int);

void main(){

int n,k=0;

int *x,*y;

printf("Введите размер массива: ");

scanf("%d",&n);

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

if(!x) return;

vvod_mas(x,n);

printf("Содержание массива:\n");

vivod_mas(x,n);

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

if(x[i]==5){

k++;

printf("\nk=%d\n",k);

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

x[j-1]=x[j];

}

}

n=n-k;

y=(int*)realloc(x,n*sizeof(int));

if(y)

x=y;

else

return;

printf("Содержание нового массива:\n");

vivod_mas(x,n);

}

void vvod_mas(int *p,const int k){

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

printf("[%d]=",i);

scanf("%d",(p+i));

}

}

void vivod_mas(int *p,const int k){

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

printf("[%d]=%d\n",i,*(p+i));

}

§7 Структура

7.1 Объявление структуры

Структура – это тип данных, созданный нами, построенный с использованием других типов. Ключевое слово struct начинает определение структуры.

struct имя_структуры

{

тип1 имя_переменной;

тип2 имя_переменной;

тип3 имя_переменной; и т.д.

};

Например:struct Man{

char fam[20];

char name[15];

int year, day, month;

};

Среди типов данных структуры могут также присутствовать, кроме стандартных типов данных (int, float, char и т.д.) ранее определенные типы, но структура не включать в себе переменные своего типа, примеры:

1. struct date

{

int year, day, month;

};

struct Man

{

char fam[20];

char name[15];

date birthday;

};

2. struct date

{

int year, day, month;

};

struct Man

{

char fam[20];

char name[15];

date birthday;

man any;//неправильно

};

При непосредственной работе со структурой, доступ к компонентам структуры осуществляется с помощью оператора “точка”, а при использовании указателя на структуру “->”. Синтаксис для доступа к компонентам структуры следующий:

имя_переменной_структуры. член_данных

имя_переменной_структуры.->член_данных

#include<stdio.h>

void main()

{

Man ob[3];

for(int i=0;i<3;i++)

{

printf("%d\nName: ",i+1);

scanf("%s",ob[i].name);

printf("Family: ");

scanf("%s",ob[i].fam);

printf("Rost: ");

scanf("%lf",&ob[i].rost);

printf("VES: ");

scanf("%lf",&ob[i].ves);

}

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

{

printf("%d\n%s\t%s\n%.1lf\t%.1lf\n",i+1,ob[i].fam,ob[i].name,ob[i].rost,ob[i].ves);

}

}

#include<stdio.h>

struct date

{

int day,month,year;

};

struct Person

{

char fam[20];

char name[15];

};

struct Student

{

int grup;

int mark;

struct date birthday;

struct Person man;

};

void main()

{

Student ob;

printf("Name: ");

scanf("%s",ob.man.name);

printf("Family: ");

scanf("%s",ob.man.fam);

printf("Day: ");

scanf("%d", &ob.birthday.day);

printf("Month: ");

scanf("%d",&ob.birthday.month);

printf("Year: ");

scanf("%d",&ob.birthday.year);

printf("Mark: ");

scanf("%d",&ob.mark);

printf("Gruppa: ");

scanf("%d",&ob.grup);

printf("Student is gruppi %d \n%s \t%s \n%d.%d.%d\n Mark:%d \n", ob.grup, ob.man.fam, ob.man.name,ob.birthday.day,ob.birthday.month,ob.birthday.year,ob.mark);

}

#include<stdio.h>

struct Person

{

char fam[20];

char name[15];

};

void main()

{

Person ob1;

Person *p;

p=&ob1;

printf("Name: ");

gets(p->name);

printf("Family: ");

gets(p->fam);

printf("%s\t%s\n",ob1.fam,ob1.name);

}

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

#include<stdio.h>

#include<string.h>

struct Person

{

char *fam;

char *name;

};

void main()

{

Person ob1,ob2;

char x[20];

int l;

printf("Name: ");

scanf("%s",x);

l=strlen(x)+1;

ob1.name= new char[l];

if(!ob1.fam)

{

printf("\a\a\a\a\n");

return;

}

strcpy(ob1.name,x);

printf("Family: ");

scanf("%s",x);

l=strlen(x)+1;

ob1.fam= new char[l];

if(!ob1.fam)

{

printf("\a\a\a\a\n");

return;

}

strcpy(ob1.fam,x);

ob2=ob1;

printf("%s\t%s\n%s\t%s\n",ob1.fam,ob1.name,ob2.fam,ob2.name);// здесь возможна //ошибка

}

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

#include<stdio.h>

struct Man

{

char fam[20];

int tel;

};

struct Man func1(struct Man);

void func2(struct Man *p);

void main()

{

struct Man ob;

puts("Vizov func1 ili func2 - ? ");

fflush(stdin);

switch(getchar())

{

case '1': ob=func1(ob);

break;

case '2': func2(&ob);

break;

}

printf("sotrudnik - %s tel.- %d\n",ob.fam,ob.tel);

}

struct Man func1(struct Man ob1)

{

puts("Familiya:");

fflush(stdin);

gets(ob1.fam);

puts("Telefon:");

fflush(stdin);

scanf("%d",&ob1.tel);

return ob1;

}

void func2(struct Man *p)

{

puts("Familiya:");

fflush(stdin);

gets(p->fam);

puts("Telefon:");

fflush(stdin);

scanf("%d",&p->tel);

}

Число байтов, выделенных под структуру не всегда равна сумме длин отдельных ее элементов из-за некоторых особенностей работы процессора с данными с фиксированной и плавающей точкой, что приводит к так называемому “выравниванию”, размещению элементов с четного адреса. Выделение памяти осуществляется в последовательности объявления данных. При размещении структурной переменной в памяти для выравнивания на границу слова компилятор оставляет между ее элементами и элементами массива структурных переменных пустые байты для соблюдения следующих правил:

  • Структурная переменная (элемент массива структур) начинается на границе слова, т.е. с четного адреса;

  • Любой элемент, кроме элементов типа char, так же располагаются с четного адреса и соответственно имеет четное смещение от начала структурной переменной;

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

Между структурами и элементами структуры могут быть неиспользованные байты памяти.

Задачи:

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

#include<stdio.h>

struct Student

{

char fam[20],name[20];

int year,marks[5],average;

};

void func_vvoda(Student *);

void func_vivoda(Student );

void main()

{

Student ob[10];

for(int i=0;i<10;i++)

func_vvoda(&ob[i]);

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

func_vivoda(ob[i]);

}

void func_vivoda(Student ob1)

{

puts("");

printf("%s\t%s\t%d\t%d\n",ob1.fam,ob1.name,ob1.year,ob1.average);

}

void func_vvoda(Student *p)

{

int sum=0;

puts("Familiya:");

fflush(stdin);

gets(p->fam);

puts("Name:");

fflush(stdin);

gets(p->name);

puts("5 marks:");

fflush(stdin);

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

{

scanf("%d",&p->marks[i]);

sum+=p->marks[i];

}

p->average=sum/5;

puts("Year:");

fflush(stdin);

scanf("%d",&p->year);

}

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

Аналогично, что и в предыдущей задаче

#include<stdio.h>

struct Student

{

char fam[20],name[20];

int group,marks[5],average;

};

void func_vvoda(Student *);

void func_vivoda(Student );

int func_max(Student ob1[],int n);

void main()

{

Student ob[4];

int max;

for(int i=0;i<4;i++)

func_vvoda(&ob[i]);

max=func_max(ob,4);

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

if(ob[i].average==max)

func_vivoda(ob[i]);

}

int func_max(Student ob1[],int n)

{

int max=ob1[0].average;

for(int i=1;i<n;i++)

if(max<ob1[i].average)

max=ob1[i].average;

return max;

}

  1. Создать массив данных о студентах. О каждом студенте записать имя, фамилию, год рождения, оценки по 5-ти экзаменам и определить сумму оценок. И отсортировать список по сумме баллов.

  2. Ввести массив структур, используя динамическое распределение памяти. Рассортировать массив в алфавитном порядке.

#include<stdio.h>

#include<string.h>

#include<malloc.h>

struct Student

{

char name[80];

int age;

};