ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 31.03.2021

Просмотров: 334

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

  cin >> count;

 num_right = 0;

 do {

  drill(); count--;

 }while(count);

 cout << "Вы дали " << num_right<< " правильных ответов.\n";

 return 0;

}


void drill()

{

 int count; /* Эта переменная count — локальная и никак не связана с одноименной глобальной.*/

 int а, b, ans;

 // Генерируем два числа между 0 и 99.

 а = rand() % 100;

 b = rand() % 100;

 // Пользователь получает три попытки дать правильный ответ.

 for(count=0; count<3; count++) {

  cout << "Сколько будет " << а << " + " << b << "? ";

   cin >> ans;

  if(ans==a+b) {

   cout << "Правильно\n";

   num_right++;

   return;

  }

 }

 cout << "Вы использовали все свои попытки.\n";

 cout << "Ответ равен " << a+b << '\n';

}


При внимательном изучении этой программы вам должно быть ясно, что как функция main(), так и функция drill() получают доступ к глобальной переменной num_right. Но с переменной count дело обстоит несколько сложнее. В функции main() используется глобальная переменная count. Однако в функции drill() объявляется локальная переменная count. Поэтому здесь при использовании имени count подразумевается именно локальная, а не глобальная переменная count. Помните, что, если в функции глобальная и локальная переменные имеют одинаковые имена, то при обращении к этому имени подразумевается локальная, а не глобальная переменная.


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

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

Использование глобальной переменной в "роли", с которой легко бы "справилась" локальная переменная, делает такую функцию менее универсальной, поскольку она полагается на необходимость определения данных вне этой функции.

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


Функции


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

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


В языке программирования С++ есть два типа функций:


  1. Функции, которые не возвращают значений

  2. Функции, возвращающие значение


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

// структура объявления функций не возвращающих значений

void /*имя функции*/(/*параметры функции*/) // заголовок функции

{

// тело функции

}

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


// struct_func.cpp: определяет точку входа для консольного приложения.


#include "stdafx.h"

#include <iostream>

using namespace std;


// объявление функции нахождения n!

void faktorial(int numb)// заголовок функции

{

    int rezult = 1; // инициализируем переменную rezult значением 1

    for (int i = 1; i <= numb; i++) // цикл вычисления значения n!

        rezult *= i; // накапливаем произведение в переменной rezult

    cout << numb << "! = " << rezult << endl; // печать значения n!

}


int main(int argc, char* argv[])

{

    int digit; // переменная для хранения значения n!

    cout << "Enter number: ";

    cin >> digit;

    faktorial(digit);// запуск функции нахождения факториала

    system("pause");

    return 0;

}


Так как функция не должна возвращать значение, то тип возвращаемых данных должен быть void. Имя функции - faktorial, внутри круглых скобочек объявлена переменная numb типа int. Эта переменная является параметром функции faktorial().


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

// структура объявления функций возвращающих значения

/*возвращаемый тип данных*/ /*имя функции*/(/*параметры функции*/) // заголовок функции

{

// тело функции

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

}

Структура объявления функций осталась почти неизменной, за исключением двух строк. В заголовке функции сначала нужно определять возвращаемый тип данных, это может быть тип данных int, если необходимо возвратить целое число или тип данных float - для чисел с плавающей точкой. В общем, любой другой тип данных, всё зависит от того, что функция должна вернуть. Так как функция должна вернуть значение, то для этого должен быть предусмотрен специальный механизм, как в строке 5. C помощью зарезервированного слова return  можно вернуть значение, по завершении работы функции. Всё, что нужно, так это указать переменную, содержащую нужное значение, или некоторое значение, после оператора return. Тип данных возвращаемого значения в строке 5 должен совпадать с типом данных в строке 2. Переделаем программу нахождения факториала так, чтобы функция faktorial() возвращала значение факториала.



// struct_func.cpp: определяет точку входа для консольного приложения.


#include "stdafx.h"

#include <iostream>

using namespace std;


// объявление функции нахождения n!

int faktorial(int numb)// заголовок функции

