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

Информатика Экзамен

.pdf
Скачиваний:
10
Добавлен:
02.05.2015
Размер:
738.97 Кб
Скачать

4

using namespace std;

5

 

6

struct part // объявление структуры

7{

8int modelnumber; // номер модели изделия

9int partnumber; // номер детали

10float cost; // стоимость детали

11};

12

13void main()

14{

15part part1; // определение структурной переменной

16part1.modelnumber = 6244; // инициализация полей

17part1.partnumber = 373; // переменной part1

18part1.cost = 217.55F;

19

20// вывод значений полей на экран

21cout << "Модель " << part1.modelnumber;

22cout << ", деталь " << part1.partnumber;

23cout << ", стоимость $" << part1.cost << endl;

24}

Результат работы программы выглядит следующим образом:

Модель 6244, деталь 373, цена $217.55

В программе PARTS присутствуют три основных аспекта работы со структурами: определение структуры, определение переменной типа этой структуры и доступ к полям структуры. Рассмотрим каждый из этих аспектов.

Определение структуры

Определение структуры в языке С++ задает ее внутреннюю организацию, описывая поля, входящие в состав структуры:struct part

{

int modelnumber;

int partnumber;

float cost;

};

Синтаксис определения структуры

Определение структуры в языке С++ начинается с ключевого слова struct. Затем следует имя структуры, в данном случае этим именем является part. Объявления полей структуры modelnumber, partnumber и cost заключены в фигурные скобки. После закрывающей фигурной скобки следует точка с запятой (;) – символ, означающий конец определения структуры. Обратите внимание на то, что использование точки с запятой после блока операторов при определении структуры отличает синтаксис структуры от синтаксиса других рассмотренных нами элементов про­граммы. Как мы видели, в циклах, ветвлениях и функциях блоки операторов тоже ограничивались фигурными скобками, однако точка с запятой после таких блоков не ставилась.

Смысл определения структуры

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

Определение структурной переменной

Первый оператор функции main() выглядит следующим образом:part part1;

Он представляет собой определение переменной part1, имеющей тип part. Определение переменной означает, что под эту переменную выделяется память.

Доступ к полям структуры

Когда структурная переменная определена, доступ к ее полям возможен с применением пока неизвестной нам операции точки. В программе первому из полей структуры присваивается значение при помощи оператораpart1.modelnumber = 6244;

Поле структуры идентифицируется с помощью трех составляющих: имени структурной переменной part1, операции точки (.) и имени поля modelnumber. Подобную запись следует понимать как «поле modelnumber переменной part1». Операция точки в соответствии с общепринятой терминологией называется операцией доступа к полю структуры, но, как правило, такое длинное название не употребляют.

Обратите внимание на то, что в выражении с использованием операции точки (.) на первом месте стоит не название структуры (part), а имя структурной переменной (part1). Имя переменной нужно для того, чтобы отличать одну переменную от другой: part1 от part2 и т. д. С полями структурной переменной можно обращаться так же, как с обычными простыми переменными. Так, в результате выполнения оператораpart1.modelnumber = 6244;

полю modelnumber присваивается значение 6244 при помощи обычной операции присваивания. В программе также продемонстрирован вывод значения поля на экран с помощью cout:cout << "Модель " << part1.modelnumber;

Инициализация полей структуры

Следующий пример демонстрирует способ, при помощи которого можно инициализировать поля предварительно определенной структурной переменной. В программе используются две структурные переменные.1 // partinit.cpp - инициализация структурных переменных

2

#include "iostream"

3

 

4

using namespace std;

5

 

6struct part // объявление структуры

7{

8int modelnumber; // номер модели изделия

9int partnumber; // номер детали

10float cost; // стоимость детали

11

12 };

13

14 //////////////////////////////////////////////////////////

15

16void main()

17{

18part part1 = {6244,373,217.55F }; // инициализация переменной

19

part part2;

// объявление переменной

20

21// вывод полей первой переменной

22cout << "Модель " << part1.modelnumber;

23cout << ", деталь " << part1.partnumber;

24cout << ", стоимость $" << part1.cost << endl;

26

part2 = part1; // присваивание структурных переменных

27

28// вывод полей второй переменной

29cout << "Модель " << part2.modelnumber;

30cout << ". деталь " << part2.partnumber;

31cout << ". стоимость $" << part2.cost << endl;

32}

В приведенной программе определены две переменные типа part: part1 и part2. После того как поля переменной part1 инициализированы, происходит вывод их значений на экран, затем значение переменной part1 присваивается переменной part2, и значения ее полей также выводятся на экран. Результат работы программы выглядит следующим образом:

Модель 6244, часть 373, цена $217.55

Модель 6244, часть 373, цена $217.55

Неудивительно, что обе выведенные строки идентичны, поскольку значение второй переменной было присвоено первой переменной.

