Архив рубрики: Основы программирования на C++

В этой рубрике объединены статьи нашего сайта, которые освещают основы программирования на C++ для начинающих

О локализации символьных строк




локализация символьных строк в с++

Подавляющее число примеров кодов со строками C/C++ (в любых публикуемых источниках) оперирует с нуль-терминальными массивами (ASCIZ) элементов char (в стиле C), или с контейнерным типом string (в стиле C++), построенным как надстройка над такими массивами. Всё это замечательно работает со строками латинских (англоязычных) символов, но может идти вразнос на строках, содержащих символы иноязычных алфавитов (русский, китайский, арабский или иврит). Здесь всё не так просто… и весьма плохо описано в литературе, что и понятно: англоязычных авторов мало занимают вопросы иноязычной локализации, а отечественные авторы, в большинстве, переписывающие и адаптирующие англоязычные публикации, не уделяют внимания этой стороне вопроса.

Язык C — весьма старый язык программирования, а C++ наследует из него форматы и сдерживается требованиями синтаксической совместимости с C. Для того, чтобы не иметь в C/C++ проблем с такими строками (называемыми локализованными) нужно понимать что там с этими локализациями происходит…

Исторически, символы (char) представлялись (1963 год) стандартом ASCII как младшие 7 бит одного байта, при этом старший 8-й бит предназначался для контроля ошибок, возникших при передаче данных. Такая кодировка позволяет кодировать максимально всего 128 различных символов, и этого числа с трудом хватает на символы английского алфавита (большие и малые), цифровые (коды 0x30-0x39), управляющие (код меньше 0x20) и специальные символы. Когда возникала необходимость представления национальных алфавитов, вводилась альтернативная таблица символов, например KOI-7 для русского языка. Переключение в потоке ввода-вывода на альтернативную таблицу символов производилось символом с кодом 0x18 (код называется: Device Control 2) в потоке, а возврат к основную таблицу ASCII — символом с кодом 0x17 (Device Control 1).

Позже, с середины 80-х годов, с времени широкого распространения IBM PC и замены ними компьютеров других семейств, стандарт ASCII был расширен на 8-й бит байта char, байт мог представлять 256 символов: младшие 127 представляли исходную таблицу ASCII (с латинским шрифтом), а старшие — национальный алфавит. Но, поскольку национальные алфавиты могут быть самыми разнообразными, то для поддержки каждого из них потребовалось ввести свою кодовую страницу, например, для русского языка это могут быть страницы CP-866 (в MS-DOS), CP-1251 (в Windows), KOI-8r (в UNIX, Linux) — и каждая из этих страниц предлагает свой, отличающийся от других, порядок символов русского языка. При этом, для корректного отображения (или декодирования) любой локализованной символьной строки нужно обязательно знать кодовую страницу в которой она представлена.

Для того, чтобы положить конец этому вавилонскому столпотворению языковых кодовых страниц, был предложен (1991г.) стандарт представления UNICODE, в системе кодирования которого каждый символ кодируется 32-бит значением (4 байта, но не все 32-бит значения допустимы). Применение данного стандарта позволяет закодировать огромное количество символов разных систем письменности. Документы, закодированные по стандарту UNICODE, могут содержать в едином тексте японские и китайские иероглифы, буквы латиницы, кириллицы, греческого алфавита (α, ε, θ, π, σ, λ, φ, Ω…), математические символы, символы музыкальной нотной нотации, символы вымерших, редких, экзотических народностей. При этом нет необходимости в переключении кодовых страниц. Например, вот как выглядят некоторые символы языка, обозначенного как “сингальский”:

Первый UNICODE стандарт был выпущен в 91-м году. Последний на данный момент — в 2017 и он описывает 136755 разнообразных символов.

