Введение в язык C++

Цель данного занятия -- познакомить вас с основными конструкциями и типами данных языка C++ (стандарта 2017 года, C++17). Познакомиться к простым контейнером vector. Посмотреть на некоторые тонкости использования языка.

А также развернуть среду разработки и познакомить вас с контестером МИСиС.

Ну и начнём с того, что вы зарегистрируетесь и отметитесь на нашем сайте https://icpc.appmat.ru

Среды разработки

IDE -- это интегрированная (I) среда (E) разработки (D), в которую сразу включены все плюшки, типа подстветки синтаксиса, рефакторинга, подсказлок, линтера.

Редактор кода (типа VS Code, Atom, Emacs) -- конструктор, из которого можно собрать для себя IDE с теми же возможностями.

Установка CLion на Windows и macOS имеет свои особенности:

Первая программа

#include <iostream>

using namespace std;

int  main() {
    cout << "Hello, world!" << endl;
}
In [1]:
#include <iostream>

using namespace std;

cout << "Hello, world!" << endl;
Hello, world!

Типы данных

Естественно, в языке есть разные типы данных.

Тип данных Назначение Диапазон
bool Логичное (Истина или ложь) $${True, False}$$
char Один символ $$-128..127$$
short Целое число $$-2^{15}... 2^{15}-1 $$
int Целое число $$-2^{31}... 2^{31}-1 $$
float Число с плавающей точкой $-2.22507*10^{-308} ... +1.79769*10^{308}$, 7-8 знаков после запятой

Модификаторы.

  • long -- длинное число, увеличивает количество знаков, хранимых в числе.
  • unsigned -- делает число беззнаковым, что увеличивает диапазон в 2 раза.
In [2]:
#include <iostream>
#include <limits>

using namespace std;
In [3]:
template<typename T>
void showMinMax() {
   cout << "min: " << numeric_limits<T>::min() << endl;
   cout << "max: " << numeric_limits<T>::max() << endl;
   cout << endl;
}
In [4]:
{
    cout << "short:" << endl;
    showMinMax<short>();
    cout << "int:" << endl;
    showMinMax<int>();
    cout << "long:" << endl;
    showMinMax<long>();
    cout << "long long:" << endl;
    showMinMax<long int>();
    cout << "float:" << endl;
    showMinMax<float>();
    cout << "double:" << endl;
    showMinMax<double>();
    cout << "long double:" << endl;
    showMinMax<long double>();
    cout << "unsigned short:" << endl;
    showMinMax<unsigned short>();
    cout << "unsigned int:" << endl;
    showMinMax<unsigned int>();
    cout << "unsigned long:" << endl;
    showMinMax<unsigned long>();
    cout << "unsigned long long:" << endl;
    showMinMax<unsigned long long>();
}
short:
min: -32768
max: 32767

int:
min: -2147483648
max: 2147483647

long:
min: -9223372036854775808
max: 9223372036854775807

long long:
min: -9223372036854775808
max: 9223372036854775807

float:
min: 1.17549e-38
max: 3.40282e+38

double:
min: 2.22507e-308
max: 1.79769e+308

long double:
min: 3.3621e-4932
max: 1.18973e+4932

unsigned short:
min: 0
max: 65535

unsigned int:
min: 0
max: 4294967295

unsigned long:
min: 0
max: 18446744073709551615

unsigned long long:
min: 0
max: 18446744073709551615

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

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

In [5]:
{
    unsigned long a = 10;
    a -= 11;
    cout << a << endl;
}
18446744073709551615

Математические операции

В языке C++ есть все стандартные операции:

Операция (выражение) Оператор Синтаксис выражения
Присваивание = a = b
Сложение + a + b
Вычитание - a - b
Унарный плюс + +a
Унарный минус - -a
Умножение * a * b
Деление / a / b
Операция модуль (остаток от деления целых чисел) % a % b

И несколько нестандартных:

Операция (выражение) Оператор Синтаксис выражения
Инкремент префиксный ++ ++a
суффиксный (постфиксный) ++ a++
Декремент префиксный -- --a
суффиксный (постфиксный) -- a--

Есть также составное присвоение:

Операция (выражение) Оператор Синтаксис выражения
Сложение, совмещённое с присваиванием += a += b
Вычитание, совмещённое с присваиванием -= a -= b
Умножение, совмещённое с присваиванием *= a *= b
Деление, совмещённое с присваиванием /= a /= b
Вычисление остатка от деления, совмещённое с присваиванием %= a %= b
In [6]:
{
    int a = 5, b = 3; 
    cout << a / b << endl;
}
1
In [7]:
{
    int a = 5;
    float b = 3; 
    cout << a / b << endl;
}
1.66667
In [8]:
{
    int a = 5, b = 3; 
    cout << (float)a / b << endl;
}
1.66667
In [9]:
{
    int a = 5, b = 3; 
    cout << 1 / a << endl;
}
0
In [10]:
{
    int a = 5.6, b = 3; 
    cout << 1.0 / a << endl;
}
input_line_18:3:13: warning: implicit conversion from 'double' to 'int' changes value from 5.6 to 5 [-Wliteral-conversion]
    int a = 5.6, b = 3; 
        ~   ^~~
0.2
In [11]:
{
    string s = "Hello, world!";
    cout << s << endl;
}
Hello, world!
In [12]:
{
    string s = "Hello, world!";
    string s2 = " Vasya";
    cout << s2 + s << endl;
}
 VasyaHello, world!