Инициализация полей переменной part1 производится в момент ее определения:part part1 = {6244,373,217.55F };

Значения, которые присваиваются полям структурной переменной, заключены в фигурные скобки и разделены запятыми. Первая из величин присваивается первому полю, вторая — второму полю и т. д

Присваивание структурных переменных

Как мы видим из программы PARTINT, мы можем присваивать значение одной структурной переменной другой структурной переменной:part2 = part1;

Значение каждого поля переменной part1 присваивается соответствующему полю переменной part2. Поскольку в больших структурах число полей иногда может измеряться десятками, для выполнения присваивания структурных переменных компилятору может потребоваться проделать большое количество работы

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

Вложенные структуры

Структуры в языке С++ допускают вложенность, то есть использование структурной переменной в качестве поля какой-либо другой структуры.struct Distance

{

int feet;

float inches;

};

struct Room

{

Distance length;

Distance width;

};

Доступ к полям вложенных структур

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

(.):dining.length.feet = 13;

В этом операторе dining — имя структурной переменной, как и раньше; Length — имя поля внешней структуры Room; feet — имя поля внутренней структуры Distance. Таким образом, данный оператор берет поле feet поля Length переменной dining и присваивает этому полю значение, равное 13.

Инициализация и вложенные структуры

Далее описывается методика инициализации структурной переменной, которая содержит внутри себя поле, также являющееся структурной переменной:Room dining = { {13, 6.5),{10, 0.0} };

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

Первая из внутренних структур инициализируется с помощью конструкции:{13, 6.5}

а вторая – с помощью конструкции:

view source

print

?{10, 0.0}

21.

Формальные и фактические параметры

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

Список параметров (фактических или формальных — всё равно) записывается в круглых скобках сразу за именем функции. В принципе, список параметров может быть пустым, но скобки за именем функции обязательны!

Список фактических параметров — это те реальные данные, с помощью которых можно настроить алгоритм подпрограммы на обработку конкретных данных. Фактические параметры указываются в списке параметров при вызове функции и передаются в эту функцию. В нашем примере при вызове функции fmax() в списке фактических параметров указаны две переменные: a и b. Это реальные объекты, под которые в функции main() выделена память, они могут иметь какие-то значения и т.д.

Список формальных параметров — это по сути набор требований, которые предъявляет подпрограмма к передаваемым в неё данным. Список фактических параметров записывается в заголовке функции при её определении в скобках. Для каждого параметра необходимо указать тип и имя. При необходимости задаётся и способ передачи (об этом позже — в следующей теме). Имена формальных параметров локализованы в подпрограмме и дополняют перечень локальных объектов этой подпрограммы. Так, в нашей функции fmax() формальные параметры x и y типа double дополняют список локальных переменных, состоящий из одной переменной max типа double. В итоге функция fmax() имеет три локальных переменных, известных только в этой функции.

Между списками фактических и формальных параметров должно выдерживаться полное соответствие по количеству параметров, их типу, порядку следования и способу передачи в функцию. Несоблюдение этих требований в лучшем случае (для программиста) приводит к ошибке на стадии компиляции, в худшем — к «багам» программы, которые будут время от времени проявляться во время выполнения программы. «Выловить» же такого рода ошибки очень непросто. Как правило, они остаются в программе в течение всего периода её использования. Поэтому исключительно важно соблюдать правильность передачи данных в подпрограмму.

22.

C++. Использование указателей в качестве аргументов функций

ВC++ указатели можно использовать в качестве аргументов функций. Так, если в роли параметра функции выступает массив, то в функцию передается указатель на его первый элемент. Получается автоматическая передача массива в функцию, используя его адрес.

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

Задача

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

Решение

Понятно, что алгоритм решения этой задачи без применения функции будет очень громоздким. Разобьем задачу на подзадачи:

вычисление среднего арифметического элементов массива;

определение простого числа;

удаления элемента из массива;

упорядочивание массива;

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

float sr_arifm(int *x, int n) — вычисляет среднее арифметическое массива x из n элементов (рис. ниже)

bool prostoe(int n) — проверяет, является ли целое n простым, результат логическое значение true, если число простое, и false в противном случае (рис. ниже);

void udal(int *x, int m, int*n) — удаляет элемент с номером m в массиве x из n элементов (рис. ниже)

void upor(int *x, int N, bool pr=true) — сортирует массив x из n элементов по возрастанию или по убыванию, направление сортировки зависит от значения параметра pr, если pr=true, то выполняется сортировка по возрастанию, иначе по убыванию.

Вот так будет выглядеть текст программы:

#include "stdafx.h" #include <iostream> using namespace std;

//функция вычисления среднего значения float sr_arifm(int *x, int n)

{

int i; float s=0;

for (i=0; i<n; s+=x[i], i++); if (n>0) return (s/n); else return 0;

}

