АЙТИШНЫЙ САЙТ ПЕТРА СЕМИЛЕТОВА

ПЕТР СЕМИЛЕТОВ

ПРОСТО С++: УРОК 3

Основы работы с консолью. Почему важен текстовый вывод. Двоичная система счисления - о ужас. Что такое переменная, ее имя и значение. Зачем типы данных? Объявление переменных.

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

Для запуска компилятора мы использовали консоль, или терминал. До появления интерфейсов с окнами, кнопочками и разными картинками, основным способом общения пользователя с компьютером был текстовый экран и команды, вводимые с клавиатуры. Этот способ наиболее прост и в программировании, поэтому когда мы станем учиться писать программы, то будем использовать только ввод с клавиатуры и вывод букв на экран.

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

В Windows консоль стандартная и одна, в Линуксе же есть много разных эмуляторов терминала, которые отличаются друг от друга внешним видом и возможностями. Например, в некоторых есть вкладки, как в браузере.

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

В Windows интерпретатор команд называется cmd.exe, а в Линуксе есть разные, но наиболее популярен Bash. В Windows, cmd.exe можно запустить, нажав Win-R, и в открывшемся окне Запуска набрать команду cmd, а затем нажать Энтер.

Однако, как я говорил в прошлой серии, мы используем Cygwin-Терминал, а это терминал Линукса, перенесенный в Windows, соответственно в Cygwin-Терминале запущен командный интерпретатор Bash.

В давние времена, человек запускал компьютер и видел такой вот терминал с Башем. Но с компьютером надо что-то делать - запускать программы, копировать файлы и так далее. Всё это осуществляется при помощи команд, вводимых с клавиатуры. Вводите команду, нажимаете Энтер - интерпретатор выполняет команду.

Так, если набрать имя установленной программы, и нажать Энтер, то указанная программа запустится.

В Windows привычно понятие папки или каталога. Раньше, да и сейчас в некоторых системах, таких как Линукс, для этого более в ходу другое слово - директория (directory). Это одно и то же.

Чтобы узнать список каталогов и файлов в текущей директории, надо дать команду ls и нажать Энтер. Далее для упрощения я не буду говорить вам - нажать Энтер, просто помните, что ввод каждой команды надо завершать нажатием этой клавиши.

ls это сокращение от английского слова list - список. Команды системы UNIX - а Линукс это UNIX-подобная система - большей частью являются сокращениями, чтобы удобно было набирать. ls выводит сначала директории, а следом за ними файлы.

Чтобы перейти в другой каталог, надо ввести команду cd с последующим именем каталога. cd это сокращение от change directory, сменить директорию.

Таким образом командой ls мы узнаём, какие еще есть директории в текущей, затем пишем cd такая-то директория, и нажимаем Энтер. Если полностью набирать имя каталога не хочется, можно начать его набирать и нажать Tab - командный интерпретатор попробуем сам дописать название.

Чтобы подняться в каталог уровнем выше, надо дать команду cd пробел и две точки:

 cd ..

Чтобы подняться в корневой каталог, cd пробел и одна точка:

cd .

Для копирования файлов служит команда cp - сокращение от copy, для удаления - rm - сокращение от remove, удалить, для переименования или перемещения mv (сокращение от move) и так далее. Например:

rm file.txt

…удаляет файл с именем file.txt

А вот переименует file1.txt в file2.txt

mv file1.txt file2.txt

Скопирует файл.txt в каталог backup:

cp file.txt backup

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

Итак, с равным успехом вы можете работать с файловой системой и в консоли, и в каком-нибудь Проводнике. Разные внешне и внутри, они выполняют одни и те же функции.

В Линуксе много чисто консольных программ и программ, управляемых из командной строки, когда вместо выбора разных параметров при помощи полей ввода, кнопок и переключателей вы пишете в той же консоли имя программы, перечисляете после него в текстовом виде параметры и Энтером посылаете это на выполнение.

