Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

Лабораторная работа 7

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 25.11.2024

Лабораторная работа 7 .

Функции. Механизм объявления, обращения, возврата параметров. Указатели на функции.

Цель работы.  Изучить синтаксис работы  с функциями. Научится использовать функции в программах.

Теоретическая часть.

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

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

Когда следует использовать функции:

  1.  При повторяющемся коде, когда во многих частях программы используются один и тот же код, разумно вынести его в отдельную функцию.
  2.  Для логического разделения программы на модули.
  3.  При желании объяснить некоторые действия, создать читаемый код.
  4.  При необходимости избежать прямого доступа к переменной.

Объявление функции.

Тип_возвращаемого_значения имя_функции(Тип аргумента 1, Тип аргумента 2,…);

Реализация функции:

Тип_возвращаемого_значения имя_функции(Тип аргумента 1 имя аргумента1 , Тип аргумента 2 имя аргумента2…){

// Тело функции.

 return 0; // возвращаемое значение

}

Использование функции

переменная  = имя_функции(имя аргумента1, имя аргумента2…);

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

Любая функция, кроме main{}, должна быть объявлена перед использованием. Т.е. объявление (или реализация) функции должна быть выше по тексту файла от  места ее использования.

Первая функция, которую вы встретили при программировании на языке Си, это

int main(){

 return 0;

}

По виду это реализация функции.

Int означает, что функция возвращает значение типа int.

() означают, что функция не принимает аргументов. Можно написать int main(void).

Оператор return используется для возвращения значения из функции.

Напишем реализацию своей функции суммирующей два 16 битных числа и возвращающую 32 битный результат.

int summa(short int a, short int b){

 int summa =  a + b;

 return summa;

}

int main(void){

 int c = summa(1,2);

 printf("Сумма равна %d \n", c);// выведет 3

 return 0;

}

Так как объявление функции в файле стоит выше места ее использования, то объявление можно опустить.

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

// объявление функции

int summa(short int , short int );

int main(void){

 // использование функции

 int c = summa(1,2);

 printf("Сумма равна %d \n", c);

 return 0;

}

//реализация функции

int summa(short int a, short int b){

 int summa =  a + b;

 return summa;

}

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

Рассмотрим пример возможной ошибки.

Задача поменять значения двух переменных друг с другом

//реализация функции 

void change(int a, int b){

 int temp = a;

a = b;

 b = temp;

}

// использование функции 

int a = 9;

int b = 3;

change(a,b);

printf("a равно %d b равно %d \n", a,b);

В этом примере после выполнения функции change(a,b); a и b не изменятся т.к. в функции создались свои переменные локальные переменные a и b, и они обменялись местами.  

Для того чтобы исправить ошибку можно воспользоваться указателями на переменные.

Аргументы функции change теперь указатели на переменные

void change(int* a, int* b){

 int temp = *a;

*a = *b;

*b = temp;

}

int a = 9;int b = 3;

change(&a,&b); // при использовании передаем в функцию адреса переменных

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

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

//реализация функции

void summa(short int a, short int b, int* summa){

 *summa =  a + b;

}

// использование функции 

int c;

summa(1,2,&c);// передаем указатель на переменную

При написании функций пользуются следующими правилами хорошего стиля программирования:

  1.  Функция должна выполнять единственное действие.
  2.  Название функции должно целиком  отражать ее смысл.
  3.  Чем меньше размер, функции тем лучше.
  4.  Избегать функции, имеющие больше трех входных параметров.

Область видимости переменных

Область видимости имени (англ. scope) — понятие, означающее места в исходном коде, в которых может использоваться данное имя.

В Си есть:

–локальные  переменные, которые «видны» внутри данной структуры – функции или  управляющего блока (цикла).

– статические переменные, которые видны внутри данного файла.

– глобальные, которые «видны» во всей программе.

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

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

Бывает удобно передать саму функцию, как аргумент другой функции.

Тогда необходимо создать указатель на функцию и передать его в качестве аргумента другой функции.

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

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

Определение указателя на функцию имеет вид, например:  

int (*p)(const char *, const char *);

Это объявление сообщает компилятору, что p — это указатель на функцию, имеющую два параметра типа const char * и возвращающую значение типа int. Скобки вокруг p необходимы для правильной интерпретации объявления компилятором. Подобная форма объявления используется также для указателей на любые другие функции, нужно лишь внести изменения в зависимости от возвращаемого типа и параметров функции.

Рассмотрим пример, сравнения двух строк с использованием указателя на функцию

#include <stdio.h>

#include <string.h>

// объявление функции

void check(char *a, char *b,

          int (*cmp)(const char *, const char *));

int main(void)

{

 char s1[80], s2[80];

 int (*p)(const char *, const char *);

              /* указатель на функцию */

 p = strcmp;

 /* присваивает адрес функции strcmp указателю p */

 printf("Введите две строки.\n");

 gets(s1);

 gets(s2);

 check(s1, s2, p); /* Передает адрес функции strcmp

                      посредством указателя p */

 return 0;

}

// реализация функции

void check(char *a, char *b,

          int (*cmp)(const char *, const char *))

{

 printf("Проверка на совпадение.\n");

 int result_compare = (*cmp)(a, b); // вызов  функции по указателю

 if(!result_compare){

  printf("Равны");

 }else {

  printf("Не равны");

}

}

