Dyzzet|
C++ Data Science Алгоритмы Темы · Блог · YouTube · Telegram
§ 2. Переменные и типы

§ 2.1 Объявления, диапазоны, основы ввода и вывода

Переменные используются для хранения данных в программе. Они требуют объявления перед использованием. Сперва указывается тип переменной (в нашем случае это int — целое), затем её имя (как всякое другое имя, оно должно состоять только из латинских символов, цифр и знаков подчёркивания, причём оно не может начинаться с цифры).

int foo;

Чему сейчас равно значение переменной foo? Многие отвечают, что нулю. Но на деле это не так. Оперативную память компьютера можно сравнить с меловой доской: если вы намереваетесь что-то написать на ней, это ещё не значит, что доска чистая. Получается, что значение переменной может быть любым. Поэтому считается хорошим тоном всегда инициализировать переменные, то есть задавать их начальное значение.

int foo = 0;

Читать далее →
Конспект по языку C

Целевая аудитория — владеющие основами алгоритмизации и какого-либо языка программирования, те, кого не пугают слова «переменная» и даже «рекурсия». В курс (пока что) не входят многие серьёзные темы, например, volatile или глубины стандарта. Также я не буду рассматривать конкретные средства разработки, процесс создания проекта и компиляции. Лучше сосредоточимся на средствах языка и стандартной библиотеки. Если вы можете самостоятельно справиться с этим, то справитесь и с материалом. Сперва нужно быть знакомым с основами компьютерных архитектур, уметь переводить числа между разными системами счисления, складывать, вычитать в них и так далее, владеть основами логики, комбинаторики. Не лишним будет умение читать технические тексты по-английски и писать комментарии.

C — язык промышленного программирования, а не учебный, поэтому многие детали могут изначально пугать. Например, диапазоны переменных одного типа при компиляции на разных компьютерах могут различаться, малейшие опечатки — оборачиваться странным поведением программы или непонятными сообщениями об ошибках. Об истории языка и различиях в версиях и стандартах читайте самостоятельно.

Это, скорее, конспект без лишнего шума. Люди не машины, нам нельзя скормить алфавит, ключевые слова, завалить терминами «сигнатура» и «семантика», дать грамматику языка и что-то ждать в ответ. Я буду показывать примеры — от простого к сложному — которые вам нужно компилировать, изучать, как-то изменять. Самостоятельность — ключ к глубокому пониманию.

10 июля 2017
Полиморфная кухня — 5. C++11 и C++14

В пятой части серии рассмотрим возможности наследования и полиморфизма, которые появились в стандарте C++11, а также C++14.

Возьмём иерархию из предыдущей статьи (исходный текст см. там же).

Читать далее →
8 января 2017
Полиморфная кухня — 4. Приведение dynamic_cast и RTTI

Как у наших ворот за горою
Жил да был бутерброд с колбасою.
Захотелось ему прогуляться,
На траве-мураве поваляться.
И сманил он с собой на прогулку
Краснощёкую сдобную булку.
Корней Чуковский

В трёх первых частях серии мы подробно рассмотрели многие аспекты, касающиеся наследования и полиморфизма в C++. Сегодня поговорим о динамическом приведении типа и об идентификации типа на этапе исполнения программы.

Во вводной статье мы уже рассматривали приведение типа static_cast, которое имеет ограниченное применение. Когда дело касается приведения между типами, которые являются полиморфными (имеющими хотя бы одну виртуальную функцию), используется dynamic_cast (с неполиморфными классами это даже не скомпилируется).

Как всегда, придумаем какую-нибудь несложную иерархию.

Читать далее →
28 декабря 2016
Полиморфная кухня — 3. Множественное и виртуальное наследование

В первой части серии мы рассмотрели основы наследования и полиморфизма в языке C++, во второй рассмотрели механизм, благодаря которому всё это работает. Идём дальше: создадим более замысловатую иерархию.

Сегодня реализуем следующую иерархию. Базовым классом будет класс Cmyk, реализующий цветовую схему CMYK. Класс CmykGy будет содержать дополнительный серый, класс CmykLcLm — дополнительные светло-синий и светло-малиновый. Класс CmykGyLcLmLg внизу иерархии будет содержать все упомянутые дополнительные цвета (серый, светло-синий, светло-малиновый), а также светло-серый.

Читать далее →
20 октября 2016
Полиморфная кухня — 2. Таблицы виртуальных функций

В предыдущей статье мы рассмотрели основы наследования и полиморфизма в языке C++. Теперь подробнее рассмотрим, как реализован механизм полиморфизма.

