Задание для индивидуальной работы



1. Составить алгоритм решения задачи.

2. Разработать программу, осуществляющую ввод исходных данных, необходимые вычисления и вывод результатов.

3. Разработать несколько тестовых наборов исходных данных и испытать программу на компьютере.

4. Составить отчет по практической работе.

 

Варианты заданий

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

 

  1. Разработать программу, определяющую во введенном тексте на английском языке слово (слова), в котором (которых) доля гласных (a, e, i, o, u, y) максимальна.

 

  1. Разработать программу шифровки текста из букв. Каждая буква, являющаяся i-й по алфавиту, заменяется на (i+2)-ю букву, предпоследняя буква по алфавиту заменяется первой и т.д.

 

  1. Разработать программу, которая вводит текст и заменяет в ней первые буквы всех слов на заглавные (если слово начинается с заглавной буквы, оставляет его без изменения).

 

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

 

  1. Разработать программу, которая вводит текст и находит в нем все слова указанной длины n(nвводится).

 

  1. Разработать программу, которая вводит текст и выводит буквы, которые встречаются в каждом из слов текста по одному разу или сообщение, что таких букв нет.

 

  1. Разработать программу, определяющую во введенном тексте слова, в которых каждая буква встречается не менее двух раз.

 

  1. Разработать программу, которая вводит текст и определяет наиболее часто встречающийся символ в самом длинном слове этого текста.

 

  1. Разработать программу, которая вводит текст и букву и определяет слово (слова), содержащее наибольшее количество указанных букв.

 

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

 

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

 

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

 

  1. Разработать программу, которая вводит строку и подсчитывает, сколько в каждом слове букв, совпадающих с его первой буквой.

 

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

 

  1. Разработать программу, которая вводит текст на английском языке и выводитслова заданного текста в соответствии с ростом доли гласных в этих словах (a, e, i, o, u, y).

 

  1. Разработать программу, которая вводит текст и слово и заменяет самое длинное слово (слова) текста на введенное слово.

 

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

 

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

 

  1. Разработать программу, которая вводит текст и осуществляет его форматирование следующим образом: каждое предложение теста должно иметь свой порядковый номер и начинаться с красной строки.

 

Практическая работа № 10: Функции. Классы памяти.

Функции – это базовые строительные блоки, из которых состоит любая программа на языке C.Например, к системным функциям относятся рассмотренные printf(), scanf(), gets(), putchar() и др. Функция – самостоятельная единица программы, решающая отдельную четко сформулированную задачу. Они повышают уровень модульности программы, облегчают ее чтение, внесение изменений,отладку и являются основным инструментом реализации принципа повторного использования кода. В частности, функция main() является обязательной для любой программы и служит точкой входа в нее, т. е. первой функцией, выполняемой после запуска программы.

Функцию можно представить в виде "черного ящика" имеющую вход (поступающая в нее информация) и выход (полученные результаты). Все, что происходит внутри черного ящика при ее вызове, программиста не интересует до тех пор, пока не нужно писать программу, реализующую эту функцию. Например, известно, что стандартной функции printf() необходимо передать управляющую строку и возможно несколько аргументов. Известен также результат вызова функции printf(). При этом неважно как он реализован. Использование функций указанным выше способом позволяет сконцентрировать внимание на обшей структуре программы, а не на деталях (нисходящий поход).

В общем виде определение функции выглядит следующим образом:

тип_возврата имя_функции(список параметров)

{

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

return выражение

}

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

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

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

имя_функции(тип имя_перем1, тип имя_перем2, ..., тип имя_перемN)

Таким образом:

function(int i, int k, int j) /* Правильно */

function(int i, k, float j) /* Неправильно */

Ниже приведены примеры функций без параметров и возвращаемого значения, с одним параметром и с двумя параметрами.

//Прототип функции проверки четности числаisodd. Необходим, поскольку определение функции находится ниже определения функции main, где он используется.

int isodd(int value);

 

void print(void)

{

printf("Функция без возвращаемого значения и аргументов\n");

}

 

//Функция нахождения максимального из двух чисел

double max(double a, double b)

{

return (a > b) ? a: b;

}

 

int main(void)

{

print();

printf("%d\n", isodd(6));

printf("%d\n", isodd(9));

printf("%g\n", max(2.5, 5.4));

_getch();

return 0;

}

 

//Функция проверки четности числа

int isodd(int value)

{

return !(value%2);

}

 

Существует два способа прекратить выполнение функции и вернуть управление вызывающейфункции. В первом случаефункция полностью выполняет свои операторы вплоть до закрывающей фигурной скобки }. Примером может послужить приведенная выше функция print(). Как только на консоль будет выведена заданная строка, функции print() ничего не остается делать, и она возвратитуправление в точку, откуда была вызвана (в данном случае в функцию main()). Этот способ используется довольно редко, поскольку, во-первых, онне позволяет реализовать несколько вариантов завершения функции, а во-вторых, в большинстве случаев она должна вернуть некий результат. Для этих целей функция может содержать несколько операторов return, который выполняет две задачи:

· немедленно передает управление из выполняющейся функции в вызывающую;

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

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

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

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

Общий вид прототипа таков:

тип имя_функции(тип парам1, тип парам2, ..., тип парамN);

Указывать имена параметров не обязательно. Единственная функция, для которой не требуется прототип,– функция main(), поскольку она всегда вызывается первой.

Программа должна содержать прототипы всех вызываемыхстандартных библиотечных функций. Для этого в программу следует включить соответствующие заголовочные файлы, поддерживаемые компиляторами языка C и которые обычно имеют расширения .h.Заголовочный файл состоит из двух элементов: определенийпеременных и функций, используемых в библиотечных функциях,а также прототипов самих библиотечных функций. Например, заголовочный файл stdio.h включается почти во все программы, поскольку он содержит прототип функции printf().

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

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

//Глобальная переменная (область видимости и время существования не ограничены)

double PI = 3.14;

//Глобальная статическая переменная (область видимости ограничена файлом)

staticdouble E = 2.72;

 

void incre(void)

{

//Локальная переменная (область видимости и время существования ограничены функцией)

char ch = 'a';

printf("ch = %c\n", ch++);

}

 

void incre2(void)

{

//Статическая переменная (сохраняет свое значение между вызовами функции)

staticchar ch = 'a';

printf("ch = %c\n", ch++);

}

 

int main(void)

{

double E = 5;

int i = 3;

incre(); incre(); incre();

incre2(); incre2(); incre2();

printf("PI = %g\n", PI); //Глобальные переменные доступны во всех функциях

printf("E = %g\n", E); //Локальная переменная перекрывает одноименную глобальную

{

       int i = 4; //Область видимости и время существования локальной переменной ограничены блоком кода

       printf("i = %d\n", i); //Локальная переменная, объявленная в блоке кода, перекрывает одноименную, объявленную в блоке (в данном случае в функции) уровнем выше

}

printf("i = %d\n", i);

_getch();

return 0;

}

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

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

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

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

Передача параметров по значению предусматривает следующие шаги.

1. При компиляции функции выделяются участки памяти для формальных параметров, т.е. формальные параметры оказываются внутренними объектами функции. При этом для параметров типа float формируются объекты типа double, а для параметров типов char и short int – объекты типа int. Если параметром является массив, то создается указатель на начало этого массива, и он служит представлением массива-параметра в теле функции.

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

3. Значения выражений – фактических параметров заносятся в участки памяти, выделенные для формальных параметров функции.

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

5. Никакого влияния на фактические параметры (на их значения) функция не оказывает.

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

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

Рассмотрим в качестве примера функции, которые обменивают местами значения двух переменных. Функция swapVal() обменивает между собой значения переменных xиy, но они никогда не вернуться в функцию main(). Причина в том, что переменные xи y в функции swapVal() не имеют ничего общего с переменными xи y, используемыми в функции main(). Чтобы достичь требуемого результата, следует передавать функции не значения переменных, а их адреса, что позволит получить доступ к содержимому памяти по этим адресам из вызванной функции. Такой способ вызова функции называют “с передачей аргументов по ссылке”, в противоположность вызову с передачей по значению.

void swapVal(int x, int y)

{

int temp;

temp = x;

x = y;

y = temp;

}

 

void swapRef(int *x, int *y)

{

int temp;

temp = *x;

*x = *y;

*y = temp;

}

 

int main(void)

{

int x = 1, y = 2;

swapVal(x, y); //Передача параметров по значению

printf("x = %d\ty = %d\n", x, y);

swapRef(&x, &y); //Передача параметров по ссылке

printf("x = %d\ty = %d\n", x, y);

_getch();

return 0;

}

Массивы и строки также могут быть параметрами функции. В этом случае внутрь функции передается только адрес начала массива. Тогда можно в качестве параметра использовать указатель. Приведем два равноправных прототипа функций:

float fun(int n, float A[ ], float B[ ]);

float fun(int n, float *a, float *b);

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

Задания для самостоятельной работы общее для всех:

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

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

Как известно, квадратное уравнение будет иметь действительные корни, если его дискриминант будет неотрицательным, т.е. когда

Задания для самостоятельной работыиндивидуальное:

1. Разработать функцию, решающую поставленную задачу.

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

3. Разработать несколько тестовых наборов исходных данных и испытать работу функции.

4. Составить отчет по практической работе.

 

Варианты заданий

 

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

 

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

  // прототип функции поиска первого вхождения подстроки в строку, // функция должна возвращать позицию первого вхождения подстроки int occurenceSubstring(char *, char *);  

3. Разработать и испытать функцию, которая определяет длину строки.

// прототип функции определения длины строки

int lengthString(char *);

 

4. Разработать и испытать рекурсивную функцию для вычисления наибольшего общего делителя двух введенных натуральных чисел.

 

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

 

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

 

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

// прототип функции вставки второй строки в первую строку с указанной позиции

char *insertnString (char *, char *, int);

Пример: строка1 – cpp.com, строка2 – studio, номер позиции = 4
результат = cppstudio.com

 

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

 

9. Разработать и испытать функцию, решающую линейное уравнение ax + b = c и возвращающую результат через ссылку. Аргументами функции являются вещественные числа a, b и c. Функция возвращает целое значение: 1, если существует ровно один корень, 0, если корней не существует, и -1, если корней бесконечно много.

 

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

 

11. Разработать и испытать рекурсивную функцию Root (а, b, ε), которая методом деления отрезка пополам находит с точностью ε корень уравнения f(x) = 0 на отрезке [а, b] (считать, что ε > 0, а < b, f(a) - f(b) < 0 и f(x) – непрерывная и монотонная на отрезке [а, b] функция).

 

12. Разработать программу, которая по введенным значениям координат точекА, В, и С находит площадь треугольника АВС. Для этого создать функцию  вещественного типа, находящую длину отрезка АВ на плоскости по координатам его концов: , где  – вещественные параметры. Используя функцию Leng, разработать функцию  вещественного типа, находящую периметр треугольника АВС по координатам его вершин, где  – вещественные параметры. Используя функции Leng и Perim, разработать функцию вещественного типа, находящую площадь треугольника АВС по формуле , где p – полупериметр.

 

13. Разработать и испытать функцию min(X) для определения минимального элемента одномерного массива X, введя вспомогательную рекурсивную функцию minl(k), находящую минимум среди последних элементов массива X, начиная с k-го.

 

14. Разработать и испытать функцию для проверки баланса парных скобок в строке, то есть количество открытых скобок должно совпадать с количеством закрытых, причём необходимо отличать тип скобок – круглые, квадратные, фигурные. Функция возвращает значение типа int равное 0 – если баланс скобок нарушен, равное 1 – если баланс скобок соблюдается, равное -1 – если скобок в строке нет.

  // прототип функции проверки баланса парных скобок int balanceBrackets(char *);  