{

    int rezult = 1; // инициализируем переменную rezult значением 1

    for (int i = 1; i <= numb; i++) // цикл вычисления значения n!

        rezult *= i; // накапливаем произведение в переменной rezult

    return rezult; // передаём значение факториала в главную функцию

}


int main(int argc, char* argv[])

{

    int digit; // переменная для хранения значения n!

    cout << "Enter number: ";

    cin >> digit;

    cout << digit << "! = " << faktorial(digit) << endl;// запуск функции нахождения факториала

    system("pause");

    return 0;

}

//Tabs

Теперь функция faktorial() имеет возвращаемый тип данных - int, так как n! - это целое число.   В строке 13 объявлен оператор return, который возвращает значение, содержащееся в переменной rezult. В строке 21 выполняем запуск функции faktorial(), возвращаемое значение которой отправляем в поток вывода с помощью оператора cout. Можно было бы написать так int fakt = faktorial(digit); — переменной типа int присваиваем возвращаемое значение функции faktorial(), после чего в переменной fakt будет храниться значение n!. Результат работы программы не изменился


Мы рассмотрели два типа функций, причём объявление функций выполняли в области программы, после подключения заголовочных файлов, но до начала функции main(). Существует несколько способов объявления функций (см. Рисунок 3).

Рисунок 3 — Функции в С++


На рисунке 3 показаны 4 способа объявления функций в языке программирования С++. Рассмотрим структуры объявления функций в одном файле, с главной функцией. Функции можно объявлять в двух областях, до начала функции main(), после функции main(). До сих пор мы объявляли функции  в одном файле, перед функцией main() - это самый простой из способов.


// struct_func.cpp: определяет точку входа для консольного приложения.


#include "stdafx.h"

/*область 1 - объявление функций до начала main()


место для объявления функций

функциям объявленным в этой области не нужны прототипы


*/

int main(int argc, char* argv[])

{


 return 0;

}

Если функции объявлять в области 1, перед главной функцией, то прототипы для этих функций не нужны. Хорошему стилю программирования соответствует способ объявления функций после main(). Рассмотрим структуру такого объявления функций.

// struct_func.cpp: определяет точку входа для консольного приложения.


#include "stdafx.h"


// место для объявления прототипов функций


int main(int argc, char* argv[])

{


 return 0;

}


/*область 2 - объявление функций после main()


место для объявления функций


*/


Область объявления функций переместилась в самый конец программы, после main(). Что касается самого способа объявления функций , то он не поменялся. Но так как функции объявлены после main(), использовать их не получится, ведь порядок объявлений изменился и функция main() просто не будет видеть функции объявленные после. Так вот для того, чтобы эти функции можно было увидеть в main() существует понятие прототипа. Прототип функции — это заголовок функции, который объявляется перед функцией main(). И если объявить прототип функции, тогда функцию можно будет увидеть в main().


// синтаксис объявления прототипа

/*тип возвращаемых данных функции*/ /*имя функции*/(/*параметры функции*/);

Структура объявления прототипа очень схожа со структурой объявления функции. Разработаем программу, которая определяет, является ли введённое пятизначное число палиндромом. Палиндром — это число или текст, который читается одинаково как слева, так и справа: 93939; 49094; 11311.


// palindrom_func.cpp: определяет точку входа для консольного приложения.


#include "stdafx.h"

#include <iostream>

using namespace std;


bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел


int main(int argc, char* argv[])

{

    cout << "Enter 5zn-e chislo: "; // введите пятизначное число

    int in_number, out_number; // переменные для хранения введённого пятизначного числа

    cin >> in_number;

    out_number = in_number; // в переменную out_number сохраняем введённое число


    if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно

        cout << "Number " << out_number << " - palendrom" << endl;

    else

        cout<<"This is not palendrom"<<endl;

    system("pause");

    return 0;

}

bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел

{

    int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты

    balance1 = number % 10; // переменной balance1 присвоили первый разряд пятизначного числа

    number = number / 10;   // уменьшаем введённое число на один разряд


    balance2 = number % 10; // переменной balance2 присвоили второй разряд

    number = number / 100;  // уменьшаем введённое число на два разряда


    balance4 = number % 10; // переменной balance4 присвоили четвёртый разряд

    number = number / 10;   // уменьшаем введённое число на один разряд


    balance5 = number % 10; // переменной balance5 присвоили пятый разряд

    if ((balance1 == balance5) && (balance2 == balance4))

        return true// функция возвращает истинное значение

    else

        return false; // функция возвращает ложное значение

}


До сих пор мы объявляли функции в одном файле, с основной программой, то есть там, где находится функция main(). В С++ существует возможность поместить объявления функций в отдельный файл, тогда необходимо будет подключать файл с функциями, как в случае с подключением стандартных заголовочных файлов. Есть два способа:

  1. создание файла типа *.cpp, в котором объявляются функции;

  2. создание файлов  типа *.cpp и *.h.

К хорошему стилю программирования относится второй способ. Таким образом, если объявлять функции в другом файле, то делать это согласно способу два. Переделаем программу нахождения палиндрома так, чтобы объявление функции palindrom5() находилось в отдельном файле *.cpp. Файл *.h нужен для того, чтобы скрыть реализацию функций, т. е. в файле *.h будут содержаться прототипы функций. С помощью обозревателя решений MVS создаём файл типа *.h и называем его palendrom.


1

2

3

4

5

// код файла palendrom.h

#ifndef palendrom

#define palendrom

bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел

#endif

Директивы в строках 2,3,5 необходимо всегда объявлять в файлах с прототипами функций, причём прототипы функций всегда объявляются в файлах типа *.h. После директив записанных в строках 2,3, но до директивы #endif объявляются прототипы функций. В строке 4 объявлен прототип функции palindrom5(). Объявление данной функции находится в файле palendrom.cpp, который предварительно тоже был создан с помощью обозревателя решений MVS.

// содержимое файла palendrom.cpp

#include "stdafx.h"

#include "palendrom.h"

bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел

{

    int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты

    balance1 = number % 10; // переменной balance1 присвоили первый остаток

    number = number / 10;   // уменьшаем введённое число на один разряд


    balance2 = number % 10; // переменной balance2 присвоили второй остаток

    number = number / 100;  // уменьшаем введённое число на два разряда


    balance4 = number % 10; // переменной balance4 присвоили четвёртый остаток

    number = number / 10;   // уменьшаем введённое число на один разряд


    balance5 = number % 10; // переменной balance5 присвоили пятый остаток

    if ((balance1 == balance5) && (balance2 == balance4))

        return true// функция возвращает истинное значение

    else

        return false; // функция возвращает ложное значение

}


В файле palendrom.cpp находится объявление функции palindrom5(). Так как файл palendrom.cpp является исполняемым файлом (*.cpp - исполняемые файлы), то в нём обязательно нужно подключить контейнер "stdafx.h", как в строке 2. Чтобы связать файл, где объявлена функция palindrom5() и файл с её прототипом, подключим заголовочный файл (файл с прототипом), это сделано в строке 3. Обратите внимание на то, что при подключении созданного нами файла используются двойные кавычки, а не знаки больше, меньше. Осталось только запустить функцию palindrom5() в главном исполняемом файлеfunc_palendrom.cpp.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

// func_palendrom.cpp: определяет точку входа для консольного приложения.


#include "stdafx.h"

#include <iostream>

// подключение заголовочного файла, с прототипом функции palindrom5()

#include "palendrom.h"

using namespace std;


int main(int argc, char* argv[])

{

    cout << "Enter 5zn-e chislo: "; // введите пятизначное число

    int in_number, out_number; // переменные для хранения введённого пятизначного числа

    cin >> in_number;

    out_number = in_number; // в переменную out_number сохраняем введённое число


    if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно

        cout << "Number " << out_number << " - palendrom" << endl;

    else

        cout<<"This is not palendrom"<<endl;

    system("pause");

    return 0;

}