Но UNICODE — это ещё только стандарт представления каждого символа. Для представления этого символа в конкретной операционной системе (или языке программирования) нужна ещё система кодирования символов UNICODE.

  • Достаточно широко используются системы кодирования:
    UTF-32 — для представления каждого символа используются 4 байта, непосредственное численное значение кода UNICODE
  • UTF-32 — для представления наиболее часто используемых символов используются 2 байта (первые 65536 позиций), а остальные представляются в виде в виде «суррогатных пар». Такое кодирование используется в операционных системах Windows начиная с Windows NT.
  • UTF-32 — для представления каждого символа используются последовательность байт переменной длины: от 1 байта для символов основной таблицы ASCII, до 6 байт для редко используемых символов (символы русского алфавита кодируются 2-мя байтами). Эта кодировка создавалась позже других для операционных систем Plan 9 и Inferno в 1992г. Кеном Томпсоном и Робертом Пайком с коллегами, и вошла как единая и основная кодировка символьных строк в более поздних языках программирования Python и Go. Такое кодирование используется, на сегодня повсеместно, в POSIX/UNIX операционных системах, Linux.

Возвращаясь к тому, что C/C++ старое семейство языков программирования, для представления в них локализованных символов потребовалось ввести новый тип данных — широкие символы wchar_t вместо char (тип данных появился в стандарте C89, но, в полной мере с API поддержки, только в стандарте C99). Вместо строчных функций библиотеки C вида str*() для широких предлагаются их полные аналоги, но в виде wcs*() (вместо префикса str записываем префикс wcs). В разных системах wchar_t может иметь разную разрядность (в Linux это int32_t, в Windows int16_t) но для программиста это не имеет значения и не создаёт различий.

Для работы и преобразования многобайтовых последовательностей записанных в кодировке UTF-8 в C/C++ вводится семейство функций вида mb*(): mbtowc(), mblen(), mbstowcs(), wcstombs() и др. Это механизм взаимных преобразований между массивами char[] (в которых также выражаются строки UTF-8) и wchar_t[]. Если вы не сталкиваетесь с кодировкой UTF-8 (что с большой вероятностью имеет место в Windows), то эта группа функций вас не должна занимать.

Аналогично, вместо контейнерного класса C++ string вводится аналогичный контейнерный класс широких символов wstring.

Конкретно о технике работы с широкими локализованными строками мы поговорим в следующей статье. А пока 1-й элементарный пример … без комментариев — как повод для размышления (обратите внимание и объясните, что вызов strlen() в каждом случае даёт число байт в строке явно не соответствующее визуально видимое число букв в ней):

P.S. С большой детальностью про локализацию в C/C++ и работе с локализованными строками, кто интересуется с большей подробностью, могут почитать здесь: Языковая локализация C/C++ Языковая локализация C/C++ — там объяснений более 22 страниц формата офисного документа.

Рассылка новых уроков по программированию:

sqrt() — функция библиотеки cmath




sqrt( value );

Функция sqrt() библиотеки cmath (math.h) принимает параметр value и возвращает его квадратный корень.

Если параметр ( в нашем случае – value) отрицательный, возникает ошибка.

Результат выполнения показан в онлайн компиляторе ideone

пример работы функции sqrt c++

Рассылка новых уроков по программированию:

Online компиляторы




Часто возникает необходимость быстро показать кому-либо, как решить небольшую задачу по программированию или как реализовать алгоритм. Можно просто скинуть в ответ кусок кода, но лучше воспользоваться одним из online-компиляторов. Во многих из них есть возможность получить специальную ссылку на скомпилированный код. Такую ссылку можно например оставлять в комментариях к статьям. Пройдя по ней люди увидят не только сам код, но и результат работы программы.

Рассмотрим несколько вариантов online-компиляторов поддерживающих язык программирования C++

1. Online компилятор для С++ на сайте primat.org . Добавляем код, жмем RUN и ждем выполнения.

online-компилятор на primat.org

Если программа по ходу работы требует действий пользователя – выполняем их:

online-компилятор - действия пользователя

Если возникнут ошибки они отобразятся во вкладке compilation, которая откроется автоматически. Во вкладе options можно выбирать разнообразные параметры для компиляции, если вас не устраивают заданные по умолчанию.

Чтобы получить ссылку на этот код – жмем

online-компилятор - действия пользователя

Так же на этом сайте есть компилятор для Паскаль.

2. ideone online-компилятор

ideone online-компилятор

