C Урок 30. Указатели на функции. Часть 2



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

 

Перейдём в файл student.c и добавим сразу три функции, которые будут прибавлять курс, возраст и изменять имя студента

 

 

Зачем изменять имя, думаю понятно. Например, студентка вышла замуж и изменила фамилию. Бывает же такое.

Добавим ещё одну функцию, которая будет удалять студента, например, если он отчислен по причине академической неуспеваемости либо по причине окончания учебного заведения

 

 

Первые три функции вообще простые и не нуждаются в объяснении.

А вот четвёртая интересная.

Мы по сути ничего не удаляем.

Мы просто копируем следующий элемент массива за якобы удаляемым в позицию удаляемого элемента, а в позицию того элемента, который мы скопировали, копируем следующий элемент. И так до тех пор, пока не дойдём до последнего элемента. Последний элемент у нас — это значение счётчика студентов минус один, так как элементы считаются с нуля.

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

В заголовочном файле student.h добавим на наши функции прототипы

 

 

 

И там же объявим ещё одну структуру, вернее, тип структуры, в который мы, кроме указателя на студента, который затем будет указателем на нулевой элемент в массиве всех студентов, добавим ещё и указатели на функции, по типам такие же, как и наши 4 только что добавленные функции. Мало того, мы и имена можем использовать те же, так как это уже поля структуры и они с прототипами функций никак не пересекаются и нам незачем выдумывать для указателей новые имена

 

 

Теперь вернёмся в функцию main() файла main.c, закомментируем предыдущий участок кода, создадим массив студентов, проинициализируем их также, как и в прошлом уроке и выведем их данные в консоль, в том числе и их позиции, а по окончания вывода добавим ещё один переход на новую строку

 

 

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

 

 

Что круто в структуре?

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

Чудеса да и только!

Это потому, что мы не просто создали переменную типа структуры. Она у нас уже есть. Мы её создали и проинициализировали. Вот и весь секрет.

Мы можем собрать наш код и проверить это несколькими способами.

 

 

1 способ: вызвать контекстное меню на любом из этих полей и посмотреть куда мы попадём.

Давайте проделаем это

 

 

И попадём мы вот куда

 

 

Следующие способы посмотрим чуть позже.

Давайте нашу девушку «выдадим замуж», изменив ей фамилию (имя и отчество мы ей оставим прежние), одному студенту добавим возраст, так как у него день рожденья сегодня, а другого переведём на следующий курс, а затем снова всех выведем в консоль

 

 

Проверим, сработало ли наше действие

 

 

Всё сработало. Иванова стала Петровой, Петров стал старше на год, а Саблин перешёл на 2 курс.

Теперь второй способ посмотреть, куда смотрят имена.

Поставим точку останова куда-нибудь после объявления и инициализации переменной структуры и зайдём в отладку. Запустим программу до точки останова

 

 

Мы видим реальные адреса процедур. Запомним их. Перейдём в файл student.c, не останавливая отладку, и, подводя курсор к именам функций, посмотрим их адреса

 

     

 

Адреса совпали.

Третий способ — дизассемблер.

Зайдём туда

 

 

Те же адреса. Отлично.

Осталось нам попробовать отчислить какого-нибудь студента-пятикурсника, будем считать, что он получил диплом.

Давайте это проделаем и затем снова выведем список наших студентов

 

 

Проверим, удалился ли у нас пятикурсник Васильев

 

 

Васильева больше нет в массиве. Отлично!

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

Всем спасибо за внимание!

 

 

Предыдущая часть Программирование на C Следующий урок

 

Исходный код

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

C Указатели на функции

2 комментария на “C Урок 30. Указатели на функции. Часть 2
  1. Vladimir:

    Добрый день. По хорошему, раз уже есть addStudent и deletePos , то в них и надо проверять количество студентов. Вы совсем не ленивый 🙂

  2. max:

    что то я запутался, зачем

    strcpy(st_list[i].nm, st_list[i+1].nm);
    st_list[i].age = st_list[i+1].age;
    st_list[i].course = st_list[i+1].course;

    разве нельзя просто st_list[i] = st_list[i+1]

    ?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*