Например, вы можете дать команду mpv и указать после нее имя файла с каким-нибудь фильмом. Запустится крутой мультимедийный плейер mpv и откроет видеофайл. Разработка программ, управляемых из консоли - не каменный век, а другой подход.

И если учиться писать программы, то в случае консольной мы можем сразу понятно выводить что-то на экран и получать ввод с клавиатуры, а для создания оконной программы с кнопочками нам пришлось бы изучать слишком много на первых порах лишнего. Итак, мы сокращаем путь от теории к практике.

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

Язык программирования это язык в первую очередь письменный. Конечно, можно читать исходники вслух, но в случае реальных и сложных программ это неудобно и никому не нужно. Тексты программ воспринимаются в первую очередь глазами, когда внутреннее озвучивание зачастую отсутствует вовсе, поэтому даже у англоязычных программистов иногда возникают вопросы, когда требуется все же как-то озвучивать написанное. При случае я коснусь этого подробнее.

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

Мы строим речь при помощи предложений. В С++ предложения называются выражениями. Каждое выражение надо завершать точкой с запятой. Можно объединять несколько выражений в одно составное при помощи фигурных скобок, открывающей и завершающей - {}. В таком случае, после завершающей скобки, точка с запятой не ставится. Сейчас это пустые слова, но когда придет время, вы о них вспомните и они обретут плоть.

Выражения составляются из слов. В С++ есть как бы встроенный словарь, основа языка. Эти основные слова называются ключевыми или зарезервированными. Вот примеры таких слов:

if - если
else - иначе

Эти слова нужны для построения логических выражений. Наш образ мыслей мы переносим в программу. Мы как бы размышляем и записываем это алгоритмически.

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

Или - если человек ввел правильный пароль, выслать ему деньги, иначе вывести сообщение об ошибочном пароле.

Полный список ключевых слов С++ можно посмотреть по ссылке.

Итак, эти слова имеют для языка С++ определенное значение и заданы правила их использования.

Также вы можете расширять словарный С++ запас за счет своих слов, добавляя в программу нужные вам вещи.

Простейшие такие штуки - это, во-первых переменные, а во-вторых - функции.

Функция это поименованный алгоритм. Иначе говоря, написанный вами набор выражений, которому вы даете имя, название. Затем, вы пишете в программе имя функции, и в месте, где вы его написали, программа при своем выполнении произведет так называемый вызов функции, то есть будут выполнены выражения, из которых состоит эта функция. Это как записать рецепт, дать ему название и потом, когда вы хотите приготовить блюдо, просто назвать вслух его название и перечислить, сколько каких продуктов вы туда кладете.

Подробнее к функциям мы обратимся позже.

Теперь о переменных. Вы знакомы с ними со школы - все эти иксы, игреки, буквы в формулах, где V обычно означает скорость, T - время и так далее. В программировании переменные ощущаются менее абстрактно и создаются вами при необходимости хранить какие-то данные, ибо переменная это поименованная область памяти.

Представьте себе склад - это память. На складе лежат разного размера коробки с названиями. Вот эти коробки и есть переменные. В них можно складывать числа. В компьютере вообще всё это числа - буквы тоже числа, звук, картинки - всё разложено на числа, все ими представлено.

Продолжу пример с коробкой. Имя переменной - это надпись на коробке. Как я уже говорил, исторически сложилось и принято давать переменным имена на английском, латинскими буквами. В новых версиях С++ появилась возможность использования Unicode, а значит и славянских алфавитов. Хотите - называйте переменные на привычном языке.

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

Помните! Имена функций и переменных всегда надо начинать с буквы! В имени может быть число, например A1, B1, но первой всегда стоит буква, большая или маленькая. Также, в С++, в составе имени можно использовать символ подчеркивания, однако никакие другие символы - ни точки, ни запятые, ни знак доллара и тому подобное.