Сразу при входе обратите внимание на тот язык программирования, который выбран по умолчанию. Смените его при необходимости. Входящие данные внесите в stdin:

ideone online-компилятор

ideone online-компилятор

Тут очень большой выбор языков для компиляции:

языки программирования на ideone

3. Online-компилятор Wandbox

Wandbox online-компилятор

Входящие данные надо прописывать в Stdin до того, как нажмете Run.

Wandbox online-компилятор

Мне понравилось, что он хранит историю компиляций. Кроме С++ здесь есть широкий выбор языков программирования для компиляции:

языки программирования на Wandbox

4. C/C++ Online Compiler

online-компилятор Compiler

online-компилятор Compiler

В последнем как-то заморочено со ссылкой у них. Плюс не понятно где смотреть результат выполнения программы. Просто показывает, что программа вернула значение 0.

Смотрите также как установить Microsoft Visual Studio 2015 Express

Рассылка новых уроков по программированию:

pow() — функция библиотеки cmath




pow(a, b);

Функция pow() библиотеки cmath принимает два параметра: a, b. Первое число a (базовое) возводится в степень b.

Возвращает значение ab .

Результат выполнения 23 , 53, 52 :

pow () - функция библиотеки cmath

 

Рассылка новых уроков по программированию:

fma () – функция библиотеки cmath




fma(a, b, c);

Функция fma() библиотеки cmath принимает три параметра: a, b – значения для умножения, c – значение для добавления.

Возвращает значение a * b + c.

Результат выполнения ( 2 * 2 + 3):

fma () - функция библиотеки cmath

Рассылка новых уроков по программированию:

Установка Microsoft Visual Studio 2015 Express (IDE).




Среда разработки Microsoft Visual Studio – это такая специальная программа в которой мы будем писать команды компьютеру, а она эти команды будет переводить (при помощи так называемого компилятора) в машинный язык (из единиц и нулей), обрабатывать и выдавать нам некий результат работы нашего программного кода. Чтобы приступить к установке Microsoft Visual Studio Express вам надо пройти по этой ссылке. Прокрутите страницу и найдите там блок с Express for Desktop – это то что нам нужно.установка Microsoft Visual Studio Express

Примечание: Сейчас Microsoft рекомендует устанавливать Visual Studio Community. Если хотите установите его с той же страницы.

Единственное, перед тем как нажать кнопку Загрузка, просмотрите пункты System Requirements (системные требования к вашему компьютеру). Если они не отвечают вашим, к примеру у вас более старая версия Windows, то найдите в Google Microsoft Visual Studio 2010 Express или Microsoft Visual Studio 2013 Express и выберите ту версию, которая сможет нормально работать на вашем компьютере. Ну а если все требования выполняются – жмите Загрузка.

как установить Microsoft Visual Studio 2015 ExpressНемного ждем, пока закачается файл wdexpss_full_RUS.exe Вы можете найти его в Загрузках на вашем компьютере. Кликаем на него два раза и нажимаем кнопку Запустить:

как установить Microsoft Visual Studio 2015 Express
Установка Microsoft Visual Studio 2015 Express – рис.2

Если так случилось, что вы не являетесь счастливым обладателем Internet Explorer 10, вы увидите такое предупреждение:

как установить Microsoft Visual Studio 2015 Express
Установка Microsoft Visual Studio 2015 Express – рис.3

Смело нажимайте Продолжить. Далее вам предстоит выбрать на какой диск будет произведена установка (можете оставить то, что предлагают по умолчанию). Нажимайте Установить.

как установить Microsoft Visual Studio 2015 Expressм
Установка Microsoft Visual Studio 2015 Express – рис.4

Тут уже придется подождать кому сколько отмерено. Для тех у кого SSD – минут 15, а для жесткого диска берем минут 30 – 40. Так что у вас появилось немного свободного времени. Можете отдохнуть.

как установить Microsoft Visual Studio 2015 Express
Установка Microsoft Visual Studio 2015 Express – рис.5

После того, как всё будет принято и применено мы увидим сообщение:

как установить Microsoft Visual Studio 2015 Express
Установка Microsoft Visual Studio 2015 Express – рис.6

