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

OOP_Bakalavry_-_Laboratornye_raboty

.pdf
Скачиваний:
20
Добавлен:
11.05.2015
Размер:
998.6 Кб
Скачать

Лабораторная работа №1 Основные элементы языка Си++

1.Создайте проект типа Win32 Console Application в среде разработки Visual Studio 2012 Express для языка Си++. Название для проектов необходимо придумать такое, чтобы по названию проекта можно было понять его назначение. Например, название ProgrammingPractics отражает цель вашего проекта в рамках данной дисциплины – в данном проекте на протяжении всего курса вы будете изучать основы программирования на языке Си++ и объектно-ориентированного подхода.

ВАЖНО: никогда не стоит добавлять в название проекта свою фамилию, имя или местоимение «My». Важно понять, что ваша фамилия в названии проекта, переменной или функции никак не повлияет на работоспособность программы. Это лишние слова, которые перегружают название, делают его длинным и непонятным и в конечном счете могут ввести в заблуждение другого разработчика. Более подробно правильное именование элементов программного кода можно ознакомиться в стандарте оформления кода RSDN [1].

2.Напишите простейшую программу на языке Си++, выводящую на экран сообщение “Hello, World!”. Одним из вариантов реализации является следующий код:

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

#include "stdafx.h" #include <stdio.h>

void Main()

{

printf("Hello, World!\n");

}

Принцип выполнения данной программы построчно описан во многих источниках, в частности «Язык Си++» В. Подбельского [2] или «Си++. Руководство для начинающих» Г. Шилдта [3].

Вопросы для проверки:

1)Как в языке Си++ объявляется комментарий? Для чего нужны комментарии?

2)Что такое директива препроцессора? Что выполняет директива препроцессора include?

3)Чем отличается для директивы include указание названия библиотеки в кавычках (например, “stdafx.h”) и в угловых скобках (например, <stdio.h>)?

4)Для чего необходимо подключать библиотеку <stdio.h>? Какие функции содержит эта библиотека?

5)Что такое функция Main()? Для чего она нужна?

6)Что выполняет функция printf(“Hello, World!\n”)? Как расшифровывается printf? Для чего нужен спецсимвол “\n” в конце строки, если при выполнении программы он не отображается на экране?

7)Что делает оператор “;”? Для чего нужно ставить точку с запятой в языке Си++?

8)Перечислите основные этапы компиляции программы? Что выполняется на каждом этапе?

3.Напишите программу с объявлением и инициализацией целочисленных переменных. Выведите их значения на экран. Также выведите на экран сумму двух целочисленных перемен-

ных. Для этого наберите следующий код:

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a; // Объявление целочисленной переменной a = 5; // Инициализация переменной значением

int b = 3; // Допустимо одновременное объявление и инициализация

printf("\n Variable a equals %d", a); // Вывод значения переменной на экран printf("\n Variable b equals %d", b); // Значение переменной подставится вместо %d printf("\n Summ of a and b equals %d", a + b); // Можно выводить сразу

// результат сложения

}

ПРИМЕЧАНИЕ: Для демонстрации программ преподавателю просто добавьте код, находящийся внутри фигурных скобок в предыдущую программу после метода printf(“Hello, World!\n”). Таким образом, вы совместите две программы в одной и сможете продемонстрировать их одновременно.

Вопросы для проверки:

1)Что такое переменная в языке Си++? Что такое тип данных?

2)Чем отличаются целочисленные типы данных от вещественных (с плавающей точкой)?

3)Как в языке Си++ происходит объявление и инициализация переменной какого-либо типа?

4)Как с помощью функции printf() вывести значение переменной на экран? Что означает “%d” внутри форматной строки? Какие еще параметры помимо “%d” существуют для функции printf() и для каких типов данных их необходимо использовать?

5)Что будет, если использовать не тот параметр, например, для вывода целочисленного типа использовать параметр “%f”?

6)Что будет, если вывести на экран значение переменной, которая еще не была инициализирована никаким значением?

4.Напишите программу, которая будет выводить на экран результаты деления двух целочисленных переменных со значениями 5 и 3 и двух вещественных переменных со значениями 5.0 и 3.0. Получившийся результат поясните. Пример реализации:

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a = 5; int b = 3;

float z = 5.0; float y = 3.0;

printf("Float variables division: %f \n", z/y); printf("Integer variables division: %d \n", a/b);

}

