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

Что ж, программная среда установлена, и редактор настроен. Теперь можно приступать к изучению языка C++. Как вы уже знаете, программа состоит из инструкций, расположенных в текстовом файле. Структура обычной программы выглядит так:

<Подключение заголовочных файлов>
<Объявление глобальных переменных>
<Объявление функций, классов и др.>
int main() {
   <Инструкции>
   return 0;
}
<Определения функций и классов>

В самом начале программы подключаются заголовочные файлы, в которых содержатся объявления идентификаторов без их реализации. Например, чтобы иметь возможность вывести данные в окно консоли, необходимо подключить файл iostream, в котором содержится объявление объекта cout. Подключение осуществляется с помощью директивы #include:

#include <iostream>

С помощью директивы #include можно подключать как стандартные заголовочные файлы, так и пользовательские файлы.

После подключения заголовочных файлов производится объявление глобальных переменных. Переменные предназначены для хранения значений определенного типа. Глобальные переменные видны во всей программе, включая функции. Если объявить переменную внутри функции, то область видимости переменной будет ограничена рамками функции и в других частях программы использовать переменную нельзя. Такие переменные называются локальными. Объявить целочисленную переменную можно так:

int x;

В этом примере мы объявили переменную с названием x и указали, что переменная может хранить данные, имеющие тип int. Ключевое слово int означает, что переменная предназначена для хранения целого числа.

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

warning: conversion from 'double' to 'int'

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

Если в команде компиляции не указан флаг -Wconversion, то предупреждающих сообщений о потери данных вообще не будет. Советую установить этот флаг в настройках проекта для режима Debug. Открываем свойства проекта (в меню Project выбираем пункт Properties) и из списка слева выбираем пункт C/C++ Build | Settings. На отобразившейся вкладке из списка Configuration выбираем пункт Debug, а затем на вкладке Tool Settings выбираем пункт GCC C++ Compiler | Warnings. Устанавливаем флажок –Wconversion. Проверяем также установку флажка –Wall. Сохраняем изменения.

Обратите внимание на то, что объявление переменной заканчивается точкой с запятой. Большинство инструкций в языке C++ должно заканчиваться точкой с запятой. Если точку с запятой не указать, то компилятор сообщит о синтаксической ошибке. Пример сообщения:

error: expected ';' before 'std'

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

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

int x = 10;

Если глобальной переменной не присвоено значение при объявлении, то она будет иметь значение 0. Если локальной переменной не присвоено значение, то переменная будет содержать произвольное значение. Как говорят в таком случае: переменная содержит «мусор».

Обратите внимание на то, что перед оператором = и после него вставлены пробелы. Количество пробелов может быть произвольным или пробелов может не быть вовсе. Кроме того, допускается вместо пробелов использовать символ перевода строки или символ табуляции. Например, эти инструкции вполне допустимы:

int x=21;
int y=                 85;
int z
=
56;

Тем не менее, следует придерживаться единообразия в коде и обрамлять операторы одним пробелом. Если присваивание производится в объявлении функции (задается значение параметра по умолчанию), то пробелы принято не указывать вовсе. Следует учитывать, что это не строгие правила, а лишь рекомендации по оформлению кода.

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

int x = 21; int y = 85; int z = 56;

Из этого правила есть исключения. Например, после директив препроцессора точка с запятой не указывается. В этом случае концом инструкции является конец строки. Директиву препроцессора можно узнать по символу # перед названием директивы. Типичным примером директивы препроцессора является директива #include, которая используется для включения заголовочных файлов:

#include <iostream>

После объявления глобальных переменных могут располагаться объявления функций и классов. Такие объявления называются прототипами. Схема прототипа функции выглядит следующим образом:

<Тип возвращаемого значения> <Название функции>(
                             [<Тип> [<Параметр 1>]
                      [, ..., <Тип> [<Параметр N>]]]);

Например, прототип функции, которая складывает два целых числа и возвращает их сумму выглядит так:

int sum(int x, int y);

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

int sum(int x, int y) {
   return x + y;
}

Как видно из примера, первая строка в определении функции sum() совпадает с объявлением функции. Следует заметить, что в объявлении функции можно не указывать названия параметров. Достаточно указать информацию о типе данных. Таким образом, объявление функции можно записать так:

int sum(int, int);

После объявления функции ставится точка с запятой. В определении функции внутри фигурных скобок должна быть описана реализация функции. Так как в объявлении указано, что функция возвращает целочисленное значение, следовательно, после описания реализации необходимо вернуть значение. Возвращаемое значение указывается после ключевого слова return. Если функция не возвращает никакого значения, то перед названием функции вместо типа данных указывается ключевое слово void. Пример объявления функции, которая не возвращает значения:

void print(int);

Пример определения функции print():

void print(int x) {
   std::cout << x << std::endl;
}

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

void print(int x)
{
   std::cout << x << std::endl;
}