Значит всё установилось без проблем и можно сразу запускать программу. Вам предложат войти в Учетную запись Майкрософт. Если у вас ее нет – нажмите Регистрация. Лучше зарегистрироваться сразу, так как если этого не сделать, то через 30 дней MVS 2015 Express перестанет работать, пока вы не создадите эту учетную запись.

Установка Microsoft Visual Studio 2013 Express
Установка Microsoft Visual Studio 2015 Express – рис.7

После входа или регистрации мы наконец-то увидим открывшуюся среду разработки. Чтобы убедиться, что она нормально работает (а по-другому и быть не может), покажу вам как создать новый проект, внести в него код и запустить. В открывшейся MVS нажимаем Создать проект

как установить Microsoft Visual Studio 2015 Express
Установка Microsoft Visual Studio 2015 Express – рис.8

В этом окне нажмите на Visual C++, Win32, Консольное приложение Win32, введите любое имя для вашего нового проекта и снимите галочку с Создать каталог для решения. Жмем ОК.

Установка Microsoft Visual Studio 2013 Express
Установка Microsoft Visual Studio 2015 Express – рис.9

Откроется Мастер приложений. В нем нажмите Далее

Установка Microsoft Visual Studio 2013 Express
Установка Microsoft Visual Studio 2015 Express – рис.10

отметьте Консольное приложение и Пустой проект. Далее можно нажимать Готово.

Установка Microsoft Visual Studio 2013 Express
Установка Microsoft Visual Studio 2015 Express – рис.11

Проект создан. Теперь в нем нам надо создать файл с расширением .cpp. В него мы будем писать код программы. Делается это так: в окошке Обозреватель решений нажмите правой кнопкой мыши на имя вашего проекта (у меня это ConsoleApplication2)

Установка Microsoft Visual Studio 2013 Express
Установка Microsoft Visual Studio 2015 Express – рис.12

Выберите Добавить и Класс:

создание проекта и файлов cpp в microsoft visual studio

Откройте вкладку Visual C++ и выберите C++, а затем в списке шаблонов в центральной области выберите Класс C++. Нажмите Добавить.

создание проекта и файлов cpp в microsoft visual studio

В поле мастере универсальных классов C++ введите в поле Имя класса mycode. Не изменяйте имена файлов и параметры по умолчанию. Нажмите кнопку Готово.

создание проекта и файлов cpp в microsoft visual studio

Все – теперь в вашем проекте создан файл, в который можно писать команды на языке С++.

создание проекта и файлов cpp в microsoft visual studio

Еще, для удобства работы, я вам сразу предлагаю включить нумерацию строк кода. Для этого нажмите Сервис – Параметры – Текстовый редактор – С/С++ и установите галочку Номера строк. ОК.

Установка Microsoft Visual Studio 2013 Express
Установка Microsoft Visual Studio 2015 Express – рис.15

Далее, не вдаваясь в подробности, просто скопируйте код ниже и вставьте в ваш файл с именем mycode.cpp. (все что в нем содержалось до этого можно удалить)

После вставки нажмите сочетание клавиш Ctrl + Shift + B – начнется компиляция программы. Вы должны увидеть в нижней строке окна Сборка: успешно: 1, с ошибками: 0 и т.д. После этого нажимаем Ctrl + F5 и видим в открывшемся окне сообщение: “Мы создали первый проект в MVS2015”.

как установить Microsoft Visual Studio 2015 Express
Установка Microsoft Visual Studio 2015 Express – рис.16

Надеюсь, у вас всё получилось. Если возникли какие-то вопросы задавайте их в комментариях к этой статье.

Существует также много online компиляторов которыми вы можете пользоваться для несложных задач по программированию.

Указатели на функции





указатель на функцию, с++, программирование для начинающих, c++

Уже было отмечено, что указатели могут указывать на самые разнообразные типы объектов в программе на языке C++. Точнее, на все и на любые виды объектов, являющиеся данными в программе.

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

Здесь с функцией area() всё ясно: она вычисляет площадь круга того радиуса, который предан ей, как параметр. Но позже мы объявляем переменную указатель на функцию:

В момент этого объявления указатель pfunc представляет собой ничего более, как некоторый адрес во внутреннем представлении компьютера (4 байта в 32-бит операционной системе, 8 байт в 64-бит операционной системе). Это в точности тот же внутренний вид, который имеет, скажем, указатель на целочисленную переменную int*. Но этот указатель имеет свой строго определённый тип: указатель на функцию, принимающую один параметр типа double, и возвращающую значение типа double. Но вот на какую конкретно функцию указывает указатель, в точке его определения — не важно: значение указателя не определено.

А вот следующим оператором присвоения мы привязываем указатель на функцию к конкретной функции area(). Абсолютно правильным было бы записать присвоение указателю адреса функции: pfunc = &area. Но компилятор C++ настолько умён, что и упоминание имени функции в операторе присвоения интерпретирует как её адрес. Таким образом запись pfunc = area также совершенно корректная. С этого момента мы можем использовать указатель pfunc для вызова функции на которую он указывает. Для этого мы записываем значение на которое указывает указатель *pfunc (операция * в таком контексте называется разыменованием указателя). Скобки вокруг разыменованного значения pfunc в записи (*pfunc)( r ) нужны из соображений приоритетов раскрытия операций в выражении. Выполнение этого примера:

указатель на функцию, с++, программирование для начинающих, c++

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

Предположим, для некоторого крупного проекта мы готовим последовательность тестов, выполняемых в процесс развития и роста самого тестируемого проекта (это так называемая технология разработки тестирования, и очень продуктивная). Число пошаговых тестов в такой ситуации будет постоянно нарастать по мере продвижения готовности базового проекта.

В этой ситуации мы можем поступить так (ex2.cc):

И вот что мы имеем на исполнении:

указатель на функцию, с++, программирование для начинающих, c++

В этом листинге tests[ ] – это массив указателей на функции без параметров и без возвращаемых значений. Красивое решение, не правда ли? Мы можем не задумываясь добавлять новые функции массива вызываемых тестов, и они все последовательно будут вызываться при выполнении.

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

Для иллюстрации всего сказанного создадим программу самого примитивного калькулятора, выполняющего арифметические действия над целочисленными операндами (ex3.cc):

Здесь собственно вычисление выполняет функция calculate(). Но она ничего не «знает» о выполняемых действиях и о арифметических операциях вообще: она применяет к 2-м первым своим параметрам одну из 6-ти функций, которую ей передали 3-м параметром для выполнения.

Кто не знает о typedef читайте тут.

В этом коде функция strtod() – стандартная функция библиотеки языка C (ANSI C, стандарта POSIX), которая извлекает десятичное число из строки, полученной со стандартного потока ввода. В контексте наших обсуждений это интересно тем, что:

  • программа на C++ может использовать всё множество библиотечных вызовов языка C;
  • программа C++ использует на этапе выполнения разделяемые библиотеки языка C (.so или .dll), и при отсутствии стандартной библиотеки C, программы на C++ становятся неработоспособными.

Но вернёмся к работе показанного калькулятора (его предельная упрощённость связана с тем, что мы не занимаемся проблемами ввода, его формата и не обрабатываем ошибки ввода пользователем – в реальных программах так делать нельзя):

указатель на функцию, с++, программирование для начинающих, c++

Наблюдательный читатель мог бы заметить, что функция calculate() при всём своём желании и не могла бы выполнить ни одно из требуемых арифметических действий, так как выполняющие эти действия функции sum(), dif(), mul() и div() описаны позже функции calculate() и не видимы в коде функции calculate().

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

Если вам что-то не понятно по материалу или по коду программ – задавайте вопросы в комментариях.

Предлагаем вам оценить этот урок и урок Указатели на объекты:

Рассылка новых уроков по программированию:

Преобразование типов




преобразование типов с++, для начинающих, для чайников, с нуля, основы программирования c++Преобразование типов в С++ достаточно древняя, или точнее классическая операция. Если вкратце и по-русски: Преобразование типа – это указание компьютеру считать некий набор байтов целым или вещественным. Или указателем на определенный класс.