15. Разработать и испытать функцию: int arrayUnique(int array[], int size), которая удаляет из целочисленного одномерного массива повторяющиеся элементы и возвращает новый размер массива.

 

16. Разработать и испытать функцию, которая переворачивает строку и возвращает указатель на перевёрнутую строку.

// прототип функции инверсии стоки

char *reverseString(char *);

пример:

входная строка: С++
выходная строка: ++С

 

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

 

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

// прототип функции выделения из строки подстроки, начиная с позиции N и длиной k символов

char *сutString(char *, int, int);

 

19. Даны действительные числа Получить:

где u,v,w – комплексные числа:

Определить функции выполнения арифметических операций над комплексными числами.

 

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

 

Практическая работа № 11: Производные типы данных.

Язык Cпозволяет определять и использовать следующие производные типы данных: структуры, объединения и перечисления.

Структура – это совокупность нескольких переменных, часто различных типов, объединяемых под одним именем. Переменные, из которых состоит структура, называются ее членами, элементами или полями. С помощью структур удобно размещать в смежных полях связанные между собой элементы информации. Здесь могут быть собраны различные объекты – переменные, массивы, указатели, другие структуры и т.д. Если в массиве представлены переменные одного типа (например, float), то в структуре могут наличествовать переменные различных типов. Объявление структуры подготавливает шаблон, который можно использовать для создания ее объектов (экземпляров этой структуры). При объявлении структуры определяется агрегатный тип данных, но не переменная.

Определение структуры состоит из двух шагов:

· объявление шаблона структуры (задание нового типа данных);

· определение переменных типа объявленного шаблона.

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

Ниже приведен пример шаблона структуры работника (служащего – employee), включающего поля: имя, фамилия, возраст, размер почасовой оплаты.

struct employee

{

char Name [21];  // имя

char Surname [21]; // фамилия

int age;         // возраст

double hourlysalary; // почасовойоклад

};

Как видно, шаблон структуры struct employee состоит из символьных массивов типа char, целого числа типа int и числа с плавающей точкой двойной точности типа double. Описание элементов производится в фигурных скобках, после закрывающей скобки обязательна точка с запятой.

Переменные структуры объявляются так же, как и переменные других типов. На основе приведенного шаблона сделаем несколько объявлений новых структурных переменных:

struct employee new_employee, * employeePtr, stack[120];

Здесь new_employee – переменнаятипа struct employee, *employeePtr – указательна struct employee, stack[120] – массивиз 120 элементовтипа struct employee.

Объявление переменных может быть объединено с определением структуры, а именно:

struct employee

{

char Name [20+1];  // имя

char Surname [20+1]; // фамилия

int age;           // возраст

double hourlysalary; // почасовойоклад

} new_employee, *employeePtr, stack[120];

Указание имени не является для структуры обязательным. Если определение структуры не содержит его, то переменные данного типа могут быть объявлены только в ее определении, но не отдельно.

При создании структур часто используется ключевое слово typedef. Оно предоставляет программисту средство создания синонимов (или псевдонимов) для ранее определенных типов данных.К нему часто обращаются для того, чтобы дать укороченное имя структурному типу. Например, оператор вида

typedefstruct employee Employee;

определяет новый тип с именем Employee как синоним типа struct employee.

Ключевое слово typedef может быть использовано в определении типа структуры без указания его имени. Например,

typedefstruct

{

char *Name;     // имя

char *Surname;  // фамилия

int age;        // возраст

double hourlysalary; // почасовойоклад

} Employee;

создает тип Employee без использования отдельного оператора typedef. В данном примере необходимо предусмотреть выделение памяти под символьные указатели.

Теперь созданный тип Employee можно использовать для объявления структурных переменных определенного типа, например

Employeestack[120];

Синтаксис инициализации структур аналогичен инициализации массивов. Например, выполниминициализацию ранее определеннойструктурыstruct employee:

struct employee new_employee = { "Иван", "Иванов", 25, 6.78 };

При инициализации структуры ее элементы (инициализаторы) должны соответствовать заданному типу и отделяться друг от друга запятыми.

Доступ к элементам (компонентам, полям) структуры осуществляется двумя способами:

1. с помощью оператора точки. при непосредственной работе со структурой;

2. с помощью оператора стрелки –> при использовании указателей на структуры.

Общий формат доступа к элементам структуры имеет вид

имя_переменной_структуры.имя_поля;

имя_указателя_на_структуру–>имя_поля;

(*имя_указателя_на_структуру).имя_поля;

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

new_employee.hourlysalary = 21.0;

employeePtr->hourlysalary = 21.0;

Здесь new_employee – это имя всего объекта-структуры, а hourlysalary – имя элемента этой структуры. Аналогично и в случае использования указателя *employeePtr на структуру.

Когда объявлен массив структур, например stack[120], это означает, что создано 120 наборов переменных, каждый из которых организован так, как определено в структуре с именем employee. Чтобы получить доступ к определенной структуре stack[120], следует указать имя массива с индексом, который изменяется от 0 до 119. Например, для пятой структуры сделать изменения в почасовом окладе можно следующим образом:

stack[4].hourlysalary = 121.5;

или

(stack+4)->hourlysalary = 121.5;

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

struct date // Структура дата

{

int day; // день

int month; // месяц

int year; // год

};

 

struct employee

{

char Name [20];   // имя

char Surname [20]; // фамилия

int age;          // возраст

double hourlysalary; // почасовойоклад

struct date birthday; // деньрождения

};

Инициализация вложенной структуры может быть следующей:

new_employee.birthday.year = 1990;

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

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

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

enum имя_типа_переч {список_констант} список_перем;

Имя_типа_переч и список_перем указывать не обязательно (однако хотябы один из этих элементов объявления должен присутствовать).

В следующем фрагменте кода определяется перечисление месяцев года с именем month и объявляется соответствующая переменная, которой присваивается значение «апрель»:

enum month {jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec};

enum month m = apr;

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

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

enum month {jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec};

При этом разным константам может соответствовать одно и то же целое число:

enum flag {off = 0, no = 0, on = 1, yes = 1};

Объединение – это область памяти, которая используется для хранения переменных разных типов. Объединение позволяет интерпретировать один и тот же набор битов по-разному. Объявление объединения напоминает объявление структуры. Вот его общий вид:

union имя_типа_объединения

{

тип имя_члена;

тип имя_члена;

тип имя_члена;

...

} имена_экземпляров_объединения;

Например:

union u_type

{

int i;

char ch;

};

Это объявление не создает никаких переменных. Чтобы объявить экземпляр объединения, нужно либо указать его имя в концеобъявления, либо применить отдельный оператор объявления.Рассмотрим пример программы на языке C, в котором объявляетсяэкземпляр cnvt объединения u_type:

union u_type cnvt;

В переменной cnvt целочисленная переменная i и символьная переменная ch хранятся в одной и той же области памяти. Разумеется, переменная i занимает 4 байта, а переменная ch – только 1. Обе переменные используют одну и ту же область памяти. Влюбом месте программы на переменную cnvt можно ссылаться,считая, что в ней хранится либо целое число, либо символ.

При объявлении экземпляра объединения компилятор автоматически выделяет память, достаточную для хранения наибольшего члена объединения. Например, если считать, что целые числа занимают 4 байта, размер переменной cnvt равен 4 байта, потому что в ней должна храниться целочисленная переменная i, хотя переменная ch занимает только один байт.

Для доступа к членам объединения используются те же синтаксические конструкции, что и для доступа к членам структуры.Например, чтобы присвоить элементу i объединения cnvt число 10,следует выполнить следующий оператор:

cnvt.i = 10;

Задания для самостоятельной работы:Определить структуру «Группа» с полями: номер группы, курс и структуру “Студент” с полями: номер зачетной книжки, имя, фамилия, пол (реализовать в виде перечисления), указатель на структуру «Группа». Объявить и инициализировать глобальный массив студентов. Написать функцию, выводящую на экран список студентов заданной группы.

 


Дата добавления: 2018-04-05; просмотров: 827; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!