Теперь, важное понятие - значение переменной - то, что ХРАНИТСЯ в коробке. Это некое число. От размера коробки, зависит наибольший размер числа, хранимого в ней.

Напомню, что размеры в компьютере строго регламентированы. Наименьший размер - бит. В бите может быть число, 0 или 1. Следующий размер - байт. Байт состоит из 8 бит. Внутренне, компьютерная техника использует двоичную систему счисления, где все числа состоят из сочетаний нулей и единиц.

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

Если кратко, то в десятичной системе у нас есть цифры от 0 до 9. Число - это количество чего-либо, и оно записывается цифрами.

Если мы начнем считать 1, 2, 3, 4 и так до 9, то есть будет добавлять к числу по единице, и затем добавим к девяти единицу, то сумма, число, будет состоять уже из двух цифр, 10. Два разряда. Один это числа до десяти, второй разряд - где мы считаем уже десятки. 20, 30, и так далее.

Когда у нас будет 99 и мы добавим 1, произойдет переполнение наших двух разрядов и мы вылезем в третий, где считаются уже сотни. 100 - одна сотня. 110 - одна сотня, один десяток. 115 - одна сотня, один десяток, 5 единиц.

В двоичной системе всё проще. У нас есть всего две цифры - 0 и 1.

Начнем считать, добавлять по единице. Сначала у нас просто 0. Добавляем 1:

0+1=1 

Добавляем еще одну единицу:

1+1=?

Но в двоичной система у нас всего 2 цифры, 0 и 1, других нет, мы не можем ими пользоваться. Нет ни три, ни четыре, ничего такого. Поэтому… Для наглядности запишу в столбик. Мы складываем верхнее с нижним:

 1+
 1
  =
10

Это не десять. Это просто так написано. На деле, наше число просто увеличилось на регистр. Единички сложились и не могли уместиться в одном разряде, поэтому переместились в новый, дополнительный. А в начальном разряде стал нолик.

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

Как же будет выглядеть в двоичной системе счисления количество три?

А добавим к количеству 2 еще единицу. Напоминаю - это пример в двоичной системе.

10+
 1
  =
11

Всё складывается согласно обычной математике, но мы ограничены нулем и единицей. Один плюс один дает нам перенос в следующий разряд.

Добавим еще единичку, чтобы получить количество 4:

 11+
  1
   =
100

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

Но довольно, вам это пока не нужно! И еще долго не будет нужно!

Вот сухие факты.

В переменную размером 1 байт, то есть 8 бит, поместится число, которое может быть от 0 до 255. В такой переменной можно хранить много чего полезного. Например, в игре это может быть количество жизней персонажа. Или одна из его координат на экране. Помните восьмибитные игровые приставки? В NES - более известной у нас как Денди, разрешение экрана составляло 256x240 пикселов. Оно происходило именно из-за восьмибитной природы используемого в нем процессора, регистры которого - быстрые ячейки памяти - просто не могли хранить в себе бОльшие числа.

Однако, как вы знаете, числа могут быть еще и отрицательными. Как быть, если в восьмибитной переменной, в переменной размером в один байт, нам нужно хранить не числа от 0 до 255, а еще и отрицательные числа? Тут мы переходим к одному из свойств чисел - они могут быть знаковыми и беззнаковыми. Знаковое число может быть не только положительным, со знаком плюс, но и отрицательным, со знаком минус. А беззнаковое - всегда положительное.

Правда в том, что в переменной размером 1 байт может храниться и знаковое число, но тогда его значение ограничено диапазоном от -128 до +127. Как видим, этот диапазон получен делением пополам всё те же пресловутых 255 с нулем в придачу, то есть 256 возможных вмещаемых в один байт чисел.

Теперь допустим, что мы пишем на С++ игру. И у нашего персонажа есть параметр жизнь. Пусть за этот параметр отвечает переменная, назовем ее life. Когда персонажа будут ранить враги, от значения переменной будут отниматься по единице, и если значение достигнет нуля, персонаж погибнет и будет конец игры. Мы можем на экране вместо числа, количества жизней - выводить сердечки, что угодно. Но внутренне это будет число.