Вообще, чтобы понять преобразование типов нужно учитывать механизм и структуру переменных. К примеру, переменных целого типа несколько: короткий INT, int, долго INT, не считая беззнаковые. И компьютер размещает для них разное количество ячеек памяти (байт): 1, 2 и 4 соответственно. Преобразование в рамках таких типов одного класса называется стандартным преобразованием. в:

Сделает следующее: возьмет два младших байта из переменной «а», и просто пересадит их в два байта переменной «b». Поскольку значение в а (единица) вполне себе помещается в эти два байта, программа даст правильный результат, а С++ не будет против такого преобразования.

Почему нужно учитывать размер переменной при преобразовании?

Что будет если поместить в переменную «а» число 123456789? Оно прекрасно уместится в 4 байта типа int, но в 2 байта типа короткий INT оно уже не попадает. Слишком большое. С , как и полагается, просто обрежет это длинное число, взяв из него только хвост, и поместит в переменную «b». Получим естественно ерунду. Причем с минусом, если вывести ее на экран. Преобразование из переменной, которая занимает большее количество байт в памяти не будет правильным. Если преобразовывать наоборот из short в long к примеру таких проблем не будет, поскольку байтов в переменной-получателе больше, и места для данных которые хранит short вполне хватает.

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

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

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

Если же нужно преобразовать из вещественного double (8 байт) в float (4 байта), то тут таких проблем, как с целыми не будет. Математический сопроцессор просто округлит вещественное до значения, умещающегося в 4 байта, что не приведет к неправильному значению:

Результатом все равно будет число 1.234568e+18, что означает 1.2-с хвостиком в 18-й степени. Другое дело, что в “a” уже будет округленное число до 6-го знака после запятой, а не 1.234567891234566e+18. В целом для неточных вычислений это не мешает, но рекомендуется в программе использовать вещественные одного типа, чтоб не происходило такого вот округления.

Помимо преобразования типа есть такое понятие как приведение типа.

Наглядность приведения типа можно показать таким примером:

Если преобразование – это решение С++ (а точнее компилятора), в какой тип приводить, то приведение использует тип, жестко указанный программистом. В данном примере программист говорит компилятору, что нужно преобразовывать именно в int, а не в short int. Ведь 25 помещается и в int и в short, что выберет компилятор программист может и не знать.

В быту такие преобразования типов вообще-то редкие. Да и не нужные. Идеология программирования в бытовых условиях намекает избегать таких выкрутасов, поскольку они могут оказаться граблями (как в примере выше при преобразовании целых), поэтому приведение типов в С++ не стоит использовать повсеместно.

:) Спасибо за эту статью её автору Stilet – супер модератору форума программистов ProgrammersForum.

Рассылка новых уроков по программированию:

Исключения в С++





исключения в с++, исключения c++, программирования для начинающих

Иногда, во время работы программ, встречаются ситуации которые препятствуют дальнейшей нормальной их работе. К примеру при делении числа на ноль, программа завершит работу не смотря на то, сколько пользователь работал в программе, и какой объем данных внес. Программа просто закроется. И представьте, если до этого пользователь вносил в программу данные несколько часов и проводил расчеты. При таком аварийном закрытии программы все эти данные и расчеты пропадут. Согласитесь – не очень приятно. Также может встретиться такая ситуация, когда программа пытается открыть недоступный в этот момент файл, или запросить больше, чем доступно памяти.

Такого рода ситуации программистам надо стараться предвидеть и строить программы так, чтобы они могли гибко реагировать, а не аварийно закрываться. В моей любимой книге Язык программирования C++. Лекции и упражнения автора С. Прата, дано следующее определение исключениям в С++:

исключения в с++, исключения c++, программирования для начинающих

Чтобы вам не сложно было понять механизм работы исключений в С++, рассмотрим их на простом примере. В нем мы предвидим тот случай, что в какой-то момент в ходе расчетов программы, может встретиться деление числа на 0. Наберите и скомпилируйте код, расположенный ниже. Чтобы убедиться в том, как реагирует программа на такую ситуацию, внесите число 0 в переменную num2 (она выступает делителем в примере).