Многие программисты считают такой стиль наиболее приемлемым, т. к. открывающая и закрывающая скобки расположены друг под другом. На мой же взгляд образуется лишняя пустая строка. Так как размеры экрана ограничены, при наличии пустой строки на экран помещается меньше кода и приходится чаще пользоваться полосой прокрутки. Если размещать инструкции с равным отступом, то блок кода выделяется визуально и следить за положением фигурных скобок просто излишне. Тем более, что редактор Eclipse позволяет подсветить парные скобки. Чтобы найти пару фигурных скобок следует поместить указатель ввода после скобки. В результате скобки будут подсвечены. Какой стиль использовать, зависит от личного предпочтения программиста или от правил оформления кода, принятых в определенной фирме. Главное, чтобы стиль оформления внутри одной программы был одинаковым.

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

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

;

Самой главной функцией в программе является функция main(). Именно функция с названием main() будет автоматически вызываться при запуске программы. Функция имеет три прототипа:

int main();
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char **penv);

Первый прототип функции имеет синоним:

int main(void);

Значение void внутри круглых скобок означает, что функция не принимает параметры. Подобный синтаксис используется в языке программирования C. В языке C++ указание ключевого слова void является излишним. Достаточно указать пустые скобки. Первым прототипом мы пользовались в листинге 2.1.

Второй прототип применяется для получения значений, указанных при запуске программы из командной строки (см. листинг 2.11). Параметры расположены внутри круглых скобок и разделены запятой. Параметр состоит из объявления типа данных и названия локальной переменной. Первый параметр (argc) имеет тип int, который соответствует целочисленному значению. Через этот параметр доступно количество значений, переданных в командной строке. Следует учитывать, что первым элементом массива argv является название исполняемого файла. Поэтому значение параметра argc не может быть меньше единицы. Через второй параметр (argv) доступны все значения в виде строки (тип char *). Квадратные скобки после названия второго параметра означают, что доступен массив строк. Более подробно передачу значений через командную строку мы рассмотрим далее в этой главе.

Параметр penv в третьем прототипе позволяет получить значения переменных окружения.

Перед названием функции указывается тип возвращаемого значения. Ключевое слово int означает, что функция возвращает целое число. Возвращаемое значение указывается после ключевого слова return в самом конце функции main(). Число 0 означает нормальное завершение программы. Если указано другое число, то это свидетельствует о некорректном завершении программы. Согласно стандарту, внутри функции main() ключевое слово return можно не указывать. В этом случае компилятор должен самостоятельно вставить инструкцию, возвращающую значение 0. Возвращаемое значение передается операционной системе и может использоваться для определения корректности завершения программы.

Вместо безликого значения 0 можно воспользоваться макроопределением EXIT_SUCCESS, а для индикации некорректного завершении программы — макроопределением EXIT_FAILURE. Предварительно необходимо включить заголовочный файл stdlib.h или cstdlib. Определения макросов:

#include <stdlib.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

Пример:

return EXIT_SUCCESS;

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

Листинг 2.3. Пример программы

// Подключение заголовочных файлов
#include <iostream>
#include <cstdlib>
// Объявление глобальных переменных
int x = 21;
int y = 85;
// Объявление функций, классов и др.
int sum(int, int);
void print(int);
// Главная функция (точка входа в программу)
int main() {
   int z;           // Объявление локальной переменной
   z = sum(x, y);   // Вызов функции sum()
   print(z);        // Вызов функции print()
   return EXIT_SUCCESS;
}
// Определения функций и классов
int sum(int x, int y) {
   return x + y;
}
void print(int x) {
   std::cout << x << std::endl;
}

Объявление функций можно вынести в отдельный заголовочный файл и включить его с помощью директивы #include. В разд. 2.4 мы создали заголовочный файл HelloWorld.hpp. Давайте им воспользуемся. Вначале добавим в программу инструкцию:

#include "HelloWorld.hpp"

после инструкции:

#include <cstdlib>

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

Удаляем эти инструкции из программы и сохраняем файл:

// Объявление функций, классов и др.
int sum(int, int);
void print(int);

Затем вставляем в файл HelloWorld.hpp код из листинга 2.4.

Листинг 2.4. Содержимое файла HelloWorld.hpp

#ifndef HELLOWORLD_HPP_
#define HELLOWORLD_HPP_

// Объявление функций, классов и др.
int sum(int, int);
void print(int);

#endif /* HELLOWORLD_HPP_ */

Директивы препроцессора #ifndef, #define и #endif препятствуют повторному включению заголовочного файла. Если этих директив не будет, то повторное объявление идентификаторов (например, глобальных переменных) вызовет ошибку при компиляции. Вместо этих директив можно указать в самом начале файла директиву препроцессора #pragma со значением once:

#pragma once

// Объявление функций, классов и др.
int sum(int, int);
void print(int);

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов