§2 Процесс создания программы. Компиляция. GCC. Интегрированные среды разработки. Потоки. Поток вывода

Компиляция

Компиляция — это сборка программы, включающая трансляцию всех модулей программы, написанных на одном или нескольких исходных языках программирования в эквивалентные программные модули на машинном (двоичном) языке (коде) и последующие действия по сборке исполняемой машинной программы. Программное обеспечение выполняющее эти многоступенчатые операции (см. ниже) называется компилятором.
Первый компилятор был создан Грейс Хоппер (1906 — 1992) — американской учёной и коммодором флота США. (Ей также приписывается популяризация термина debugging для устранения сбоев в работе компьютера.)

Grace Hopper, Amazing Grace (“Удивительная Грейс”)

В нашем курсе будет использоваться компилятор GCC. GNU Compiler Collection (GCC) — это набор компиляторов для различных языков программирования, разработанный в рамках проекта GNU. GCC является свободным программным обеспечением, который распространяется фондом свободного программного обеспечения (FSF) на условиях GNU GPL. Он используется как стандартный компилятор для свободных UNIX-подобных операционных систем. В настоящее время GNU Compiler Collection (текущая версия 8.х) расширен для компиляции исходных кодов на таких языках программирования, как С, C++, Objective-C, Java, Фортран и Ada.
В дистрибутивах Linux компилятор GCC для C++ доступен в репозитории пакетов. Сборку GCC для Windows можно получить на сайте mingw-w64 (GCC for Windows 64 & 32 bits). Подробнее об установке mingw-w64 в Windows можно прочитать в методичке. Кроме того, можно установить версию IDE Code::Blocks, которая поставляется вместе с MinGW (актуальную версию GCC нужно устанавливать вручную).

Примечание. Обратите внимание, что последние стандарты (С++17 и С++20) имеют в GCC экспериментальную поддержку. Получить более детальные сведения о поддержке стандартов C++ в GCC можно на этих сайтах: C++ Standards Support in GCC и C++ compiler support

Процесс создания программы

Верстка исходного кода

Создание программы начинается с записи (верстки) программного кода (исходного кода, исходника) на выбранном языке программирования. Для написания исходного кода программы можно использовать обычные plain-text редакторы. Современные редакторы имеют возможность подсветки синтаксиса и дополнительные расширения, которые превращают их в компактные IDE. Примером таких редакторов могут служить Geany, KWrite, Gedit, Notepad++). Однако лучшим решением будет использование полноценных интегрированных среды разработкиIDE (Integrated Development Environment) о которых речь пойдет ниже, в частности, IDE Code::Blocks.
Для создания первой консольной программы мы будем использовать редактор Kwrite, являющимся компонентом графического окружения KDE, который умеет “подсвечивать” синтаксис C++. Созданный в этой программе файл исходного кода должен иметь расширение .cpp.

Препроцессор

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

Компиляция

Используемый компилятор (GCC) транслирует исходный код программы в объектный, машинно-ориентированный, код. Созданный в результате компиляции исполняемый модуль привязан как к данной платформе, так и к типу процессора. (Таким образом, программа, созданная в ОС Linux не будет работать в Windows, не смотря на то, что она создана компилятором GCC аналогичной версии). Компиляция завершится успешно, если в программе не будут обнаружены синтаксические ошибки, в противном случае, компилятор выдаст сообщение о найденных ошибках и остановит свою работу.

Компоновка

Компоновщик (он же линкер) завершает сборку программы объединяя (связывая) объектный код программы с объектным кодом библиотек в финальный продукт – исполняемый код.
4

Тестирование и отладка программы

На этом этапе готовая программа подвергается всестороннему анализу на предмет обнаружения неверных результатов – алгоритмических ошибок. Для этих целей в IDE применяется специальный программный модуль – отладчик. В связке с GCC используется GNU Debugger — переносимый отладчик проекта GNU (GDB)

Структура программы

Пустая программа

В С++ main() называется главной функцией программы. В ней осуществляется реализация основного алгоритма программы: вызовы функций, обращения к объектам библиотечных и пользовательских классов, инициализация, ввод и вывод данных, взаимодействие с операционной системой.
Программа 2.1

int main() {
	// Это однострочный комментарий
	/* Это 
	многострочный 
	комментарий    */
}

В примере выше в теле главной функции (между фигурными скобками, { }) – пусто: программа будет выполнена, но видимых результатов в окне консоли мы не увидим, поскольку в теле программы только два вида комментариев: “//” – однострочный и “/* */” – многострочный. Комментарии (закомментированные строки) не участвуют в работе программы, они игнорируются препроцессором при сборке программы. Но комментарии в программе всё-таки нужны! Они позволяют разработчикам программ оформлять исходник, обмениваться информацией о назначении тех или иных программных объектов, объяснять идею реализации алгоритма, собственных структур данных, создавать документацию.
Спецификатор типа данных int (целое число) перед именем главной функции (main) означает, что эта функция возвращает числовые коды ошибок (или 0, если таковые отсутствуют). Согласно стандарту языка C++, требуется обязательно указывать тип int перед main.