Чтобы поместить такую штуку в нашу программу-игру, надо объявить переменную. Это значит - написать в программе ее имя и указать тип переменной, чтобы компилятор знал, сколько ей дать памяти.

Тип переменной, в простейшем случае, это одно из зарезервированных слов, при помощи которого мы задаем размер переменной. Какого размера будет коробочка?

Наша переменная life будет хранить беззнаковое число, у нас ведь не может быть отрицательной жизни.

Поэтому в программе на С++ мы, чтобы объявить переменную life напишем следующее выражение:

unsigned char life;

Первое слово, unsigned - переводится как беззнаковый. Второе слово, char - сокращение от character, символ, буква. Наши программисты иногда ошибочно произносят этот тип как “кэр”, однако правильное, принятое в мире произношение - чар.

unsigned char здесь - тип переменной. Так называется тип. И в программе под переменную life отводится памяти ровно 8 бит, они же 1 байт, в котором можно хранить число от 0 до 255.

Если мы напишем вместо этого

char life;

То ничего страшного не случится, просто самое большое число, которое мы можем хранить в life, равно теперь 127 вместо 255.

А что будет, если персонаж бегает-прыгает, собирает дополнительные жизни и его никто не ранит? Что если персонаж подбирает на уровне жизнь, превышающую максимальное число, которое может поместиться в переменной?

Допустим, life у нас объявлена как беззнаковое число:

unsigned char life;

Вот наш герой уже имеет 255 жизней и берет еще одну. 255+1, должно получиться 256, но они физически не могут поместиться в нашей коробочке. Тогда в программе происходит переполнение. Но деваться за пределы отведенной памяти числу некуда, поэтому отсчет как бы возвращается в начало диапазона. Если к восьмибитному 255 добавить 1, мы вернемся к началу диапазона, то есть к нулю. Если восьмибитному 255 добавить 2, получим 1, ибо мы вернулись к нулю и добавили хвостик, единицу. Таким образом при переполнении счет идет как бы кольцеобразно, по кругу.

А как быть с диапазоном от -128 до +127. Точно так же. Добавляем к 127 единицу и переносимся к -128.

Поэтому, во избежании переполнения, в программах ставят проверочные ограничители.

Пожалуй, самый популярный в С++ тип это не варианты char, а int - сокращение от integer, целый. int дает нам размер переменной аж 4 байта, что позволяет хранить в ней числа в диапазоне от -2147483648 до 2147483647 в случае знакового типа и от 0 до 4294967295 в беззнаковом варианте.

Допустим, мы хотим хранить в переменной, сколько денег у нас в банке, имея в виду соображения, что деньги могут уйти в минус, в кредит. Мы должны предусмотреть это, а значит, нам понадобится ЗНАКОВЫЙ тип, где есть поддержка отрицательных чисел.

Пишем в программе:

int money;

Всё, у нас есть переменная для хранения денег до 2 миллиардов с гаком.

А если нам нужно больше, и без возможности уйти в минус? Тогда пишем:

unsigned int money;

Так мы получим возможность хранить уже до 4 с гаком миллиардов.

Под конец сегодняшнего урока рассмотрим еще один тип, для хранения дробных чисел. Ведь до сих пор мы работали только с целыми.

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

Конечно, для денег тип с дробью подходит больше всего, ведь в дробную часть уходят копейки.

Итак, объявляем переменную

float money;

Тип float поддерживает как положительные, так и отрицательные числа и занимает 4 байта в памяти.

Что же, к написанию работающего примера программы мы еще не приступили, но - тише едешь, дальше будешь. Накапливаем знания, чтобы ко времени написания программы было понятно всё.

Поддержать курс:

Навигация:

Оглавление

Предыдущий урок

Следующий урок