Практическая часть.

Переписать программу с лабораторной по структурам, используя функции.

Программа разбита на логические блоки, с соответствующими комментариями. Сделаем из каждого логического блока функцию.

// объявление подключаемых файлов

#include <stdio.h>

#include <math.h>

//объявление именнованных констант

enum {

 TAU,

 Informatika,

 NumberExamsSubject,

};

enum {

 NumberStudents = 3,

};

// объявление собственных типов

typedef struct{

 char  name[40];

 unsigned char examsMark[NumberExamsSubject];

 float meanExamsMark;

}recordBook;

// объявление функций

void for_correct_work_printf(void);

void init_from_keyboard(recordBook* students);

void calc_mean_mark(recordBook* students);

float calc_mean_group(recordBook* students);

void calc_mean_student(recordBook* students, float mean_value, int* mean_index);

int main(void){

 // для корректной работы printf и scanf

for_correct_work_printf();

 // Инициализация в тексте программы

 recordBook students[] = {

  {"Иванов", {4,4}},

  {"Петров", {5,5}},

  {"Сидоров", {3,4}}

};

 // инициализация с помощью клавиатуры

init_from_keyboard(&students[0]);

 // Нахождение средней оценки по экзаменам

calc_mean_mark(&students[0]);

 // Нахождение средней оценки по группе

 float meanMarkGroup = calc_mean_group(&students[0]);

 // Нахождение студента с оценкой самой близкой к средней

 int mean_student_index=0;

calc_mean_student(&students[0], meanMarkGroup, &mean_student_index);

 // Вывод результата на экран

 printf(" Самый средний студент - %s",students[mean_student_index].name);

 return mean_student_index;

}

void for_correct_work_printf(void){

 setvbuf(stdin, NULL, _IONBF, 0);

 setvbuf(stdout, NULL, _IONBF, 0);

}

void init_from_keyboard(recordBook* students){

 int i = 0;

 int j = 0;

 for(i = 0; i < NumberStudents;  i++){

 printf("Введите фамилию %d  студента \n", i+1 );

 scanf("%s", (students+i)->name);

 for(j = 0; j < NumberExamsSubject;j++ ){

  printf("Введите оценку %d  студента  за  %d предмет\n", i+1, j+1 );

  scanf("%d", (int*)&((students+i)->examsMark[j]));

 }

}

}

float calc_mean_group(recordBook* students){

 int i = 0;

 float meanMarkGroup = 0;

 for(i = 0; i < NumberStudents;  i++){

 meanMarkGroup += (students+i)->meanExamsMark;

}

meanMarkGroup = meanMarkGroup/NumberStudents;

 return meanMarkGroup;

}

void calc_mean_mark(recordBook* students){

 int i = 0;

 int j = 0;

 for(i = 0; i < NumberStudents;  i++){

 int summa = 0;

 for(j = 0; j < NumberExamsSubject;j++ ){

   summa += (students+i)->examsMark[j];

 }

 (students+i)->meanExamsMark = (float)summa/NumberExamsSubject;

}

}

void calc_mean_student(recordBook* students, float mean_value, int* mean_index){

 float difference = 0;

 float min_difference = fabs(mean_value - students->meanExamsMark);// начальная разница

*mean_index = 0;

 int i;

 for(i = 1; i < NumberStudents;  i++){

 difference =  fabs(mean_value - (students+i)->meanExamsMark);

 if(difference < min_difference){

  min_difference = difference;

  *mean_index = i;

 }

}

}




1. 20г место опроса Опрос начат в час
2. методическое руководство для практических занятий по ортодонтии Чита 2008 г
3. Создание предпринимательской фирмы и рассмотрение эффективности ее работы на примере печатного цеха
4. варіантів використання ДВВ яку створено за допомогою CSEзасобу Enterprise rchitect v9
5. Тема 1. Исторический путь человечества- парадигмы исследования 1
6. Вариант 4 Просклонять словосочетания- officium civ~le officium ii n ~ обязанность долг; civ~lis e ~ гражда
7. 2014учгод Автотуризм ~ б~л-
8. наступает момент учета итогов дня определения потерь и завоеваний
9. Учет расчетов по налогам и сборам в организациях
10. і Та тільки тут веселий галас бою Розгоном бур і божевіллям хвиль Безмежжя Зачарований тобою Пливу в теб
11. принцессами Шелковинкой и Шерстинкой и сыновьями принцами Лёнушкой и Хлопком
12. Лабораторная работа 1
13. 2 Ма~саты- Биологиялы~ молекулаларды~ электронды~ ~~рылысын сол молекуларды~ электронды~ к~шуін ж
14. ~АЗА~ АРУЫ П~НІ Ж~НЕ ОНЫ~ МА~ЫЗЫ МЕН М~НІ Б~гінгі ~аза~ ~ызы ~ ерте~гі ана бір отбасыны~ ~йыт~ысы
15. ПРАВОВИЙ АНАЛІЗ Спеціальність 12
16. духа населенных мест используют два норматива
17. Информационное общество общество особое не известное истории
18. лексикограматична єдність двох і більше компонентів граматично організованих за моделлю словосполучення
19. Методические рекомендации для студентов Организация работы процедурного кабинета
20. РЕФЕРАТ дисертації на здобуття наукового ступеня кандидата технічних наук Харків ~ 2000