Вывод строки “Здравствуй, мир!”

В редакторе KWrite (или, если вы используете GNOME, – GEdit) напишем код программы 2.2. Эта программа печатает на экране символьную строку “Здравствуй, мир!”. (Первая программа которую обучающийся пишет сам на изучаемом языке).
Программа 2.2

#include <iostream>
using namespace std;

int main() {
	cout << "Здравствуй, мир!" << endl;
	return 0;
}

Для вывода строки нам потребуется включить (с помощью директивы #include) библиотечный класс iostream, содержащий функции ввода/вывода. Исторически так сложилось, что библиотечный класс ввода/вывода автоматически не включается в программу. Для вывода символьной строки необходимо использовать объект потока cout и операцию вставки “<<" (два символа "меньше", следующих друг за другом, без пробела). Символьная строка должна быть заключена в двойные кавычки. Завершает вывод данных манипулятор endl (end line - конец строки). Заканчивается программа инструкцией return (возврат значения). Инструкция return является необязательной (поскольку программа, в случае её отсутствия, будет возвращать значения операционной системе не явно). Но мы возьмем за хороший навык всегда использовать эту инструкцию в конце программы. Возвращаемое значение - 0. Обратите внимание, что любая инструкция (предложение языка) в C++ должно заканчиваться точкой с запятой.
Объявление

using namespace std;

говорит о том, что мы будем использовать пространство имен стандартной библиотеки (STD). Это позволит сделать код более лаконичным. В противном случае строка 11 выглядела бы следующим образом:

std::cout << "Здравствуй, мир!" << std::endl;

Создание консольного приложения

Сохраним этот файл с именем mypro1.cpp в директории ~/workspace/my_pro_1/
5
Для компиляции и линковки приложения необходимо ввести следующую команду в окне терминала Konsole:

g++ -o mypro1 mypro1.cpp

Данная команда состоит из следующих элементов: g++ - вызов программы-компилятора (GCC) с флагом -o. Далее вводится имя бинарного файла и имя компилируемого "исходника".
6
В результате выполнения этой команды в директории ~/workspace/my_pro_1/ появится исполняемый бинарный файл с именем mypro1. В окне терминала запустим эту программу обращаясь по имени файла: ./mypro1. Результат работы программы появится здесь же, в окне терминала - это символьная строка "!!!Hello World!!!".
В компиляторе GCC, по умолчанию, не включена поддержка стандарта C++11. Для включения поддержки этого стандарта в команду g++ необходимо добавить следующий флаг: -std=c++11. (Отметим, что программы нашего курса требуют включения поддержки стандарта не ниже C++11).
Флаги стандартов:

  • -std=c++11 или -std=c++0x
  • -std=c++14 или -std=c++1y
  • -std=c++17 или -std=c++1z
  • -std=c++2a

Интегрированные среды разработки (IDE)

Мы не будем использовать при создании программ текстовые редакторы, поскольку они не предлагают разработчикам никакого инструментария для быстрой верстки приложений. Для эти целей мы будем использовать интегрированную среду разработки (IDE). IDE включают в себя редакторы кода, средства работы с компилятором и отладчиком, интеграцию с системами управления версиями, конструкторы GUI. IDE существенно облегчают и ускоряют верстку программного кода, так как встроенные редакторы обладают возможностью подсветки синтаксиса, автодополнения, навигации и рефакторинга. Существует большое семейство IDE для программирования на C/C++ как проприетарных, так и free software. Крупнейшие производители коммерческого ПО предлагают некоторые свои продукты, такие как IDE и компиляторы, совершенно свободно, но с весьма усеченным комплектованием.
Однако, в настоящее время, разработчики обеспечены значительным количеством свободных IDE, которые имеют довольно мощные интерфейсы, ничем не уступающие интерфейсам коммерческих аналогов. Динамично развивающиеся проекты доступны на гораздо большем числе платформ, что позволяет свободно писать кроссплатформенные приложения. Ими поддерживается большой спектр компиляторов, включая коммерческие. Среди крупнейших, из свободных IDE, можно отметить следующие:

  • Eclipse IDE for C/C++ Developers (Допускается к использованию на Всероссийской олимпиаде по информатике)
  • Code::Blocks (Допускается к использованию на Всероссийской олимпиаде по информатике, является базовым в нашем курсе)
  • QtCreator (это среда будет базовой в нашем курсе при знакомстве с технологией RAD)
  • CodeLite
IDE Code::Blocks

code-blocks
Code::Blocks написана на С++ и использует библиотеку wxWidgets. Имея открытую архитектуру, может масштабироваться за счёт подключаемых модулей. Поддерживает языки программирования С, С++, D, Fortran. Code::Blocks разрабатывается для Windows, Linux и Mac OS X. Данная IDE является базовой в нашем курсе и должна быть установлена совместно с компилятором GCC. (Как это сделать см. в методичке Установка и создание первого приложения в IDE Code::Blocks).

Потоки. Поток вывода

В программе 2.2 мы впервые столкнулись с понятием потока. Что же такое поток? Поток (stream) — это абстракция, отражающая перемещение данных от источника к приемнику. В большинстве программ требуется получать данные из-вне (например, с клавиатуы), а также отправлять результаты вычислений на стандартное устройство (монитор).
2
Такое движение данных называется стандартным потоком ввода/вывода. Разумеется, среда C++ реализует потоки не сама по себе, а в непосредственном взаимодействии с операционной системой. Реализация потоков в языке C++ выполнена таким образом, что потоки для различных источников и приемников выглядят единообразно. Синтаксически вывод на языке C++ действительно напоминает поток. Инструкция потока вывода начинается соответствующим объявлением cout (читается "си-аут"). cout является объектом класса библиотеки C++ отвечающей за ввод и вывод - iostream. Данные отправляют (или добавляются) в поток с помощью операции вставки (вывода) <<. Например:

cout << "Ничего я не боюсь, если рядом C++!\n";
cout << "5 + 10 = " << 15 << endl;

Такая строка может быть очень длинной, поэтому, для читабельности кода, эту строку можно (и даже нужно!) оформлять в виде столбца:

cout << "2 x 1 = " << 2 << "\n"
     << "2 x 2 = " << 4 << "\n"
     << "2 x 3 = " << 6 << "\n"
     << "2 x 4 = " << 8 << "\n"
     << "2 x 5 = " << 10 << "\n"
     << "2 x 6 = " << 12 << "\n"
     << "2 x 7 = " << 14 << "\n"
     << "2 x 8 = " << 16 << "\n"
     << "2 x 9 = " << 18 << "\n"
     << "2 x 10 = " << 20 << endl;

Как мы уже сказали ранее, поток завершается манипулятором endl. (Манипуляторы - это инструкции форматирования, которые вставляются непосредственно в поток). Этот манипулятор вставляет завершающий ("нулевой") символ, являющийся признаком конца строки и освобождает буфер вывода. На самом деле, данные не выводятся сразу же на устройство, а накапливаются в специальной области памяти, называемой буфером. Буфер не является чем-то недоступным в программе и в процессе работы, с помощью специальных функций, мы можем получать доступ к элементам буфера непосредственно.

Примечание. Хотя endl и производит переход на новую строку, внутри потока использовать его не следует (но возможно). Для того, чтобы осуществить переход на новую строку используется специальная управляющая последовательность "\n" (как во фрагменте программы выше).

Форматированный вывод

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

*
**
***
** **
**  **
**   **
**    **
**     **
**      **
**       **
**        **
*************
**************

Программа 2.3

//=====================================================================
// Description : Форматированный вывод с помощью манипулятора setw
//======================================================================

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	cout << "*\n"
	     << "**\n"
	     << "***\n"
	     << "**" << setw(3) << "**\n"
	     << "**" << setw(4) << "**\n"
	     << "**" << setw(5) << "**\n"
	     << "**" << setw(6) << "**\n"
	     << "**" << setw(7) << "**\n"
	     << "**" << setw(8) << "**\n"
	     << "**" << setw(9) << "**\n"
	     << "*************\n"
	     << "**************"
	     << endl;
}

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

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