ПРИМЕЧАНИЕ: в результате выполнения программы на экране будут представлены два результата деления, однако, несмотря на одинаковые исходные значения переменных, результаты деления будут отличаться. При делении вещественных чисел результат будет равен 1.666, а при делении целочисленных переменных результат будет равен 1. Именно данную особенность вам и необходимо пояснить.

Вопросы для проверки:

1)Чем отличается операция деления для целочисленных и вещественных типов данных?

2)Какой оператор вычисляет остаток от деления целочисленных переменных? Существует ли данный оператор для вещественных чисел?

3)Какие еще операции и операторы вы знаете, которые существуют для одного типа данных, но не существуют для другого?

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

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a; int b;

//Вывод текстового сообщения, поясняющего назначение программы

//является правилом хорошего тона и помогает пользователю

//разобраться в вашей программе

printf("---Program for integer summation---");

// Всегда поясняйте пользователю, какие данные ему нужно ввести printf("\n\n Enter first integer value: ");

scanf("%d", &a); // Чтение значения переменной с клавиатуры

printf(" Enter second integer value: "); scanf("%d", &b);

printf(" \n Summ of %d and %d equals %d \n", a, b, a+b);

}

ПРИМЕЧАНИЕ: обратите внимание на использование знака & (амперсанд) в методе scanf(). ПРИМЕЧАНИЕ: обязательно выводите на экран поясняющие сообщения о том, что именно пользователь должен ввести с клавиатуры и для чего. Постарайтесь объяснить пользователю, какой тип данных ему нужно ввести, в каком формате, и как эти данные будут использоваться в дальнейшем

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

Вопросы для проверки:

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

2)Функции printf() и scanf() являются так называемым форматным вводом/выводом. В языке Си++ существует также потоковый ввод/вывод, реализуемый с помощью потоков cin и cout. Продемонстрируйте на простом примере использование потокового ввода/вывода.

3)Почему потоковый ввод/вывод предпочтительнее форматного? Какие недостатки существуют у форматного ввода/вывода?

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

#include "stdafx.h" #include <stdio.h>

void Main()

{

int value;

int* pointer; // Объявление указателя на целочисленный тип данных int anotherValue;

value = 5;

pointer = &value; // Операция взятия адреса переменной

//pointer может хранить адрес только

//целочисленной переменной

anotherValue = *pointer; // Операция разыменования

//Вывод значения, полученного при разыменовании указателя printf("Value, stored in pointer: %d \n",anotherValue);

//Вывод адреса, который хранится в указателе

printf("Address in pointer: %p \n", pointer);

// Вывод результата разыменования указателя printf("Value in pointer: %d \n", *pointer);

}

ПРИМЕЧАНИЕ: указатель – специальный тип данных языка Си++, предназначенный для хранения адресов памяти других переменных. Примером объявления указателя является переменная pointer – обратите внимание на звездочку, установленную после типа данных int. В данном случае это означает что переменная-указатель pointer может хранить в себе адрес целочисленной переменной, но только целочисленной! Работа с указателями происходит с помощью специальных операций – разыменования и взятия адреса. Также существуют операции инкремента и декремента адреса. Более подробно назначение такого специфического и мощного инструмента как указатель будет рассмотрено в следующих лабораторных работах.

ПРИМЕЧАНИЕ: обратите внимание на именование переменных. В данном примере такие имена переменных как value, pointer, anotherValue дают представление о том, что это за переменная и для чего она нужна. Любая создаваемая вами переменная должна иметь четкое понятное имя, которое должно отражать назначение переменной. Также обратите внимание на использование регистров – переменная именуется с маленькой буквы, однако каждое новое слово, используемое в названии пишется с заглавной. Разделители между словами в виде нижних подчеркиваний отсутствуют. Например: anotherValue. Данный стиль именования переменных называется Camel, так как заглавные буквы новых слов напоминают горбы верблюда. Неправильно: anothervalue, Anothervalue, another_value, AnOtHeRvAlUe. На самом деле, компилятору не важно как именно вы назовете переменные – имя переменной не влияет на результат компиляции и выполнения программы. Однако ваш исходный код в первую очередь должен быть читаемым для другого разработчика и для вас. Для этого обязательно соблюдение правил именования переменных! Подробнее можно ознакомиться в [1].

Вопросы для проверки:

1)Что такое указатель? Продемонстрируйте синтаксис объявления переменных-указателей.

2)Что такое операция разыменования? Что такое операция взятия адреса?

