Файл: Лабораторная работа 1 Изучение среды разработки программ 3 Лабораторная работа 2 Исследование базовых типов данных языка Си 18.doc

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

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

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

Добавлен: 05.12.2023

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

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

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

СОДЕРЖАНИЕ

Лабораторная работа № 1Изучение среды разработки программ

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Лабораторная работа № 2Исследование базовых типов данных языка Си

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 3Исследование операций языка Си Цель занятия: Совершенствование навыков объявления, инициализации переменных и ввода и вывода информации Совершенствование навыков разработки программ в среде программирования MS Visual C++ Исследование возможностей языка С++ для реализации арифметических, логических и поразрядных операций над данными Время на выполнение работы: 4 часаПрограмма исследований: Исследование арифметических операций Исследование логических операций Исследование поразрядных операций Подготовка к выполнению работы: Изучить рекомендованную литературу (структура программы на языке высокого уровня, алфавит и элементарные конструкции языка Си, переменные и константы, стандартные типы данных, выражения и операции в языке Си). Изучить материал настоящего руководства. Материалы для подготовки к занятию: Конспект лекций. [1] стр. 31-38. Содержание отчета: Цели исследования. Программа работы. Листинги программ. Результаты исследований. Выводы по каждому пункту и общий вывод. МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ Любое выражение языка состоит из операндов (переменных, констант и др.), соединенных знаками операций. Знак операции - это символ или группа символов, которые сообщают компилятору о необходимости выполнения определенных арифметических, логических или других действий. Операции выполняются в строгой последовательности. Величина, определяющая преимущественное право на выполнение той или иной операции, называется приоритетом. В таблице 3.1 перечислены различные операции языка Си. Их приоритеты для каждой группы одинаковы. Чем большим преимуществом пользуется соответствующая группа операций, тем выше она расположена в таблице. Приоритеты могут регулироваться с помощью круглых скобок. Таблица 3.1 – Операции языка Си Знак операции Назначение операции ( ) Вызов функции [ ] Выделение элемента массива . Выделение элемента записи -> Выделение элемента записи (тождественно(.)) ! Логическое отрицание Поразрядное отрицание - Изменение знака ++ Увеличение на единицу -- Уменьшение на единицу & Взятие адреса * Обращение по адресу (тип) Преобразование типа (т.е. (float) a) sizeof( ) Определение размера в байтах * Умножение / Деление % Определение остатка от деления + Сложение - Вычитание << Сдвиг влево >> Сдвиг вправо < Меньше, чем <= Меньше или равно > Больше, чем >= Больше или равно = = Равно != Не равно & Поразрядное логическое "И" ^ Поразрядное исключающее "ИЛИ" | Поразрядное логическое "ИЛИ" && Логическое "И" || Логическое "ИЛИ" ?: Условная (тернарная) операция = Присваивание +=, - =, *=, /=, %=, <<=,>>=, &=, |=, ^= Бинарные операции (например, а *= b(т.е. a = a * b) и т.д.) , Операция запятая Для исключения путаницы в понятиях "операция" и "оператор", необходимо отметить, что оператор - это наименьшая исполняемая единица программы. Различают операторы выражения, действие которых состоит в вычислении заданных выражений (например: a = sin(b)+c; j++;), операторы объявления, составные операторы, пустые операторы, операторы метки, цикла и т.д. Для обозначения конца оператора в языке С++ используется точка с запятой. Что касается составного оператора (или блока), представляющего собой набор логически связанных операторов, помещенных между открывающей ({) и закрывающей (}) фигурными скобками ("операторными скобками"), то за ним точка с запятой не ставится. Отметим, что блок отличается от составного оператора наличием определений в теле блока. Охарактеризуем основные операции языка С++. Сначала рассмотрим одну из них - операцию присваивания (=). Выражение вида х = у + z;присваивает переменной х значение суммы переменных у и z. Наличие « ; » в конце операции говорит о том, что записан оператор. На первый взгляд все просто. Но очень часто у начинающих программистов возникает путаница в понимании этого оператора. Это связано с тем, что с точки зрения математики следующие два выражения в общем-то эквивалентны:х = у + z;у + z = х;Но программирование – есть процесс записи на формализованном языке последовательности команд, которые необходимо выполнить для достижения конечного результата. Из этого аспекта и вытекает ключевая разница из этих, казалось бы, тождественных выражений.Для любого языка программирования операция присваивания « = » в обязательном порядке подразумевает следующий порядок ее выполнения. Справа от знака « = » задается источник присваивания (то, что присваивается), а слева – приемник (или то, чему присваивается источник): х = у + z; Приемник Источник Первым вычисляется результат источника, который затем присваивается приемнику, НО НЕ НАОБОРОТ! Именно поэтому выражение у + z = х не имеет смысла! Источником может быть любая последовательность операций. Приемником – только переменная.По этой же причине оператор у + z;тоже бессмыслен, так как результат операции никуда не сохранен! (За исключением использования механизма перегрузки операции в классах, который будет рассмотрен во втором семестре). Операцию "=" разрешается использовать многократно в одном выражении, например: x = y = z = 100;Различают унарные, бинарные итернарные операции. У первых из них один операнд, у вторых – два и у третьих - три. В языке Си выделяют три группы операций: арифметические операции; логические операции и операции отношения; операции с битами. 1. Арифметические операции задаются следующими символами (таблица 3.1): +, -, *, /, %, -, !, . Например: a = b + c;a = b - c;a = b * c;a = b / c;a = b % c; a = !b;a = -b;a = b;a = sizeof (b);Операции +, -, * интуитивно понятны и не нуждаются в объяснении.Операции увеличения и уменьшения на 1 (++ и --).Эти операции, называемые также инкрементом и декрементом, имеют две формы записи - префиксную, когда операция записывается перед операндом, и постфиксную. В префиксной форме сначала изменяется операнд, а затем его значение становится результирующим значением выражения, а в постфиксной значением выражения является исходное значение операнда, после чего он изменяется.Операция определения размера sizeof предназначена для вычисления размера объекта или типа в байтах, и имеет две формы:sizeof выражение или sizeof( тип )Операции отрицания (-, ! и ). Арифметическое отрицание (унарный минус-) изменяет знак операнда целого или вещественного типа на противоположный. Логическое отрицание(!) дает в результате значение 0, если операнд есть истина( не нуль), и значение 1, если операнд равен нулю. Операнд должен быть целого или вещественного типа, а может иметь также тип указатель. Поразрядное отрицание(), часто называемое побитовым, инвертирует каждый разряд в двоичном представлении целочисленного операнда.Деление (/) и остаток от деления(%). Операция деления применима к операндам арифметического типа. Если оба операнда целочисленные, результат операции округляется до целого числа, в противном случае тип результата определяется правилами преобразования. Операция остатка от деления применяется только к целочисленным операндам. Знак результата зависит от реализации.Бинарные операции +=, -=, *= и /= эквивалентны следующим: a += 3;a -= 3;a *= 3;a /= 3;  a = a + 3;a = a - 3;a = a * 3;a = a / 3; 2. Поразрядные операции задаются следующими символами (таблица 3.1): <<, >>, &, |, ^. Например:a = b << 3;a = b >> 2;a = b & c;a = b | c;a = b ^ c;Операции сдвига (<< и >>) применяются целочисленным операндам. Они сдвигают двоичное представление первого операнда влево или вправо на количество двоичных разрядов, заданное вторым операндом. При сдвиге влево (<<) освободившиеся разряды обнуляются. При сдвиге вправо (>)освободившиеся биты заполняются нулями, если первый операнд беззнакового типа, и знаковым разрядом в противном случае. Операции сдвига не учитывают переполнение и потерю значимости.Примеры: int i=10, j, k ; /* i = 0000 1010 */k = i<<2 ; /* k = 0010 1000 */j = k<<1 ; /* j = 0101 0000 */i = j>>4 ; /* i = 0000 0101 */Битовые операции (&, |, ^) применяются только к целочисленным операндам и работают с их двоичными представлениями. При выполнении операций операнды сопоставляются побитового (первый бит первого операнда с первым битом второго, второй бит первого операнда со вторым битом второго, и т д.).При поразрядной конъюнкции, или поразрядном И (операция обозначается &) бит результата равен 1 только тогда, когда соответствующие биты обоих операндов равны 1.При поразрядной дизъюнкции, или поразрядном ИЛИ (операция обозначается |) бит результата равен 1 тогда, когда соответствующие биты хотя бы одного из операндов равен 1.При поразрядном исключающем ИЛИ (операция обозначается ^) бит результата равен 1 только тогда, когда соответствующий бит только одного из операндов равен 1.Примеры: int i=6, j=5, k ; /* i = 0110, *//* j = 0101 *//* --------- */k = i&j ; /* k = 0100 */k = i|j ; /* k = 0111 */k = j^j ; /* k = 0011 */3. Логические операции и операции отношения задаются следующими символами (таблица 3.1): <, <=, >, >=, ==, !=, &&, ||.Логические операции (&&и ||). Операнды логических операций И (&&) и ИЛИ (||) могут иметь арифметический тип или быть указателями, при этом операнды в каждой операции могут быть различных типов. Преобразования типов не производятся, каждый операнд оценивается с токи зрения его эквивалентности нулю (операнд, равный нулю, рассматривается как false, не равный нулю - как true).Результатом логической операции является true или false. Результат операции логическое И имеет значение true только если оба операнда имеют значение true. Результат операции логическое ИЛИ имеет значение true, если хотя бы один из операндов имеет значение true. Логические операции выполняются слева направо. Если значение первого операнда достаточно, чтобы определить результат операции, второй операнд не вычисляется. Результаты логических операций могут быть представлены следующим образом:Таблица 3.2 – Логические операции языка Си x y x && y x || y 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 1 Операции отношения (<, <=, >, >=, = =, !=) сравнивают первый операнд со вторым. Операнды могут быть арифметического типа или указателями. Результатом операции является значение true или false (любое значение, не равное нулю, интерпретируется как true). Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции сравнения. Результаты операций отношения могут быть представлены следующим образом:Таблица 3.3 – Операции отношения языка Си  x y x < y x <= y x > y x >= y x = = y x != y 0 0 false true false true true false 0 1 true true false false false true 1 0 false false true true false true 1 1 false true false true true false 1>2>1   2   3   4   5   6   7   8   9   ...   22

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ Исследование арифметических операций для заданных исходных данных исследовать влияние типа данных на конечный результат для всех арифметических операций. Пример:typedef signed short int INT;int main(int argc, char* argv[]){INT a=12678, b=-19003, c;float x=a,y=b,z;char d=156,e=68,f;cout<<"\n------------------\nInteger: a="<c=a-b; cout<<"\n-: "<c=a*b; cout<<"\n*: "<c=a/b; cout<<"\n/: "<c=a%b; cout<<"\n%: "<c=-a; cout<<"\n-: "<c=!a; cout<<"\n!: "<c=a; cout<<"\n

Лабораторная работа № 4Применение управляющих инструкций языка для организации ветвлений в программе

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

ЗАДАНИЕ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ

Лабораторная работа № 5Исследование циклов

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 6Применение массивов и указателей для решения прикладных задач

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Лабораторная работа № 7Исследование массивов и указателей

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 8Применение функций работы со строками для решения прикладных задач

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Практическое занятие № 6Использование функций для работы с массивами

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Практическое занятие № 7Программирование рекурсивных алгоритмов

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Практическое занятие № 8Применение производных типов данных для решения прикладных задач

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Лабораторная работа № 5Исследование методов доступа к файлам данных

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 6Исследование связанных списков данных

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

ЛИТЕРАТУРА

cout:

cout « *names; // Печать Сергей

Для вывода второй строки используется следующий оператор cout:

cout *(names+1); // Печать Михаил

При обращении к элементу массива при помощи оператора *, получаем доступ к одной из строк массива. Можно использовать возвращаемое этим оператором значение везде, где можно использовать строковую констан­ту или символьный массив.

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

  • копирования строк (strcpy, strncpy);

  • сравнения строк (strcmp, strncmp);

  • объединения строк (strcat, strncat);

  • поиска подстроки (strstr);

  • поиска вхождения символа (strchr, strrchr, strpbrk);

  • определения длины строки (strlen);

  • преобразования строки в число (atoi, atoll, atof);

  • и так далее.

Более подробно функции работы со строками рассмотрены в [1] стр. 91, 416.

Учитывая, что строки состоят из символов, полезно знать некоторые функции работы с символами. Для работы с символами служит библиотека ctype (заголовочный файл ctype.h). Она содержит:

  1. Функции проверки на принадлежность символа множеству:

  • isalmum(c) – букв и цифр (A-Z, a-z, 0-9);

  • isalfa(c) – букв (A-Z, a-z);

  • iscntrl(c) – управляющих символов (с кодами 0…31 и 127);

  • isdigit(c) – цифр (0-9);

  • isgraph(c) – печатаемых символов кроме пробела;

  • islower(c) – букв нижнего регистра (a-z);

  • isprint(c) – печатаемых символов;

  • ispunct(c) – знаков пунктуации;

  • isspace(c) – символов-разделителей;

  • isupper(c) – букв верхнего регистра (A-Z);

  • isxdigit(c)- шестнадцатеричных цифр.

  • Функции преобразования символов:

    • tolower(c) - к нижнему регистру;

    • toupper(c) к верхнему регистру.

    Более подробно функции работы с символами рассмотрены в [1] стр. 92, 416.

    1   ...   8   9   10   11   12   13   14   15   ...   22

    ПРОГРАММА РАБОТЫ


    1. Изучение способов формирования строк в языке Си

    • Набрать и отладить программу:

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

    {

    char Arr1[25];

    char Arr2[]={"Second string!"};

    char Arr3[]={'T','h','i','r','d',' ',

    's','t','r','i','n','g'};

    char *Arr4="Fouth string";

    cout<<"\nEnter string: \"First string\": ";

    cin>>Arr1;

    cout<<"\nString 1: "<Оператор 1

    cout<<"\nString 2: "<Оператор 2

    cout<<"\nString 3: "<Оператор 3

    cout<<"\nString 4: "<Оператор 4

    return 0;

    }

    • Проанализировать результат работы программы и ответить на вопрос, почему Оператор 2 и Оператор 4 выводят на экран свои фразы полностью, а оператор 1 – только ее часть.

    • Почему Оператор 3 выводит свою фразу своей строки и чужую.

    • Что нужно сделать, чтобы Оператор 3 выводил только свою фразу.




    1. Применение функций работы со строками для обработки символьных массивов

    • Набрать и отладить программу заполнения числового массива из символьной строки:

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

    {

    char str[]="2, 75.3, 24.45, 55, 0, 0.37";

    char *ptr=str; //Оператор 1

    float Arr[10];

    int i=0;

    printf("\nИсходная строка:\n%s\n",str);

    do

    {

    Arr[i]=atof(ptr); //Оператор 2

    i++;

    if (i>9) break;

    }while(ptr=strchr(ptr,','),ptr++); //Оператор 3

    printf(“\nМассив чисел: \n“)

    for (int s=0;s

    printf("%5.2f\n", Arr[s]);

    return 0;

    }

    • Проанализировать результат работы программы и ответить на вопрос: что происходит при выполнении Операторов 1-3.

    Занятие 9

    Лабораторная работа № 9
    Использование функций для решения прикладных задач



    Цель занятия:


    • Совершенствование навыков разработки программ в среде программирования MS Visual C++

    • Совершенствование навыков использования циклов и ветвлений в программах

    • Получение начальных навыков в объявлении и использовании функций


    Время на выполнение работы: 2 часа
    Учебные вопросы:


    1. Изучение порядка объявления и описания функций

    2. Изучение порядка вызова функций


    Подготовка к выполнению работы:


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

    2. Изучить материал настоящего руководства.


    Материалы для подготовки к занятию:


    1. Конспект лекций

    2. [1] стр. 73-78.


    ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

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

    С понятием функции в языке C++ связано три следующих компонента:

    • описание функции;

    • прототип;

    • вызов функции.

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

    [тип_результата] <имя_функции> [спсок_параметров])

    {

    /* объявления и операторы

    или, другими словами, тело функции*/

    }

    Здесь тип_результата тип возвращаемого значения. В случае отсутствия спецификатора типа предполагается, что функция возвращает целое значение (int). Если функция не возвращает никакого значения, то на месте типа записывается спецификатор void. В списке параметров для каждого параметра должен быть указан тип. При отсутствии параметров список может быть пустым или иметь спецификатор void.

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

    Прототип функции может указываться до вызова функции вместо описания функции для того, чтобы компилятор мог выполнить проверку соответствия типов аргументов и параметров. Прототип функции по форме такой же, как и заголовок функции, в конце его ставится «;». Параметры функции в прототипе могут иметь имена, но компилятору они не нужны.

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

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

    В первом случае оператор имеет следующий формат:

    [имя_функции] (список_аргументов);

    Например: void Ptint(“Hello World!”);

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

    [Переменная] = [имя_функции] (список_аргументов);

    Например: z=max(x,y);

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

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

    Возможное решение данной задачи имеет вид:

    /* включение файла max.cpp с

    телом функции max */

    #include "max.cpp"

    void main()

    {

    int x,y,z;

    cout << "\n поочередно введите х и у \n";

    cin >> х; cin >> y;

    z=max (х, y); /* вызов функции */

    cout << "z=" << z;

    return;

    }

    Описание функции max находится в отдельном файле max.cpp, находящемся в том каталоге, из которого запускается исходная программа, и имеет следующий вид:

    int max (int a, int b)

    {

    int с; //

    c=(a>b)?a:b; // тело функции

    return с; //

    }

    Вызов функции является выражением в правой части оператора присваивания z=max(x,y);, при выполнении которого значения аргументов х и у подставляются вместо параметров а и bсоответственно (передача параметров в функцию по значению). После выполнения тела функции возвращаемое значение передается в место вызова функции и присваивается переменной z. Описание функции находится в файле, поэтому для включения файла в программу необходимо в тексте программы указать директиву препроцессора #include "max.cpp".

    Описание функции может находиться в одном файле с главной программой. При этом директива #include "max.cpp" не указывается, а вместо нее помещается описание функции. В рассмотренной программе функция имеет возвращаемое значение. Существуют за­дачи, которые не требуют передачи возвращаемого значения. Такой пример приведен ниже.

    Пример 2. Использование функции без возвращаемого значения.

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

    void print(char); // прототип функции

    void main()

    {

    char x;

    cout <<”\nВводите символы.

    <<” Enter – окончание ввода;

    do

    {

    x=getch();

    print (x);

    } while (x!= 13);

    return 0;

    }

    void print(char a) { cout <

    В функции рrint( ) отсутствует возвращаемое значение, поэтому обращение к функции осуществляется оператором вызова функции рrint(x);. В результате обращения к функции на экран будет выведен символ, введенный с клавиатуры с помощью оператора x=getch().

    Язык Си позволяет использовать процедуру перегрузки функций. Суть этого заключается в использовании одного и того же имени функции для решения различных, но схожих по назначению задач. Для реализации этого механизма описывается каждый из вариантов такой функции. Например, рассмотрим задачу нахождения среднего значения двух чисел. При реализации этой задачи требуется описывать отдельную функцию для целых чисел, чисел с плавающей точкой и их комбинации. Это связано с тем, что каждый передаваемый параметр должен иметь свой тип (int,float,double). Следовательно, если в функцию для нахождения среднего значения целых чисел передать числа с плавающей точкой, то в функции в соответствии с прототипом эти числа преобразуются путем отбрасывания дробной части в целые, что приведет к неправильному результату. Поэтому, для решения этой задачи пришлось бы описывать несколько функций с разными именами для разных типов данных. Механизм перегрузки функций позволяет для решения этой задачи использовать несколько функций с одним именем, при этом решение о выборе того или иного варианта функции для конкретного типа данных принимает сама программа.

    Рассмотрим листинг такой программы:

    Пример 3. Использование механизма перегрузки функции

    void PrintData(int *s, int N);

    void PrintData(char *w);

    void main()

    {

    int *a,n; char str[50];

    cout<<”\nEnter the array size: “; cin>>n;

    a=new int[n];

    for (int i=0;i

    PrintData(a,n);

    cout<<”\nEnter a string: “; cin>>str;

    PrintData(str);

    return;

    }

    void PrintData(int *s, int N)

    {

    cout<

    for (int i=0;i

    return;

    }

    void PrintData(char *w)

    {

    cout<<endl<<w; return;

    }

    Как видно из примера, функция PrintData() имеет одно имя, но два разных набора параметров. При вызове функции по списку передаваемых параметров автоматически вызывается тот вариант функции, который соответствует этому набору параметров. Если же функции с таким набором параметров нет, то компилятор выдаст сообщение об ошибке при компиляции листинга программы.
    ПРОГРАММА РАБОТЫ

    1. Изучение порядка объявления и описания функций

    • реализовать приведенные в теоретических сведениях примеры 1 - 3 ;

    • отладить и запустить программы;

    • разработать прототип и тело функции вычисления факториала числа.

    1. Изучение порядка вызова функций

    • разработать программу вычисления факториала числа с использованием пользовательской функции;

    • отладить и запустить ее в среде программирования.




    Занятие 10




    Лабораторная работа № 5

    Исследование способов работы с функциями


    Цель занятия:

    • Совершенствование навыков разработки программ в среде программирования MS Visual C++

    • Совершенствование навыков в программировании с использованием указателей

    • Исследование способов передачи параметров в функцию

    • Исследование порядка возвращения параметров из функции


    Время на выполнение работы: 2 часа
    Программа исследований:

      1. Исследование способа передачи параметров в функцию по значению

      2. Исследование способов передачи параметров в функцию по адресу

      3. Исследование порядка возвращения параметров из функции


    Подготовка к выполнению работы:

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

    2. Практически освоить порядок работы на ПЭВМ в среде программирования MS Visual C++.


    Материалы для подготовки к занятию:

    1. Конспект лекций

    2. [1] стр. 73-82


    Содержание отчета:

    1. Цели исследования.

    2. Программу работы.

    3. Листинги программ

    4. Результаты исследований

    5. Выводы по каждому пункту и общий вывод.

    1   ...   9   10   11   12   13   14   15   16   ...   22

    МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ



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

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

    Пример:

    /* использование параметров по значению */

    void change (int x, int y);

    void main()

    {

    int a=5,b=15;

    cout<<”\na=”<

    change(a,b);

    cout<<”\na=”<

    return;

    }

    void change (int x, int y)

    {

    int k=x;

    x=y;

    y=k;

    }

    В данной функции значения переменных x и y, являющихся формальными параметрами, меняются местами, но поскольку эти переменные существуют только внутри функции change, значения фактических параметров, используемых при вызове функции, останутся неизменными, то есть значения переменных a и b как были 5 и 15 соответственно, так и остались. Для того чтобы менялись местами значения фактических аргументов можно использовать функцию приведенную в следующем примере.

    Пример:

    /* использование параметров по адресу */

    void change (int *x, int *y)

    { int k=*x;

    *x=*y;

    *y=k;}

    При вызове такой функции в качестве фактических параметров должны быть использованы не значения переменных, а их адреса change (&a,&b);. Тогда функция будет оперировать не с локальными значениями, а со значениями по адресам, переданным в функцию в качестве параметров, что приведет к обмену значениями переменных a и b.

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

    Пример:

    /* использование параметров по ссылке */

    void change (int &x, int &y)

    { int k=x;

    x=y;

    y=k;}

    При вызове такой функции в качестве фактических параметров должны быть использованы имена переменных: change (a,b);. При этом, в функции мы будем работать с самими переменными a и b, но через альтернативные их имена: x и y.

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

    Функция возвращает значение если ее выполнение заканчивается оператором return, содержащим некоторое выражение. Указанное выражение вычисляется, преобразуется, если необходимо, к типу возвращаемого значения и возвращается в точку вызова функции в качестве результата. Если оператор return не содержит выражения или выполнение функции завершается после выполнения последнего ее оператора (без выполнения оператора return), то возвращаемое значение не определено. Для функций, не использующих возвращаемое значение, должен быть использован тип void, указывающий на отсутствие возвращаемого значения. Если функция определена как функция, возвращающая некоторое значение, а в операторе return при выходе из нее отсутствует выражение, то поведение вызывающей функции после передачи ей управления может быть непредсказуемым.
    1   ...   10   11   12   13   14   15   16   17   ...   22

    ЗАДАНИЕ НА ИССЛЕДОВАНИЕ





    1. Исследование способа передачи параметров в функцию по значению

    • реализовать в среде программирования следующий листинг:

    void Swap(int a, int b);

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

    {

    int x,y;

    cout<<"\nEnter two numbers: ";

    cin>>x>>y;

    cout<<"\nx="<передачи параметров в функцию по адресу

    • реализовать в среде программирования следующий листинг:

    void Swap(int *a, int *b);

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

    {

    int x,y;

    cout<<"\nEnter two numbers: ";

    cin>>x>>y;

    cout<<"\nx="<

    cin>>x>>y;

    cout<<"\nx="<порядка возвращения параметров из функции

    • реализовать в среде программирования следующий листинг:

    int Max(int a, int b);

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

    {

    int x,y,c;

    cout<<"\nEnter a two numbers: ";

    cin>>x>>y;

    c=Max(x,y);

    cout<<"\nMaximum is "<

    cout<

    return 0;

    }

    int Max(int a, int b)

    {

    int c;

    c=(a>b)?a:b;

    return c;

    }

    • с использованием режима отладки исследовать процесс исполнения программы в микропроцессоре. Обратить внимание на способ и место хранения значений локальных переменных a,b иc;

    • реализовать в среде программирования следующий листинг:

    int* GetMem();

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

    {

    int *a;

    a=GetMem();

    cout<<"\n a is "<

    cout<<"\n*a is "<<*a;

    cout<

    return 0;

    }

    int* GetMem()

    {

    int *c=new int(5);

    return c;

    }

    • с использованием режима отладки исследовать процесс исполнения программы в микропроцессоре;

    • сделать выводы.


    Занятие 11
    1   ...   11   12   13   14   15   16   17   18   ...   22

    Практическое занятие № 6
    Использование функций для работы с
    массивами



    Цель занятия:


    • Совершенствование навыков разработки программ в среде программирования MS Visual C++

    • Совершенствование навыков описания и использования функций в программах

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


    Время на выполнение работы: 2 часа
    Учебные вопросы:


    1. Изучение процедуры передачи массива в функцию

    2. Изучение процедуры возвращения массива из функции


    Подготовка к выполнению работы:


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

    2. Изучить материал настоящего руководства.


    Материалы для подготовки к занятию:


    1. Конспект лекций

    2. [1] стр. 78-80.

    ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ



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

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