Так как переменная var равна 3, цикл while, в нормальной ситуации, должен отработать три раза. С каждым шагом цикла var уменьшается на единицу с помощью декремента. Но так как мы сразу внесли значение 0 в переменную num2, программа не пройдет до конца даже первый шаг цикла. Она прервется.

В следующем листинге, мы исправим это упущение – добавим несколько компонентов, которые помогут среагировать на данную ситуацию без прерывания работы программы. А именно:

  • блок try или try-блок (попытка, проба);
  • генератор исключения – блок throw (обработать, запустить);
  • обработчик исключения, который его перехватывает -команда catch (поймать, ловить)

Как работает исключение? – Программист прописывает в коде (в try-блоке) конкретное условие, что если переменная num2 станет равна 0, то в таком случае необходимо генерировать исключение в throw. Далее, то что сгенерировал throw, перехватывает catch-блок (в виде параметра функции) и программа выполнит тот код, который прописан в этом блоке.

Пример:

Разберем подробно. В строках 21-29 находится блок try. В нем необходимо размещать тот код, который может привести к необратимым ошибкам. Еще до арифметического выражения деления задаем условие: если num2 будет равно 0, то пусть throw генерирует число 999 (к примеру). В том случае, сразу после генерации числа, дальнейшие команды в блоке try выполняться уже не будут, а само число “упадет” в блок catch (в виде параметра). Далее выполнится то, что указано в блоке catch – в нашем случае, это будет сообщение об ошибке:

cout << "Ошибка №" << thr << " - деление на 0!!!" << endl;

и программа будет выполнять последующие команды. В том случае, если число num2 != 0, то throw ничего не генерирует и catch-блок не сработает.

Посмотрите теперь, как отреагирует программа, если вы введете num2 равное нулю. Запускайте программу.

исключения в с++, исключения c++, программирования для начинающих

Как видим, там где могла произойти ошибка и досрочное завершение программы, мы увидели сообщение Ошибка №999 – деление на 0!!! Программа “перескочила” через операцию деления на 0 и выполнила catch-блок.

Чтобы вы лучше поняли, как значение генерируемое throw перехватывает catch-блок, замените код в строках 21 – 33 на этот:

В этом примере, если num2 равно 0, throw генерирует строку, а не число. Строка “падает” в catch-блок и выводится на экран.

Рассмотрим еще такой пример, когда исключение генерируется в функции, которая делит одно число на другое:

Чтобы исключение сработало правильно, эту функцию надо вызвать в блоке try:

catch перехватит число 99, а деление на 0 не состоится.

Основное, что нужно запомнить об исключениях в С++:

  • В try-блоке (блоке повторных попыток) необходимо размещать код, который потенциально может привести к аварийному закрытию программы;
  • Исключение генерируется в блоке throw. Если throw сработает программа автоматически приступит к выполнению команд catch-блока, игнорируя оставшийся код в try-блоке;
  • Улавливающий блок – catch-блок, перехватывает то, что генерирует блок throw. Он обязательно должен находиться под try-блоком. Ничего не должно быть прописано между ними;
  • catch-блок не сработает, если исключение не было сгенерировано. Программа его просто проигнорирует.

Чтобы поддержать наш сайт – нажмите на копилку. Вам будет предложено отправить SMS. Сумма – на ваш выбор.

Рассылка новых уроков по программированию:

Отладчик Microsoft Visual Studio




отладчик Microsoft Visual Studio, умная точка останова

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

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

Иногда, чтобы найти ошибку и посмотреть, что к ней приводит, надо пройти какой-то участок кода по шагам, по которым программа проходит в момент выполнения. Так же интересно увидеть, как при этом меняются данные программы (значения переменных): какие значения они принимают в определённые моменты времени. В Microsoft Visual Studio для такой работы, к счастью, есть отладчик. В этой статье будут рассмотрены основы работы с отладчиком.

Допустим, надо проанализировать и отладить следующий код:

Наберите его в Visual Studio. В этом коде нет синтаксических ошибок, которые не пропустил бы компилятор до начала выполнения программы. Программа начнет выполняться, проделает определенный участок работы и возникнет ошибка:

отладчик Microsoft Visual Studio, умная точка остановаНачнем отладку и посмотрим, в следствии чего произошла ошибка на этапе выполнения. Для этого, находясь в Visual Studio, надо нажать клавишу F10. Программа начнет выполнятся и остановится на первой выполняемой строке. Вы увидите жёлтую стрелку возле той строки программы, которая выполняется в данный момент:

отладчик Microsoft Visual Studio, умная точка останова

Чтобы перейти к выполнению следующего шага, надо снова нажать на F10. Желтая стрелка переместится на другую строку:

отладчик Microsoft Visual Studio, умная точка останова

Теперь посмотрите вниз экрана в Visual Studio – там есть вкладка в которой можно отслеживать, как изменяются данные переменных в реальном времени.

отладчик Microsoft Visual Studio, умная точка останова

Тут переменная только создается и хранит какой-то мусор. При следующем нажатии на F10 стрелка переместится в строку 8. Во вкладке уже будет видно, что объявлена переменная i, а также какое значение приобрела переменная var55.

отладчик Microsoft Visual Studio, умная точка останова

Нажимайте на F10 и смотрите, как изменяются данные. Когда вы будете проходить отладчиком по циклу четвертый раз, переменная i примет значение 0. Это и приводит к ошибке выполнения программы так как на 0 делить нельзя.

отладчик Microsoft Visual Studio, умная точка останова

отладчик Microsoft Visual Studio, умная точка останова

Для выхода из режима отладки – нажмите Shift+F5. Если код большой и вам надо отладить его с какой-то определенной строки, а не с самого начала – просто установите курсор в нужную строку и нажмите Сtrl+F10.

Точка останова (breakpoint) и Умная точка останова

На сайте msdn есть такое определение точки останова:

отладчик Microsoft Visual Studio, умная точка останова

Если надо выполнить программу до определённого места в коде и только достигнув его, запустить отладчик – используют точку останова.

Чтобы установить точку останова в строку cout << var55 / i << endl; , поставьте курсор перед ней и нажмите F9. После этого можно будет увидеть возле этой строки красную точку – это она и есть.

отладчик Microsoft Visual Studio, умная точка останова

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

отладчик Microsoft Visual Studio, умная точка останова

В консоли будет отображаться то, что успело выполниться до 12-й строки.

отладчик Microsoft Visual Studio, умная точка остановаДальше можно отлаживать программу, как и раньше – нажимая F10 и наблюдая за переменными. Всё что выполняется в программе, будет отображаться в консоли. Чтобы снять точку останова – надо поставить курсор в строку где она находится и нажать F9

Если, к примеру, итераций не 3, как в нашем коде, а 333 и мы видим, что ошибка появляется на последних итерациях, правда не очень хочется проходить все эти шаги цикла отладчиком? Есть возможность пропустить, скажем, 330 итераций, и проанализировать только последние 3. Для этого воспользуемся умной точкой останова. Сначала скопируйте этот код:

Теперь установите обычную точку останова (F9) и щелкните по ней правой кнопкой мыши. Откроется выпадающее меню с дополнительными возможностями для неё.

умная точка останова

Чтобы выполнить программу до 330-й итерации и перейти в режим отладки, выберите Число попаданий.

умная точка остановаТеперь выбираем “если число попаданий равно”, пишем 330 и жмем ОК. На точке останова появится белый +. Это означает, что она обладает дополнительными условиями. Нажимаем F5, для запуска программы. Она приостановится и перейдет в режим отладки на 330 итерации (на 330-м попадании в точку останова). Далее уже нажимая F10 проходим по циклу до последней итерации.
Это основные, но далеко не все возможности отладчика Microsoft Visual Studio. Со временем рассмотрим и другие.

Подписывайтесь на рассылку новых уроков от сайта – не пропускайте обновления информации об основах программирования на C++. Поддерживайте наш сайт – ставьте like и делитесь ссылками на наши уроки в социальных сетях. Кнопки можно найти под каждой статьей.

Рассылка новых уроков по программированию: