Первая программа
Любая программа на С или C++ начинает свое выполнение с функции main(). Напишем нашу первую программу. Для этого создадим файл main.cpp и напишем текст:
#include
int main ()
{
cout «"Hello C++\n";
return 0;
}
Скомпилировав и запустив нашу программу мы должны получить на экране:
Hello C++
В первой строке программы мы написали директиву #include
Основные типы данных
Основные типы данных разделяются на три категории: целочисленные, с плавающей точкой и неопределенные(void). Целочисленные типы данных работают с целыми числами. Типы данных с плавающей точкой работают с данными имеющими дробную часть. Неопределенный тип данных соответствует пустому множеству значений.
Основными типами данных являются:
• char — целочисленный тип, содержит символы.
• int — является целочисленным типом, содержит целые цифры.
• short — тип данных short int (или сокращенно short) является целочисленным типом, содержащим целые числа, по размеру меньше или равен типу int.
• long — тип данных long int (или сокращенно long) является целочисленным типом, содержащим целые числа, по размеру больше или равен типу int.
• double — тип данных с плавающей точкой.
• float — наименьший тип данных с плавающей точкой.
• long double — тип данных с плавающей точкой больше чем double.
Нашу программу можно модифицировать:
#include
int main ()
{
char name[20];
cout << "What is your name: ";
cin >> name;
cout << "Hello: "<< name << end1;
return 0;
}
После запуска она должна выдать на экране вопрос "What is your name: ", мы соответственно должны ввести имя, например "Pupkin", на это программа должна выдать:
What is your name: Pupkin
Hello: Pupkin
В строке char name[20]; мы объявляем массив name типа char из 20 элементов, это значит что в массиве name может хранится не более 20 символов (подробнее о массивах мы поговорим в следующих уроках). В строке cin>>name; мы из стандартного потока ввода cin помещаем данные в наш массив name, в данном случае данные поступают с клавиатуры.
В языке C++ может быть использован модификатор const, для объявления констант (переменные содержание которых нельзя менять). Например: const char QUESTION[] = "What is your name: "; — Здесь мы объявили константу QUESTION типа char для хранения текста, далее нигде в программе ее содержание нельзя менять.
В программах отдельные Задачи лучше разделять по функциям. Обычная функция имеет вид:
Return_type name(param_type param)
{
//тело функции;
}
Где Return_type — тип возвращаемого функцией результата, name — имя функции, param_type — тип параметра передаваемого функции, param — имя параметра, которое будет использоваться внутри функции. Например, из программы предыдущего урока, печать приветствия можно выделить в отдельную функцию.
#include
const char QUESTION[] = "What is your name: "; //объявляем константу const
char HELLO[] = "Hello: "; //объявляем константу
void print_name(char* name) //объявляем функцию
{
cout «HELLO << name << end1; //печать приветствия
}
int main()
{
char name[20]; //объявления массива
cout << QUESTION; //печатаем вопрос
cin >> name; //считываем данные в массив name
print_name(name); //вызываем функцию print_name для печати приветствия
return 0;
}
В нашем случае функция print_name ничего не возвращает и поэтому имеет тип возвращаемого результата void. В качестве параметра ей передается строка name типа char.
Операторы сравнения, равенства и логические. В C++ имеется логический тип данных bool который может принимать только два значения true (истина) или false (ложь). Этот тип данных используется для контроля выполнения инструкций различных типов. В следующей таблице представлены инструкции C++, наиболее часто используемые для управления логикой выполнения.
Операторы сравнения, равенства и логические
— Операторы сравнения
меньше <
больше >
меньше или равно <=
больше или равно >=
— Операторы равенства
равно ==
не равно !=
— Логические операторы
отрицание!
логическое и &&
логическое или ||
Очень важно не путать операторы равенства и присваивания, например а==Ь — это проверка на равенство т. е. если а и Ь равны то выражение вернет true(истина) в противном случае false(ложь), а в выражении а=Ь переменная а станет равна Ь. Приведем пример с инструкцией if, она имеет вид:
if(условие)
{
инструкции
}
Здесь если условие истинно то выполняются инструкции. Мы можем составить следующую программу:
int main ()
{
int а = 0;
int Ь = 4;
if(а!= Ь) //если а не равно Ь, то
{
а = Ь; //а становится равной Ь
}
if(а == Ь) //если а равно Ь, то
{
а = b + 1; //а принимает значение b + 1
}
return 0;
}
Инструкция if-else схожа и тесно связана с инструкцией if, она имеет вид:
if(условие)
{
инструкции 1
}
else
{
инструкции 2
}
Если условие истинно то выполняются инструкции 1, а инструкции 2 пропускаются, если условие ложно, то выполняются инструкции 2, а инструкции 1 пропускаются. Например:
int main ()
{
int а = 0;
int Ь = 4;
if (а == Ь)
{
а = 4;
}
else
{
а = 3;
}
return 0;
}
Здесь а присвоится 3, т. к. условие а == Ь ложно.
Инструкция while имеет вид:
while(условие)
{
инструкции
}
Здесь сначала проверяется условие и если оно истинно то выполняются инструкции, после управление переходит опять в начало цикла к условию и так до тех пор, пока условие не станет ложным. Например:
int main ()
{
int а = 0;
while(а < 20)
{
++а;
}
return 0;
}
Оператор ++ увеличивает переменную на 1 т. е. выражение ++а идентично а + 1. В нашем цикле а будет увеличиваться на 1 пока не станет равно 20.
Вид инструкции for:
for(начальная_инструкция; условие; выражение)
{
инструкции;
}
Сначала выполняется начальная_инструкция, потом проверяется условие и если оно истинно, то выполняются инструкции, затем вычисляется выражение и управление передается в начало цикла с разницей что начальная_инструкция уже не выполняется. Например:
#include
int main ()
{
for(int i = 0; i!= 10; ++i)
{
cout << i << endl;
}
return 0;
}
При выполнении эта программа выведет на экран числа от 0 до 9.
Массивы
Массив состоит из нескольких элементов одного и того же типа. Число элементов массива задается при его объявлении и в дальнейшем не меняется. Массивы объявляются так же как и переменные. Например:
int а[100];
char b[4 0];
В первой строке объявлен массив из 100 элементов типа int, а во второй из 40 элементов типа char. Ко всему массиву целиком можно обращаться по имени. Можно обращаться и к отдельным элементам по индексу, который указывает относительную позицию элемента. Индексация массива начинается с нуля т. е. в массиве а первый элемент будет а[0], а последний а[99].
Бывают многомерные массивы. Например двумерный массив int v[3][7] можно представить как три массива типа int по 7 элементов в каждом. Представим это графически:
v[0] 0 1 2 3 4 5 6
v[1] 0 1 2 3 4 5 6
v[2] 0 1 2 3 4 5 6
Напишем программку с применением двумерного массива, которая спросит у вас сначала фамилию потом имя и отчество и в конце выведет это все на экран.
#include
int main()
{
char fio[3][25];
cout << "Your surname: ";
cin >> fio[0];
cout << "\nYour name: ";
cin >> fio[1];
cout << "\nYour patronymic name: "; cin» fio [2];
cout << "\n" << fio[0] << " " << fio[1] << " " << fio[2] << end1;
return 0;
}
В этом уроке разговор пойдет о указателях, эта сложная тема для начинающих поэтому если вы ее не поймете то советую обратится к какой либо литературе (например, книге Бьерна Страуструпа "Введение в язык C++").
Указатели в C++ используются для связи переменных с машинными адресами. Если V — переменная, то &V — ее адрес, или место в памяти, где хранится ее значение. & — это оператор определения памяти. В программе можно объявить переменные — указатели и затем использовать их для получения адресов. Приведем пример:
int а = 2;
int Ь = 4;
int *р;
Р = &а;
*р = 8;
Р = &Ь;
*Р = 6;
Здесь в первых двух строках объявляются переменные а и Ь типа int, в третей строке объявляется указатель на int. В четвертой строке указатель р берет адрес переменной а, в пятой строке переменной на которую указывает указатель (в данном случае а) присваивается значение 8. В шестой и седьмой строках указатель берет адрес переменной Ь и меняет ее значение на 6.
Всякую задачу можно разбить на несколько подзадач. Также и в программе мы можем использовать функции для разбиения ее на несколько подпрограмм. Выполнение программы начинается всегда с функции main(). Когда в программе встречается имя функции происходит обращение к ней и управление передается ей. После выполнения функции управление передается в то место откуда она была вызвана. Формально функция выглядит так:
тип имя(список_параметров)
{
инструкции
}
Здесь: тип — это возвращаемый тип(тип того что возвращает функция), имя — это название функции и список_параметров — это параметры которые передаются функции. В функциях для возврата результата используется инструкция return, она возвращает какое либо значение в то место откуда была вызвана функция. Приведем пример программы с использованием функции, которая будет высчитывать сумму двух введенных пользователем значений:
#include
int sum(int a, int b)
{
int с = a + b; return c;
}
main()
{
int a, b, res;
cout << "a = ";
cin >> a;
cout << "b = ";
cin >> b;
res = sum(a, b);
cout << "summa: " << es << end1;
}
Объявление функции можно отделить от определения, например в данной программе функцию sum можно объявить до функции main, а определить после:
#include
int sum(int a, int b);
main()
{
int a, b, res;
cout << "a = ";
cin >> a;
cout << "b = ";
cin >> b;
res = sum(a, b);
cout << "summa: " << res << end1;
}
int sum(int a, int b)
{
int с = a + b;
return c;
}
Операторы new и delete служат для управления свободной памятью. Время жизни объектов, которые создаются с помощью этих операторов, полностью управляется программистом. Программист создает объект с помощью оператора new и уничтожает его с помощью оператора delete. Оператор new принимает следующие формы:
new имя_типа
new имя_типа[выражение];
Вот фрагмент использования оператора new:
char *р;
р = new char[10];
Здесь сначала объявляется указатель на char, потом с помощью оператора new выделяется память под 10 элементов типа char (т. е. мы получаем массив из 10 элементов типа char). Для удаления объекта созданного с помощью оператора new используется оператор delete. В приведенном выше примере, чтобы удалить созданные объекты можно использовать следующий код:
delete [] р;
Тип struct позволяет программисту объединить несколько компонент в переменную с одним именем. Члены структуры могут быть различных типов. В качестве примера определим структуру описывающую квартиру. Эта структура будет хранить такие признаки квартиры как площадь, число комнат, номер, фамилия главного квартиросъемщика.
struct apartment
{
int count_rooms;
int area;
int number;
char fio [20];
};
Здесь struct — это ключевое слово, apartment — имя структуры, а count_rooms, area, number и fio члены структуры. Теперь мы можем создавать объекты типа apartment, они объявляются так же как и обычные переменные:
apartment ар;
Для доступа к членам структуры ар используется оператор выбора члена структуры".". Допустим мы хотим описать какую либо квартиру, то можно написать:
ар.count_rooms = 4;
ар. area = 90;
ар. number = 112;
ар. fio = "Ivanov I.I";
Стек — одна из полезных структур данных. Для стека характерны такие операции как вставлять и удалять данные, но выполняются они только над самым верхним элементом(вершиной стека). Такой порядок называется "первым вошел, последним вышел".
Реализуем стек для хранения символьных значений(букв), с помощью структуры и нескольких функций. Для хранения данных мы создадим структуру stak состоящую из массива s, хранящего наши данные, и переменной top которая будет хранить номер верхнего элемента.
struct stack
{
char s [1000];
int top;
};
Теперь создадим функцию reset, задача которой инициализация. В ней нам достаточно переменной top присвоить значение -1. В качестве параметра ей будет передаваться указатель на структуру (при использовании указателя для доступа к членам структуры используется не"." а оператор "->").
void reset(stack* st)
{
st->top = -1;
}
Так же нам нужны функции push (вставить) и pop (извлечь).
void push(stack* st, char s)
{
++st->top;
st->s[st->top] = s;
}
char pop(stack* st)
{
--st->top;
return st->s[st->top];
}
Теперь напишем функцию main, чтобы проверить нашу версию стека, функция будет печатать строку в обратном порядке.
main()
{
char str[] = "Му name is Gena";
int count = sizeof(str);
stack My_stack;
reset(&My_stack);
for(int i = 0; i < count; i++)
{
push(&My_stack, str[i]);
}
while(My_stack.top!= -1)
{
cout << pop(&My_stack);
}
cout << end1;
}
Полностью текст программы должен выглядеть так:
#include
struct stack
{
char s [1000];
int top;
};
void reset(stack* st)
{
st->top = -1;
}
void push(stack* st, char s)
{
++st->top;
st->s[st->top] = s;
}
char pop(stack* st)
{
--st->top;
return st->s[st->top];
}
main()
{
char str[] = "My name is Gena";
int count = sizeof(str);
stack My_stack;
reset(&My_stack);
for(int i = 0; i < count; i++)
{
push(&My_stack, str[i]);
}
while(My_stack.top!= -1)
{
cout << pop(&My_stack);
}
cout << end1;
}
Структуры в C++ могут иметь в качестве своих членов(в предыдущем примере это s и top) не только переменные но и функции. Для этого объявление функций вставляется в объявление структуры, например предыдущий пример стека можно объявить так:
struct stack
{
char s [1000];
int top;
void reset()
{
top = -1;
}
void push(char c)
{
++top;
s[top] = c;
}
char pop()
{
--top;
return s[top];
}
};
Функции-члены записаны так же как обычные функции. Отличие лишь в том что теперь они могут использовать переменные и функции "как есть", им не нужно передавать в качестве параметров такие переменные как s и top. Обращаются к функциям-членам так же как и к обычным членам: с помощью оператора".", а указатели с помощью оператора "->". Приведем несколько фрагментов кода:
stack My_stack;
My_stack.reset();
stаск * pMy_stack = &My_stack;
pMy_stack->push('A');
Переменные структур и классов (позже мы узнаем что это) принято называть — "объектами", с этой минуты и мы их будем так называть.
Функции-члены, которые определены внутри структуры, являются встраиваемыми. Обычно, только маленькие, часто используемые функции определяются внутри структуры (как в предыдущем уроке). Что бы определить функцию-член вне структуры используется оператор Давайте это наглядно покажем, переделав структуру из предыдущего урока.
struct stack
{
char s [1000];
int top;
void reset();
void push(char c);
char pop();
};
void stack::reset()
{
top = -1;
}
void stack::push(char c)
{
++top;
s[top] = c;
}
char s tack::pop()
{
--top;
return s[top];
}
Запись void stack::reset() говорит, что функция reset() принадлежит структуре stack. Благодаря оператору"::" мы можем иметь одинаковые имена функций для разных типов структур.
В объектно-ориентированном программировании существует такое понятие как механизм сокрытия данных. Давайте возьмем случай когда вы покупаете магнитофон, то вам доступны только те его части которые необходимы для работы с ним (кнопочки, экранчики и т. д.), такие части как провода, магнитные головки и т. д. вам не доступны. В структурах и классах (позже мы узнаем что это такое) сокрытие данных осуществляется с помощью ключевых слов public (открытый), private (закрытый) и protected (защищенный). Закрытые члены в программе недоступны, а открытые наоборот доступны. Внутри структуры после ключевого слова private, все члены ограничены доступом. Закрытыми членами могут пользоваться только функции-члены этой структуры. Открытые члены могут использоваться и вне структуры.
Напишем структуру, характеризующую квартиру. В ней будут такие члены как number (номер квартиры), count_room (количество комнат), floor (этаж), area (площадь), price (цена), status (приватизирована или нет), эти члены мы сделаем закрытыми, а для доступа к ним напишем функции.
struct kwart
{
public:
int GetNumber();
int GetCountRoom ();
int GetFloor();
int GetArea();
int GetPrice();
bool GetStatus();
void SetNumber(int);
void SetCountRoom(int);
void SetFloor(int);
void SetArea(int);
void SetPrice(int);
void SetStatus(bool);
private:
int number;
int count_room;
int floor;
int area;
int price;
bool status;
};
int kwart::GetNumber()
{
return number;
}
int kwart::GetCountRoom()
{
return count_room;
}
int kwart::GetFloor()
{
return floor; int kwart::GetArea()
{
return area; int kwart::GetPrice()
{
return price;
}
bool kwart::GetStatus()
{
return status;
}
void kwart::SetNumber(int num)
{
number = num;
void kwart::SetCountRoom(int count)
}
count_room = count;
}
void kwart::SetFloor(int num)
{
floor = num;
}
void kwart::SetArea(int num)
{
area = num;
void kwart::SetPrice(int num)
{
price = num;
}
void kwart::SetStatus(bool stat)
{
status = stat;
}
Теперь если мы напишем:
kwart kw;
int i = kw.area;
это будет ошибкой, так как переменная area — закрытая, если мы хотим присвоить переменной i ее значение, то нужно воспользоваться функцией GetArea():
kwart kw;
kw.SetArea(20);
int i = kw.GetArea();
А вот в этом фрагменте уже все правильно. Сначала мы переменной area с по мощью функции SetArea() присваиваем значение 20, а потом переменной i присваиваем значение area.
ПОКА ВСЕ.