//функция для определения простого числа bool prostoe(int n)

{

bool pr; int i;

for (pr=true, i=2; i<=n/2; i++) if (n%i==0) {pr=false; break;} return (pr);

}

//функция удаления элемента из массива void udal (int *x, int m, int *n)

{

int i;

for (i=m; i<*n-1; *(x+i)=*(x+i+1), i++); -*n;

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

}

//функция сортировки массива void upor(int *x, int n, bool pr=true)

{

int i, j, b; if (pr)

{

for (j=1; j<=n-1; i++) for(i=0; i<=n-1-j; i++) if (*(x+i)>*(x+i+1))

{

b=*(x+i);

*(x+i)=*(x+i+1);

*(x+i+1)=b;

}

}

else for (j=1; j<=n-1; j++) for(i=0; i<=n-1-j; i++)

if (*(x+i)<*(x+i+1))

{

b=*(x+i);

*(x+i)=*(x+i+1);

*(x+i+1)=b;

}

}

int main()

{

int *a, n, i; float sr;

cout<<"n="; cin>>n; //вывод рзмерности массива a=(int *)calloc(n, sizeof(int)); //выделение памяти cout<<"Vvedite massiv A \n";

for (i=0; i<n; i++) //ввод массива cin>>*(a+i);

sr=sr_arifm(a, n); //вычисление среднего арифметического

cout<<"sr="<<sr<<"\n"; //вывод среднего арифметического

for (i=0; i<n;)

{

if (prostoe(*(a+i))&& *(a+i)<sr) //если число простое и меньше среднего

udal (a, i, &n); //удалить его из массива

else i++; //иначе перейти к следующему элементу

}

cout<<"Massiv A \n"; //вывод модифицированного массива

for (i=0; i<n; i++) cout<<*(a+i)<<"\t";

cout<<"\n";

upor (a, n); //сортировка массива

cout<<"Upor massiv A \n"; //вывод упорядоченного массива

for (i=0; i<n; i++) cout<<*(a+i)<<"\t";

cout<<"\n";

free(a); //освобождение памяти

system("pause");

return 0;

}

23.

C++. Функции. Шаблоны. Локальные и глобальные переменные

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

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

template <class Type> заголовок

{

тело функции

}

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

Рассмотрим пример шаблона поиска наименьшего из четырех чисел.

#include "stdafx.h"

#include <iostream>

using namespace std;

//опредилим абстрактный тип данных

//с помощью служебного слова Type

template <class Type>

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

//типа данных Type

Type minimum(Type a, Type b, Type c, Type d)

{

Type min=a;

if (b<min) min=b;

if (c<min) min=c;

if (d<min) min=d;

return min;

}

int main ()

{

int ia, ib, ic, id, mini; float ra, rb, rc, rd, minr;

cout<<"vvod 4 theluh chisla \t"; cin>>ia>>ib>>ic>>id;

//вызов функции minimum, в которую

//передаем 4 целых значения

mini=minimum(ia, ib, ic, id);

cout<<"\n minimalnoe chislo= "<<mini<<"\n";

cout<<"vvod 4 vechestvennuh chisla \t"; cin>>ra>>rb>>rc>>rd;

//вызов функции minimum, в которую

//передаем 4 вещественных числа

minr=minimum(ra, rb, rc, rd);

cout<<"\n minimalnoe chislo= "<<minr<<"\n";

system("pause");

return 0;

}

Так выглядит результат работы программы:

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

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

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

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

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

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

Рассмотрим пример:

#include "stdafx.h"

#include <iostream>

using namespace std;

float pr=100.678; //переменная pr определенна глобально

int prostoe (int n)

{

int pr=1,i; //переменная pr определенна локально

if (n<0) pr=0;

else

for (i=2; i<=n/2; i++)

if (n%i==0) {pr=0; break;}

cout<<"local pr="<<pr<<"\n"; //вывод локальной переменной

cout<<"global pr="<<::pr<<"\n"; //вывод глобальной переменной

return pr;

}

int main ()

{

int g;

cout<<"g="; cin>>g;

if (prostoe(g)) cout<<"g - prostoe \n";

else cout<<"g - ne prostoe \n";

system("pause");

return 0;

}

24.

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

Например, Андрей работает в компании X, а ID (сокр. от англ. Identifier — идентификатор) его как работника равен 123. Олег работает в компании Y, а его ID также равен 123. Единственное (с точки зрения некой системы учёта), благодаря чему Андрей и Олег могут быть различимы при совпадающих ID, это их принадлежность к разным компаниям. Различие компаний в этом случае представляет собой систему различных пространств имён (одна компания — одно пространство). Наличие двух работников в компании с одинаковыми ID представляет большие проблемы при их использовании, например, по платёжному чеку, в котором будет указан работник с ID 123, будет весьма затруднительно определить работника, которому этот чек предназначается.