Повторим основные моменты. Если в классе есть хотя бы одна функция с ключевым словом virtual, то она считается виртуальной, а сам класс — полиморфным. Для каждого полиморфного класса создаётся специальная таблица — таблица виртуальных функций. А каждый объект любого из полиморфных классов дополняется указателем на одну из таких таблиц.

Рассмотрим простую иерархию: розетка и заземлённая розетка.

                                          Socket                                
                                            ↑
                                      GroundedSocket

Читать далее →
26 августа 2016
Полиморфная кухня — 1. Наследование и полиморфизм в C++

В языке C++ наследование и полиморфизм — очень важные понятия. Эта тема довольно обширна, для её понимания необходимо хорошо уяснить для себя, как объекты реального мира соотносятся с объектами в языке, как и когда происходит создание и уничтожение объектов, как работать с памятью, ссылками, указателями и зачем необходимы списки инициализации. Не лишним будем знание стандартных контейнеров, умных указателей и понимание смысла константности.

Напишем класс Pancake. Добавим три поля: радиус блинчика, толщину и сорт муки. Конструктор этого класса снабдим списком инициализации. Последний штрих — напишем функцию print().

class Pancake
{
public:
    Pancake(int radiusMm, int thicknessMm, int flourSort) :
        radiusMm_(radiusMm),
        thicknessMm_(thicknessMm),
        flourSort_(flourSort)
    {
    }
 
    void print() const
    {
        std::cout << "Pancake." << std::endl;
    }
 
protected:
    unsigned radiusMm_;     // RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR
    unsigned thicknessMm_;  // TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT
    char flourSort_;        // SSSSSSSS 00000000 00000000 00000000
};

Читать далее →
16 июля 2015
Запятая, Карл! Как устроены типы float и double

Плавающая запятая даёт много преимуществ, но «заплыв» этот полон моментов, требующих понимания и тщательного подхода. Числа с плавающей запятой используются слишком часто, чтобы пренебрегать их глубоким пониманием. Поэтому нужно хорошо разбираться, как представлены числа с плавающей запятой и как работают вычисления с ними.

Экскурс

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

$$N=(-1)^{s}\cdot m \cdot 2^{e},$$

где \(m\) — мантисса (23 бита — дробная часть мантиссы и неявно заданный ведущий бит, всегда равный единице, поскольку мантисса хранится в нормализованном виде), \(e\) — смещённая экспонента/порядок (8 бит). Один бит отводится под знак (\(s\), бит равен нулю — число положительное, единице — отрицательное).

Тип double полностью аналогичен float, он лишь содержит больше битов мантиссы и порядка.

Рассмотрим какой-нибудь пример. Число \(3{,}5\) будет представлено в следующем виде:

Читать далее →
20 апреля 2015
Массив здорового человека. Теперь в 3D!

В прошлой статье разбирались достоинства и недостатки различных форм представления массивов в памяти. В этот раз рассмотрим трёхмерный случай (и вообще \(N\)-мерный) и обратим внимание на то, как производится пересчёт логических координат в фактические.

Сперва вернёмся к двумерному случаю. Обращение к \(j\)-у элементу, раположенному в \(i\)-й строке, выглядит следующим образом: array_of_a_healthy_man[i * w + j] (\(w\) — количество элементов в строке). На рисунке представлено логическое и фактическое представление двумерного массива. Таким образом, слагаемое \(i \times w\) означает «пропустить \(i\) строк, содержащих по \(w\) элементов».

Читать далее →
12 апреля 2015
Массив здорового человека

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

Пусть необходимо хранить следующий массив элементов типа int размерностью \(5\times 10\).

\(35\ 58\ 73\ 32\ 35\ 32\ 59\ 95\ 19\ 39\\ 64\ 54\ 45\ 73\ 52\ 20\ 92\ 76\ 94\ 92\\ 47\ 93\ 65\ 14\ 25\ 92\ 27\ 93\ 14\ 94\\ 90\ 45\ 85\ 31\ 69\ 32\ 95\ 12\ 87\ 53\\ 75\ 11\ 47\ 72\ 33\ 42\ 58\ 62\ 57\ 85\)

Самый адекватный вариант в большинстве случаев — выделить в куче один массив для всех элементов.

const int w = 10, h = 5;
int* array_of_a_healthy_man = new int[h * w];

Читать далее →
5 4 3 2
1
© MMXI—MMXXV. RSS
 Boosty
Светлая тема / тёмная тема