3)Сколько байт выделяется под переменную-указатель? Одинаковое ли количество памяти выделяется для указателей на целочисленные типы данных и для указателей на вещественные типы данных? Для ответа на вопрос используйте функцию sizeof().

4)Продемонстрируйте на примере программы, чем отличается объявление указателя от операции разыменования? Как отличить друг от друга эти две операции?

5)Можно ли применить операцию взятия адреса к указателю?

6)Можно ли применить операцию разыменования к обычной переменной?

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

int integerValue; int* integerPointer;

int* anotherIntegerPointer;

float floatValue; float* floatPointer;

integerPointer = &integerValue;

// Допустимая операция

floatPointer = &floatValue;

// Допустимая

операция

integerPointer

= &floatValue;

// Недопустимая операция

floatPointer =

&integerValue;

// Недопустимая операция

anotherIntegerPointer = integerPointer;

// Допустимая

операция

floatPointer = integerPointer;

// Недопустимая операция

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

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a;

printf("Enter value for check on even/odd: "); scanf("%d", &a);

if (a%2 == 0)

{

printf("\n Value %d is even! \n", a);

}

else

{

printf("\n Value %d is odd! \n", a);

}

return 0;

}

8. Напишите программу, определяющую кратность введенного числа 5 или 2. Используйте лестничную структуру:

void Main()

{

int a;

printf("Enter value for check on even/odd: "); scanf("%d", &a);

if (a%5 == 0)

{

printf("\n Value %d multiples 5! \n", a);

}

else if (a%2 == 0)

{

printf("\n Value %d multiples 2! \n", a);

}

else

{

printf("\n Value %d doesn`t multiply 5 or 2! \n", a);

}

}

9. Напишите любую программу, использующую цикл с пред-условием:

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a = 0;

while (a < 5) // условный цикл с пред-условием

{

printf("Value is %d now \n", a); a++;

}

}

10. Напишите любую программу, использующую цикл с пост-условием:

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a = 0;

do // условный цикл с пост-условием

{

printf("Value is %d now \n", a); a++;

}

while (a < 5);

}

11. Напишите программу, демонстрирующую работу итерационного цикла:

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a = 10;

for (int i = 0; i < 10; i++)

{

printf("Iteration #%d \n", i);

}

 

printf("\n\n");

 

for (int i = 0; i < a; i++)

 

{

 

a--;

 

printf("Iteration #%d

Value is %d \n", i, a);

}

 

}

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

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a = 10;

for (int i = 0; i < 10; i++)

{

a--;

if (i >= a)

{

printf("I is more or equal A! Break of cycle"); break; // этот оператор досрочно завершает цикл

}

}

printf("\n A is %d \n", a);

}

Вопросы для проверки:

1)Какие выражения можно использовать в качестве условий в условных операторах и операторах цикла?

2)Что такое область видимости переменной? Что такое время существования переменной? Как понятие области видимости относится к условным операторам и циклам?

3)Можно ли задавать в качестве переменной-итератора цикла переменную, объявленную ранее? Можно ли в качестве правила изменения переменной задать не инкремент, а, например, умножение на 2?

4)Как организовать цикл не в порядке возрастания, а ведущий обратный отсчет? Продемонстрируйте на примере.

5)Возможно ли использование оператора break в циклах с пред- и пост-условием?

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

#include "stdafx.h" #include <stdio.h>

void Main()

{

int a = 5; int b = 3; float z;

//Неявное приведение типов z = a;

printf("Value of z is %f \n", z);

//Ошибка - невозможное приведение типов! a = z;

//Явное приведение типов

a = (int)z;

printf("Value of a is %d \n", a);

//Неявное приведение результата деления

//целочисленных переменных

z = a/b;

printf("Value of z is %f \n", z);

//Явное приведение а к float и неявное b к float

//для выполнения деления

z = ((float)a)/b;

printf("Value of z is %f \n", z);

}

Вопросы для проверки:

1)Что такое явное приведение типов данных?

2)Что такое неявное приведение типов данных?

3)Почему недопустима операция присвоения вещественного числа в целочисленную переменную, но операция становится возможна при явном приведении типов?

4)Почему в последнем примере приведения типов переменную a сначала необходимо привести к типу float, и лишь только после этого произвести деление? Чем результат деления будет отличаться от операции деления выше?

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

-Титульный лист

-Содержание

1.1Цель работы – освоение базовых элементов языка Си++, стандартных типов данных и работы с ними.

1.2Введение и постановка задачи лабораторной работы – в введении представить ответы на вопросы для проверки в виде текста без перечисления и указания самих вопросов. В постановке задачи перечислить все задачи, которые необходимо выполнить в работе – выделены жирным текстом в данном методическом пособии.

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

1.4Блок-схема программы с использованием оператора break (задание 12) – анало-

гично предыдущей блок-схеме.

1.5Исходный код реализации программы работы с указателями (задание 6).

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

ПРИМЕЧАНИЕ: при проверке отчета преподавателем особое внимание уделяется правильности оформления. Отчет должен соответствовать стандарту оформления [ОС ТУСУР 6.1- 97] (можно найти на сайте кафедры или в Интернете). Обращайте внимание на размеры шрифтов и межстрочных интервалов, размеры полей и абзацных отступов, указания номеров страниц и т.д. В качестве примера оформления титульного листа, содержания, текстового параграфа и рисунков-графиков использовать приложения В, Д, И, К, Л [ОС ТУСУР

6.1-97].

Лабораторная работа №2 Функции и массивы

В языке Си++ реализация какого-либо метода имеет следующий вид:

ВозвращаемыйТипДанных ИмяФункции(ТипВходнойПеременной1 имяВходнойПеременной1, …)

{

список выполняемых инструкций

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

}

Где возвращаемыйТипДанных – это указание того типа данных, которое будет возращаться в результате выполнения функции. Это может быть int, char, double, void или любой другой тип данных, который вы захотите. ИмяФункции – имя функции, уникальное в данном пространстве имен. По правилам языка Си++, вы не можете создать две функции с одним и тем же именем, возвращаемым типом данных и набором входных переменных.

ПРИМЕЧАНИЕ: по правилам RSDN функции именуются согласно стилю Pascal, т.е. каждое новое слово в имени начинается с заглавной буквы, например, CalculateTriangleArea. Первая буква также должна быть заглавной (в отличии имен переменных, где первая буква должна быть прописной). Помимо стиля Pascal, имя функции должно начинаться с глагола, объясняющего действие, которое выполняет данная функция.

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

ПРИМЕЧАНИЕ: обратите внимание на оформление тела функции в примере ниже. Фигурные скобки идут ровно под началом объявления функции, а всё содержимое тела смещено на одну табуляцию относительно фигурных скобок.

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

double CalculateTriangleArea(int width, int height)

{

double area = width * height / 2.0; return area;

}

Из данного примера видно, что функция в результате своего выполнения должна вернуть вещественное значение типа double. Название функции говорит о том, что в нем рассчитывается площадь треугольника, а двумя входными переменными являются его длина и высота. Внутри функции объявляется новая переменная вещественного типа, в которую тут же присваивается рассчитанное значение площади. Далее происходит возвращение значения переменной area в место вызова функции. Стоит отметить, что если функция возвращает какое-либо значение, то в месте вызова функции это значение должно быть куда-то записано, например, в какую-нибудь переменную. Исключение составляют функции, возвращающие тип void, то есть ничего. При этом указание оператора return внутри подобной функции необязательно.

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

void PrintHelloWorld()

{

printf("Hello, World!\n");

}

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

#include "stdafx.h" #include <stdio.h>

//Реализация функции, выводящей на экран текст. void PrintHelloWorld()

{

printf("Hello, World!\n");

}

int main()

{

PrintHelloWorld(); //Вызов функции в теле программы. return 0;

}

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

Вопросы для проверки:

1)Что такое функция?

2)Как выглядит объявление функции в языке Си++? Какие обязательные элементы объявления функции?

3)Что такое входные переменные функции? Какие типы данных могут использоваться в качестве входных переменных? Что такое void?

4)Что такое возвращаемое значение? Какие типы данных могут использоваться в качестве возвращаемого значения из функции?

5)В чем особенность функции Main?

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

Впредыдущем задании говорилось, что любая функция должна описана до того, как она будет вызвана в первый раз. К сожалению, при разработке программ даже средней сложности (от 50 000 строк кода) данное требование практически невозможно выполнить. Но в языке Си++ есть механизм, позволяющий обойти данное ограничение. Это прототипы функций. Прототип функции – это описание функции, возвращаемого типа данных, имени функции и её входных переменных без тела самой функции. При этом подразумевается, что само тело функции будет описано в другом месте. Следующий пример демонстрирует работу прототипов:

#include "stdafx.h" #include <stdio.h>

//Прототип функции. void PrintHelloWorld();

int main()

{

PrintHelloWorld(); //Вызов функции в теле программы. return 0;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]