In [13]:
{
    int a = 5;
    cout << a + 5 << endl;
}
10
In [14]:
{
    int a = 11, b = 2;
    cout << a % b << endl;
}
1
In [15]:
{
    int wtf = 5;
    wtf = ++wtf + wtf++;
    cout << wtf << endl;
}
input_line_23:4:11: warning: multiple unsequenced modifications to 'wtf' [-Wunsequenced]
    wtf = ++wtf + wtf++;
          ^          ~~
12

Условные операторы

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

if (x) {
       //  Если x - истина
   } else {
      // Если x - ложь   
   }
In [16]:
{
    int x = (float)rand() / RAND_MAX*30;
    if (x > 25)
        cout << "Идём на пляж! Температура: " << x << endl;
    else
        cout << "Сидим дома! Температура: " << x << endl;
}
Сидим дома! Температура: 14

Цикл For

Циклы -- стандартная конструкция большинства языков программирования, которая позволяет выполнять операцию несколько раз, проходить по массивам элементов.

Простейший цикл for -- он позволяет пройтись по заданным числам с определённым шагом.

In [17]:
{
    for (int i = 0, j = 0; i < 100 && j < 100; i++, j+=2)
        cout << i << " " << j << " ";
}
0 0 1 2 2 4 3 6 4 8 5 10 6 12 7 14 8 16 9 18 10 20 11 22 12 24 13 26 14 28 15 30 16 32 17 34 18 36 19 38 20 40 21 42 22 44 23 46 24 48 25 50 26 52 27 54 28 56 29 58 30 60 31 62 32 64 33 66 34 68 35 70 36 72 37 74 38 76 39 78 40 80 41 82 42 84 43 86 44 88 45 90 46 92 47 94 48 96 49 98 

Задача №1. Простые числа.

Требуется вывести все простые числа из диапазона от 1 до 100.

In [18]:
{
    bool prime = true;
    for (int i = 2; i < 100; i++) {
        prime = true;
        for (int j = 2; j <= sqrt(i); j++)
            if (i % j == 0) {
                prime = false;
                break;
            }
        if (prime)
            cout << i << " ";
    }
}
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 

Задача №2. Среднее арифметическое

Требуется найти среднее арифметическое $N$ чисел $a_i$, при этом $0 < N < 100$, $a_i < 100$.

In [19]:
{
    int n;
    cin >> n;
    double avg = 0;
    for (int i = 0; i < n; i++) {
        int tmp;
        cin >> tmp;
        avg += tmp;
    }
    avg /= n;
    
    cout << "Avg: " << avg << endl;
}
10
1 2 3 4 5 6 7 8 9 10
Avg: 5.5

Задача №3. Посчитать интеграл

Требуется посчитать интеграл функции $f(x) =\frac{1}{3} (\sin(x) + 1) * e^{x}$ в диапазоне от 0 до 5 с точностью до третьего знака после запятой.

In [20]:
{
    float res = 0;
    for (float x = 0; x <= 5 + 1e-4; x += 1e-4) {
        res += (1.0 / 3) * (sin(x) + 1) * exp(x) * 1e-4;
    }
    cout << res << endl;
}
18.5795

Векторы

Для хранения массивов данных в C++ есть стандартный контейнер vector. Он может хранить элементы только одного типа, к примеру vector<int>.

In [21]:
#include <vector>

using namespace std;

По вектору можно пройти циклом for.

In [22]:
{
    vector<int> a(10);
    for (int i = 0; i < 10; i++) {
        a[i] = i;   
        cout << a[i] << " ";
    }
    
}
0 1 2 3 4 5 6 7 8 9 

Задача №4. Больше среднего

Требуется найти все значения последовательности $a_i$ из $N$ чисел $a_i$, при этом $0 < N < 100$, 0 < $a_i < 100$, которые больше среднего значения элементов этой последовательности.

In [23]:
{
    int n;
    cin >> n;
    vector<int> a(n);
    double avg = 0;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        avg += a[i];
    }
    
    avg /= n;
    
    cout << "Avg: " << avg << endl;
    
    for (int i = 0; i < n; i++)
        if (a[i] >= avg)
            cout << a[i] << " ";
}
10
1 2 3 4 5 6 7 8 9 10
Avg: 5.5
6 7 8 9 10 

Задача №5. Не повторяется такое никогда (повторяется)

Требуется найти все элементы последовательности $a_i$ из $N$ чисел $a$, при этом $0 < N <= 100$, $0 < a_i <100$, которые встречаются в ней больше одного раза.

In [24]:
{
    int n;
    cin >> n;
    vector<int> a(100, 0);

    for (int i = 0; i < n; i++) {
        int tmp; 
        cin >> tmp;
        a[tmp]++;
    }
    
    for (int i = 0; i < 100; i++)
        if (a[i] > 1)
            cout << i << " ";
}
10
1 1 2 2 3 4 5 6 
7
8
1 2 

Контест для самостоятельного решения

Ссылка на регистрацию: https://contest.misis.ru/auth/register?groupKey=59128ab789d2354c1a5289c778d9cacc17245a3adbb4183f7d8bf2408174117906188a26eb235e073a94bc53d5e37d3c

Ссылка на контест: https://contest.misis.ru/contests