Практические задания

1. Составить программу, которая выводит в консольном окне ваше имя, образованное символом "*". Символ можно выводить следующим образом:
cout << ... << '*' << ... << endl; (многоточие означает, что часть кода пропущена)
2. Выведите следующие рисунки с помощью любых символов:

1.
*********************
******************
****************
**************
************
**************
****************
******************
*********************
2.
         *****
             *
            **
           ***
          ****
         *****
        ******
       *******
      ********
     *********
    **********
   ***********
*********************
 *******************
  ****************
3.
       *
      ***
    *** ***
   ***   ***
 ***       ***
***         ***
 ***       ***
   ***   ***
    *** ***
      ***
       *
4.
***********
 *********
  *******
   *****
    ***
     *
    ***
   *****
  *******
 *********
***********

Материалы к уроку

  • Презентация 0 (О C++) [PDF] [ODP]

Вопросы

  1. Опишите преимущества использования IDE по сравнению с обычным текстовым редактором и командной строкой
Домашняя работа

Используя методические рекомендации, установить на домашний компьютер компилятор GCC (MinGW) и IDE Code::Blocks (и/или IDE Eclipse). Написать, откомпилировать и запустить программу приветствия в IDE Code::Blocks.

Print Friendly, PDF & Email

Comments are closed.