Similar presentations:
Введение в курс и основы C++
1. САОД Введение в курс и основы С++
А. Задорожный2025
2. Содержание
(звездочка) в заголовке указывает на то, что имеется содержательныйкомментарий в заметках к слайду.
• Введение
• История и место C++
• Hello, World!
• Процесс построения программы
• Консольный ввод-вывод
• Встроенные типы данных
• Функции и передача параметров
• Роль заголовочных файлов
• Указатели и массивы
– Операции над указателями
– Правила объявления и чтения типов в C
• Z-строки
3. О курсе
• В основе курса базовые алгоритмы поиска икодирования (сжатия) данных, регулярные
выражения.
• Рабочий язык C++, классические контейнеры
стандартной библиотеки.
• Расположение тем отвечает
сбалансированности загрузки практических
занятий.
Цель – не “провалиться” в C++, а осваивать его
изучая алгоритмы.
4. О курсе
Алгоритмы рассматриваются на практическом уровне:• Круг задач и проблема;
• Идея решения;
• Алгоритм. Часто на уровне идей.
Математические вывод и описание алгоритмов остаются за
пределами курса.
На наш взгляд, такой подход расширяет “круг интересантов”.
Предполагается, что при необходимости, студенты смогут
самостоятельно:
• И опуститься к строгому рассмотрению;
• И расширить знания в области подобных проблем;
• И подняться до новых применений методов на практике.
5. О курсе
В результате ожидается:- Неформальное, но достаточно глубокое,
знание и понимание языка C++;
- Понимание рассмотренных проблем
обработки данных;
- Понимание базовых идей решения этих
проблем;
- Расширение инструментария в области
программирования.
6. История и место C++*
• C -> C++, Objective C.– Драйверы, требования высокой
производительности, микроконтроллеры;
– Модули для других языков (Python, …)
– Сложные межкорпоративные проекты (Root, …)
• ~C -> Java, C#, PHP, Perl, Java script, …
• Native код (выполняется непосредственно
операционной системой)
• Переносимость, особые требования к
производительности, кросс-компиляторы
7. Как построен материал*
Считаем, что уверенно знаем C#!• Синтаксически много общего;
• Максимально используем эту схожесть,
останавливаясь на различиях;
• Не изучаем стандарт языка, а знакомимся с
особенностями и применяем на практике;
8. Hello, World!*
#include <iostream>//заголовок (*.h, *.hpp)
using namespace std;
int main(int argc, char* argv[])
{
cout << "Hello, World!" << endl;
return 0;
}
9. Hello, World!*
#include <iostream>//заголовок (*.h, *.hpp)
using namespace std;
int main(int argc, char* argv[])
{
cout << "Hello, World!" << endl;
return 0;
}
После выполнения:
10. Hello, World!*
#include <iostream>//заголовок (*.h, *.hpp)
using namespace std; //пространство имен STL
int main(int argc, char* argv[])
{
cout << "Hello, World!" << endl;
return 0;
}
11. Hello, World!*
#include <iostream>//заголовок (*.h, *.hpp)
using namespace std;
int main(int argc, char* argv[])
{
cout << "Hello, World!" << endl;
return 0;
}
12. Построение программы*
Процесс построениявключает 3 шага:
• Препроцессирование
• Компиляция
• Сборка
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
return 0;
}
13. Препроцессирование
Предварительная обработка текстовых файлов исходного кода иподготовка текстов программы для последующей компиляции.
- Поступают исходники C++ (заголовочные и *.cpp файлы),
- На выходе тексты C++ готовые к компиляции, т.е. без
инструкций препроцессора.
#include - включают указанный файл в текст программы.
Включаемый файл может иметь свои #include и т.д.
Инструкции #include приводят к тому, что тексты, передаваемые на
компиляцию имеют большой объем, а их обработка требует много
времени.
! Каждая среда разработки решает эту проблему по своему.*
14. Препроцессор*
#include <iostream>/“iostream”#define MY_KEY
#undefine MY_KEY
// Между <> и “” есть различие
// Объявляем имя
// Отменяем объявление
#define max(a,b) ((a)>(b)?(a):(b)) // Объявляем макроопределение
Если нужно переносить строки, то в конце ставится обратная косая черта
– ‘\’.
#ifdef MY_KEY
Текст, если раньше было определено MY_KEY
#else
Текст, если не было определено MY_KEY
#endif
Обеспечивает возможность много-платформенных проектов
15. Компиляция
Компилятор получает файл, обработанныйпрепроцессором.
В результате компиляции исходные тексты программы
(cpp) переводятся в “объектные модули” (*.obj) –
бинарные модули, готовые для построения
программы.
Prog.cpp
Prog.obj
• Каждый cpp-файл компилируется независимо
• и из каждого такого файла получается собственный
модуль.
16. Сборка
В процессе сборки отдельные модулисобираются в исполняемую программу.
exe
• Строится единый файл;
• Фиксируются ссылки между
отдельными модулями;
Obj1.obj
Obj2.obj
main
• Находится и указывается как “точка
входа” функция main.
Obj…
17. Выполнение программы
При выполнении программы ОС:- Размещает образ программы в памяти;
- Фиксирует адреса, которые стали известны после размещения в
памяти;
- Создает “окружение”
- Передает управление на точку входа.
Далее программа выполняется в соответствие ее кодом.
Таким образом, загрузка программы требует определенного
времени. Это одна из причин, почему некоторые интерпретаторы
(например, Python) иногда работают быстрее программ. Код
интерпретатора всегда подготовлен к выполнению и
обрабатывается только текстовый файл исходного кода.
18. Hello, World! * вывод на консоль - 2
Уже знакомы с объектом cout и операцией <<. В негоможно выводить тексты ТОЛЬКО латиницей.
Можно “научить” консоль выводить по-русски, но лучше
обходиться без этого…
#include <iostream>
using namespace std;
int main()
{
setlocale(0, “Russian”);
cout << ”Hello, World!” << endl;
return 0;
}
19. Ввод данных и потоки*
int main(){
cout << “? ”;
>? 2
>x^2 = 4
double x;
cin >> x;
// читаем число. Разделитель ‘.’
cout << “x^2 = ” << x*x << endl;
return 0;
}
При вводе строк встретите неожиданности,
которые рассмотрим позднее…
20. Промежуточный итог
Узнали особенности C++ на примере “Hello,World!”:
- Структура файла текста программы.
Включает инструкции препроцессора - #...;
- Процесс построения программы на C++ и коечто о препроцессоре;
3 шага;
- Бегло рассмотрели средства ввода/вывода.
cin/cout и операции <<, >>;
21. Контрольные вопросы
1. Из каких шагов состоит построение программы на C++?2. Каковы действия ОС для выполнения программы?
3. Можно ли создать C-программу без единой функции?
4. Как в С++ вывести переменную типа double на консоль с
использованием стандартной библиотеки?
5. Что означает имя endl в стандартной библиотеке C++?
6. Как выполнить чтение целого числа с консоли в переменную y?
7. Назовите инструкции препроцессора, рассмотренные в лекции.
8. Как в тексте программы обнаружить инструкции
препроцессора?
9. Что определяет заголовочный файл iostream?
22. Встроенные типы данных*
• int … uint …, double … и char - числовые• bool - тоже целое число
char ch = ‘a’;
bool f = true;//false; В качестве bool может
выступать значение любого типа!
• указатели и массивы - производные типы.
23. Операции над числами
int x = 6, y = 5;cout << x << " + " << y << "= " << x + y << endl;
cout << x << " - " << y << "= " << x - y << endl;
cout << x << " * " << y << "= " << x * y <<>xendl;
+y=5
>x - y = -1
…" / "...;
…" % "...;
>x + y = 6
>/y=0
cout << x << " | " << y << "= " << (x | y) <<
endl;
>x % y = 2
cout << x << " & " << y << "= " << (x & y)>++x
<< endl;
=3
>x >>
y=0
cout << x << " ^ " << y << "= " << (x ^ y) <<
endl;
>x << y = 24
cout << x << " >> " << y << "= " << (x >> y) << endl;
cout << x << " << " << y << "= " << (x << y) << endl;
cout << "++x = " << ++x << endl;
cout << "~"<< x << " = " << ~x << endl;
24. Операции и выражения
• Выражение (expression) – конструкция, которая может бытьвычислена и примет определенное значение*.
• Выражение можно использовать как величины в другом
выражении.
• В C++ (как и в C-подобных) многие операции неожиданно
являются выражениями. Например, операция присваивания x =
y. Поэтому можно x = y = z = 3;
Из-за такого соглашения можно if(x = 3) … что часто приводит к
ошибкам!
• Аналогично операции << для cout и >> для cin являются
выражениями. Их значением является ссылка на тот же поток
вывода (ввода).
25. Операции над числами (битовые маски)
Инструкция define задает макроопределения#define <ИМЯ> <ЗНАЧЕНИЕ>
С использованием макроопределений текст программы
становится понятнее.
При обработке, препроцессор в тексте заменяет все имена
макроопределений на их значение.
#define READ 1
#define WRITE 2
#define APPEND 4
• READ | WRITE
• READ | APPEND
26. Функции
В C++ функции определяются так же как и методы в C#.<тип> <имя> (<параметры>)
{
<тело>
}
например,
int main (int argc, char * argv[]) {
return 0;
}
main – должна быть в каждой C++ программе. Это ее точка входа.
Такая функция:
a)Должна быть
b)Должна быть одна
27. Функции*
Правило: Сначала объявление, а потомиспользование.
Функция, переменная или тип сначала должны быть
объявлены в тексте программы, а использовать их
можно ТОЛЬКО ПОСЛЕ (ниже по тексту) объявления.
Самый простой, но не самый правильный вариант –
определять все функции перед main (могут быть
вызваны только в main или глубже).
В C# это не так. Методы можно вызывать где угодно,
лишь бы имелось их определение.
28. Функции* Прототип, заголовочные файлы, модули
На практике, часто необходимо в одном из модулей вызватьфункцию из другого модуля.
Для связи различных модулей используются заголовочные файлы
и прототипы функций.
Прототип – первая строка функции (без реализации), которая
завершается ‘;’.
Например, прототип функции main:
int main (int argc, char * argv[]);
Чтобы использовать функции из других *.cpp –файлов (модулей), их
прототипы выносятся в заголовочные *.h-файлы,
а заголовочные файлы включают в начале *.cpp-файлов.
Тогда по тексту cpp можно использовать все объявления из включенных
заголовков.
29. Термины и понятия Определение и объявление
Тем кто хочет понять язык более строго, следует различатьОпределение (имени – переменной, функции, …) и Объявление.
Определение – полное описание, которое позволяет компилятору
построить код.
Для функции это текст вместе с телом.
Объявление – ссылочное описание, которое позволят
компилятору сгенерировать обращение к имени.
Для функции это прототип.
Очевидно, что определение является и объявлением. Но не
наоборот.
Для переменных мы встречались только с определениями.
Объявления переменных и типов появятся чуть ниже.
После такого уточнения можно вернуться выше и проследить, как
применяются термины объявление и определение.
30. Функции Прототип, заголовочные файлы, модули
“Чтобы использовать функции из других *.cpp -файлов, ихпрототипы выносятся в заголовочные *.h-файлы,
а заголовочные файлы включают в начале *.cpp-файлов.”
В этом смысле, заголовочные файлы представляют собой
интерфейсы C++-модулей.
Т.е. h-файлы определяют, что и как может быть
использовано из соответствующего модуля.
Можно сказать, что пара: <имя>.cpp - <имя>.h образует
модуль компиляции. Каждый модуль компилируется
независимо. В результате получается <имя>.obj - <имя>.h.
31. Функции Прототип, заголовочные файлы и рекурсия
Сначала объявление, а потом использование.Как быть с рекурсией? [A()->B, а B()->A] Какую функцию описать
раньше?
Пример:
int A(int x) {
if(x<=0)
return 0;
return x+ B(x-1);
}
int B(int x) {
if(x<=0)
return 1;
return 2*A(x-1);
}
Прототипы снимают и эту проблему.
Компилятору достаточно прототипа (объявления), чтобы
скомпилировать вызов функции!
32. Функции* Прототип, заголовочные файлы и рекурсия
Прототипы (объявления) нужно поместить перед определениямифункций.
Пример:
Теперь с компиляцией
int A(int x);
int B(int x);
проблем не возникнет!
int A(int x) {
if(x<=0)
return 0;
return x+ B(x-1);
}
int B(int x) {
if(x<=0)
return 1;
return 2*A(x-1);
}
33. Роль h- и cpp- файлов Итог.
Исходные тексты модуля состоят из h- файла и cppфайла.В h-файл выносится интерфейс модуля (объявления).
В cpp-файле содержится реализация модуля
(определения).
Если A.cpp использует имена из B.cpp, то
чтобы компилятор “знал” как использовать имена из
B.cpp,
заголовочный файл B.h нужно включить в A.cpp.
34. Пример распределения кода по файлам
Test.h -------------------------------------------------------------------------void Swap (int &a, int &b); // Прототип функции (объявление)Test.cpp ----------------------------------------------------------------------void Swap (int &a, int &b)
// Обпределение функции
{
int c = a;
a = b;
b = c;
}
-----------------------------------------------------------------------------------Для применения функции в CPP-файле:
#include “test.h” // В Unix имя файла чувствительно к регистру. В Windows - нет
…
Swap(x, y);
…
35. Функции, C# и статические методы
В C# функций нет. Только классы, объекты и Методы. C# - чистообъектно-ориентированный язык.
Это может привести к коллизиям. Вспомним всю совокупность правил.
Правила:
1. Первая функция (метод), которая должна быть исполнена – метод
Main.
2. Чтобы вызвать метод, нужно создать объект.
3. Чтобы создать объект, нужно выполнить некоторый метод.
Возникает замкнутый круг (в C++ такой проблемы нет, там есть
просто функции, их можно вызывать без классов и объектов).
В C# (.Net) это решается статическими методами, которые нужно
вызывать без объектов, указывая только класс.
static void Main(string []argv)…
36. Промежуточные итоги
• Теперь знаем набор встроенных типов данных.Он мал (int, double, bool, char, …)
• Рассмотрели понятие “выражение”.
Понятнее стал синтаксис (x=y=2 … cout << a << b…и др.)
• Больше узнали о функциях в C++ и роли прототипов;
Для компиляции вызова функции компилятор “должен
знать ее прототип”
• Обратили внимание на “проблему” и решение с
вызовом Main в C#.
Статические методы.
37. Контрольные вопросы
1. Назовите 4 основных типа данных, определенных в языке C++.2. Дайте определение понятию “выражение” (expression) в языке
программирования.
3. Чему равны переменные x и y после выполнения оператора x = 2 * (y +=3),
если до его выполнения x равнялся 0, а y – единице?
4. Будут ли численно равны выражения: 9/5 и 9.0/5.0?
5. Чему численно будет равно выражение 2 | N, если перед этим стоит
инструкция #define N 5? Чему будет равно N & 2?
6. Какие из следующих условных выражений эквивалентны:
a. (x)
с. (!x)
b. (x == 0) d. (x != 0)
7. Возникнет ли синтаксическая ошибка, если в условном операторе написать
(x = 0)?
8. Можно ли в C++ написать x = y = 3? Почему?
9. Зачем нужны заголовочные файлы в C++?
10.Как в C# обошлись без функций?
38. Переменные и ссылки*
В C++ имеется понятие “ссылки”. Ссылки – это алиасы(псевдонимы) переменных.
int x = 3, &y = x;// y – ссылка на x. Должна быть инициализирована
при объявлении.
Теперь x и y – синонимы.
Синтаксически их использование не отличается от обычных
переменных.
x++;
y = 5;
Наличие и природа ссылок – одно из существенных отличий C++
и C#!
39. Передача параметров*
void Swap (int a, int b) {int c = a;
a = b;
b = c;
}
…
int x = 2, y = 3;
Swap(x, y);
Не сработает!
void SwapR (int &a, int &b) { // Параметры – ссылки
int c = a;
a = b;
b = c;
}
…
int x = 2, y = 3;
SwapR(x, y);
А здесь сработает!
40. Передача параметров
В C++ имеется 2 способа передачи параметров вфункции – “по значению” и “по ссылке”.
Какой использовать лучше?
Ответ зависит от цели и типа параметра!
• Должна ли функция изменять параметр?
• Насколько сложно создать копию параметра?
41. Передача параметров
• При передаче “по значению”, в функцию передаетсякопия с тем же значением. Изменить
передаваемый параметр такая функция не
сможет.
• Если параметр занимает много места в памяти или
требуется сложная процедура создания копии, то
лучше (быстрее) передавать его “по ссылке”.
• Чтобы предотвратить возможность в функции
изменять параметр переданный по ссылке, перед
ним ставится квалификатор const. Например,
void f(const int & x);
Все инструкции изменения x в теле функции f будут
запрещены!
42. Контрольные вопросы*
1. Можно ли вызвать void foo(int & a) следующимобразом: foo(x+y); Почему?
2. Может ли функция foo из предыдущего вопроса
изменить значение переменной, переданной в
качестве параметра?
3. В каких случаях нужно передавать параметры “по
ссылке”?
4. Как запретить изменение параметра переданного
по ссылке?
43. Указатели*
Одно из существенных отличий C++ от C# - интенсивноеиспользование указателей (в C# они используются редко).
int x = 5;
int *p = &x;
// указатель p (pointer) указывает на память
переменной x (его значение - адрес x)
//операция * - разыменование
cout << *p << endl; //Ссылка на x. Результат 5
(*p)++;
// увеличили значение
cout << *p << endl; //результат 6
cout << x << endl; // результат 6 - изменилась x
44. Операции над указателями*
*p – разыменование (получение ссылки на данные по адресу)p++ - переход к следующему элементу того типа, на который
указывает указатель (p-- - обратная операция)
p + i - сложение (вычитание) с целым – получаем указатель на i
элементов правее (левее).
p – t - вычитание двух указателей одного типа - целое число,
количество элементов между указателями.
p==t, p < t, p<=t, p > t, p>=t, p!=t
0 – указатель имеющий значение 0.
Означает, что не проинициализирован.
45. Операции над указателями Пример
Задача. Выполнить обмен значениями двухпеременных, используя указатели.
int x = 3, y = 5;
int *px = &x, *py = &y;
// Нельзя x и y, а только px и py
int t = *px; // поместить в t значение из памяти x
*px = *py; // поместить в x значение из памяти y
*py = t;
// поместить в память y значение из t
46. Указатели и массивы*
int m[5] = {1,2,3,4,5};int *p = m;
//int *p = &x; для массива
// амперсанд не нужен!
m
1
2
3
4
5
p
• Имя массива – указатель на первый
элемент!
47. Указатели и массивы*
int m[5] = {1,2,3,4,5};int *p = m; //раньше int *p = &x; для массива амперсанд
не нужен!
• Имя массива – указатель на первый элемент! Его
изменить НЕЛЬЗЯ, a p можно!
3 эквивалентных* варианта вывода массива на консоль:
for (int *p = m; p < m + 5; p++) //p++ передвигает указатель на след.
cout << *p << endl;
for (int i = 0; i< 5; i++)
// m + i сдвигает адрес на i элементов,
cout << *(m + i) << endl;
// а не байтов
for (int i = 0; i< 5; i++)
cout << m[i] << endl;
// m[i] тождественно *(m + i).
48. Правила интерпретации и объявления типов в C++
Объявление типов в C (C++) бывает сложнымint *(*p[])(int, int *)
В этом объявлении ищем имя переменной - p, затем
движемся вправо до окончания объявления или
закрывающей скобки: (*p[]) – “p – это массив”,
затем движемся влево до окончания объявлений или
открывающей скобки - “p – это массив указателей”.
Переходим ко внешнему объявлению и снова движемся
вправо: (int, int *) – “p – это массив указателей на функцию
с двумя аргументами”, и наконец переходим влево – “,
которая возвращает указатель на целое”.
Окончательно:
p – это массив указателей на функции с двумя
аргументами, которые возвращают указатель на целое
49. Массивы 2*
• Многомерных массивов нет. Объявляют массивмассивов:
int v[5][3]; // см. правило объявления типов
• Размер массива только по имени узнать нельзя.
• Если массив объявлен в текущем блоке, то общее
количество элементов можно вычислить с помощью:
sizeof(v)/sizeof(int);
или
sizeof(v)/sizeof(v[0]);
50. Массивы символов и z-строки*
z-строка (c-строка) – последовательностьсимволов, которая заканчивается 0 (символа
с кодом 0 нет).
char t[14]= “Hi, Kristy!”;
H
i
,
K
r
i
s
t
y
!
0
Длина массива и z-строки различаются!
?
?
51. Массивы символов и z-строки*
• Длина z-строкиchar s[32] = “Hi, Kristy!”, *p;
for (p = s; *p; p++);
int n = p – s; // Однотипные указатели можно вычитать
• Копирование z-строки*
char s[32] = “You are a crazy driver!”, t[32];
for (char *p=s, *d=t; *d++ = *p++; );
52. Массивы символов и z-строки*
• Сравнение z-строк (c-строк)char s[32] = “You are a crazy driver!”, t[32]= “Hi, Kristy!”, *p, *d;
Вопрос: Как сравниваются строки?
Посимвольно. До первого расхождения. Больше та строка, у
которой код символа больше!
for (p=s, d=t; (*d == *p) && *p; d++, p++);
cout << *p - *d << endl;
• Первое условие продолжения – равенство символов. Какова
роль *p?
• Почему не контролируется *d?
53. Указатели и ссылки (пояснение)
Те, кто начинает с C# часто путают указатели и ссылки.int x = 3;
int &y=x, *p=&x;
В C++ и указатель, и ссылка указывают на некоторую область памяти
(переменную). Но!
Ссылка связана с переменной, на которую она ссылается, “навсегда”. Со
ссылкой мы обращаемся как с переменной (y=5).
Указатель – адрес некоторой переменной. Указатель в разное время
может показывать на разные переменные (p = 0 – не указывает никуда).
Для связи со значением, на которое указывает указатель используется
операция разыменования (*p=5). Фактически, операция разыменования
дает ссылку на область памяти, на которую указывает указатель.
Ссылка и указатель имеют различный набор операций и используются
по-разному.
54. Промежуточные итоги
• Познакомились с указателями и операциями надними.
Переменные для хранения адресов
• Познакомились с массивами в C++.
Имя массива – константный указатель на первый элемент
• Познакомились с правилами чтения типов в C++.
Сначала вправо, потом влево и т.д.
• Познакомились с z-строками (c-строками);
Последовательность символов, которая заканчивается 0
55. Контрольные вопросы
1. Проинтерпретируйте объявление второго параметра main.int main(int argc, char* argv[])
2. Сколько операций умножения в операторе *p = *p * 2?
3. Сколько операций разыменования в операторе *p = *p * 2?
4. Перепишите оператор *p = *p * 2, используя только 2
звездочки.
А одну?
5. Какие 3 различных смысла в C++ имеет символ &?
6. Какие 3 различных смысла в C++ имеет символ *?
7. Результатом операции разыменования является “ссылка на
данные по адресу указателя”. Чем отличается от “значение по
адресу …”?
56. Контрольные вопросы
8. Можно ли сделать так, чтобы первый элемент C-массива имелиндекс 2?
А 0?
9. Если массив w проинициализирован значениями 1, 2, 3. Чему
равно значение выражения *w?
10.Чему равна величина p + i, где p – указатель на массив, а i –
целое число?
11.Чему равна величина p – d, где p и d – указатели на величины
типа double?
12.Поставьте эксперимент и выясните, чему равны элементы
массива w для каждого из определений:
int w[5]; и int w[5] = {}.
57. Структура “знаний” по C++
-Стандартная библиотека (STL)
-
ООП 1 (классы, объекты);
ООП 2 (создание и уничтожение
объектов);
Шаблоны;
ООП 3 (наследование, виртуальность, …);
Грамотное
программирование
время жизни переменных, состав модуля,
построение программы;
основные типы и понятия (ссылки,
указатели, выражения, прототипы, …);
синтаксические конструкции (объявления,
операторы, блоки, препроцессор);
<=
Основы и
низкоуровневое
программирование
-
Эффективное
программирование
58. Структура “знаний” по С++
• В каждом разделе есть содержательный минимум– мал по объему и позволяет решать 80% проблем.
• Для изучения эффективно не расширять, а
осваивать.
больше препроцессора, тонкости наследования, … delete, …
• Между слоями есть перекрытия. Их минимум. На
них не отвлекаться, а использовать.
cin, cout, string, new, delete, …
• Когда появится основа можно заполнять пробелы.
programming