Учебники

Краткое руководство по C ++

Обзор C ++

C ++ — это статически типизированный, скомпилированный, универсальный, чувствительный к регистру, язык программирования свободной формы, который поддерживает процедурное, объектно-ориентированное и универсальное программирование.

C ++ рассматривается как язык среднего уровня , так как он включает в себя комбинацию как языковых, так и низкоуровневых функций.

C ++ был разработан Бьярном Страуструпом, начиная с 1979 года в Bell Labs в Мюррей-Хилл, штат Нью-Джерси, как усовершенствование языка C и первоначально назывался C with Classes, но позже он был переименован в C ++ в 1983 году.

C ++ является надмножеством C, и что практически любая легальная программа на C является легальной программой на C ++.

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

Объектно-ориентированное программирование

C ++ полностью поддерживает объектно-ориентированное программирование, включая четыре столпа объектно-ориентированной разработки —

  • Инкапсуляция
  • Скрытие данных
  • наследование
  • Полиморфизм

Стандартные библиотеки

Стандарт C ++ состоит из трех важных частей —

  • Основной язык, дающий все строительные блоки, включая переменные, типы данных и литералы и т. Д.

  • Стандартная библиотека C ++, предоставляющая богатый набор функций для работы с файлами, строками и т. Д.

  • Стандартная библиотека шаблонов (STL), предоставляющая богатый набор методов, управляющих структурами данных и т. Д.

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

Стандартная библиотека C ++, предоставляющая богатый набор функций для работы с файлами, строками и т. Д.

Стандартная библиотека шаблонов (STL), предоставляющая богатый набор методов, управляющих структурами данных и т. Д.

Стандарт ANSI

Стандарт ANSI является попыткой обеспечить переносимость C ++; тот код, который вы пишете для компилятора Microsoft, будет компилироваться без ошибок, используя компилятор на Mac, UNIX, Windows или Alpha.

Стандарт ANSI некоторое время оставался стабильным, и все основные производители компиляторов C ++ поддерживают стандарт ANSI.

Изучение C ++

Самое важное при изучении C ++ — это сосредоточиться на концепциях.

Цель изучения языка программирования — стать лучшим программистом; то есть, чтобы стать более эффективным в разработке и внедрении новых систем и в поддержании старых.

C ++ поддерживает множество стилей программирования. Вы можете писать в стиле Fortran, C, Smalltalk и т. Д. На любом языке. Каждый стиль может эффективно достигать своих целей при сохранении времени выполнения и эффективности использования пространства.

Использование C ++

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

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

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

Любой, кто использовал Apple Macintosh или ПК под управлением Windows, косвенно использовал C ++, потому что основные пользовательские интерфейсы этих систем написаны на C ++.

Настройка среды C ++

Настройка локальной среды

Если вы все еще хотите настроить свою среду для C ++, вам необходимо иметь на своем компьютере следующие две программы.

Текстовый редактор

Это будет использоваться для ввода вашей программы. Примерами немногих редакторов являются Блокнот Windows, команда редактирования ОС, Brief, Epsilon, EMACS и vim или vi.

Имя и версия текстового редактора могут различаться в разных операционных системах. Например, Блокнот будет использоваться в Windows, а vim или vi — в Windows, а также в Linux или UNIX.

Файлы, которые вы создаете в редакторе, называются исходными файлами, а для C ++ они обычно называются с расширением .cpp, .cp или .c.

Для начала программирования на C ++ должен быть текстовый редактор.

Компилятор C ++

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

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

Наиболее часто используемым и бесплатным доступным компилятором является компилятор GNU C / C ++, в противном случае вы можете иметь компиляторы из HP или Solaris, если у вас есть соответствующие операционные системы.

Установка компилятора GNU C / C ++

Установка UNIX / Linux

Если вы используете Linux или UNIX, проверьте, установлен ли GCC в вашей системе, введя следующую команду из командной строки:

$ g++ -v

Если вы установили GCC, он должен напечатать следующее сообщение:

Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr .......
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)

Если GCC не установлен, вам придется установить его самостоятельно, используя подробные инструкции, доступные по адресу https://gcc.gnu.org/install/.

Установка Mac OS X

Если вы используете Mac OS X, самый простой способ получить GCC — это загрузить среду разработки Xcode с веб-сайта Apple и следовать простым инструкциям по установке.

Xcode в настоящее время доступен по адресу developer.apple.com/technologies/tools/ .

Установка Windows

Для установки GCC в Windows вам необходимо установить MinGW. Чтобы установить MinGW, перейдите на домашнюю страницу MinGW www.mingw.org и перейдите по ссылке на страницу загрузки MinGW. Загрузите последнюю версию программы установки MinGW, которая должна называться MinGW- <версия> .exe.

При установке MinGW, как минимум, вы должны установить gcc-core, gcc-g ++, binutils и среду выполнения MinGW, но вы можете установить больше.

Добавьте подкаталог bin вашей установки MinGW в переменную среды PATH, чтобы вы могли указывать эти инструменты в командной строке по их простым именам.

После завершения установки вы сможете запустить gcc, g ++, ar, ranlib, dlltool и несколько других инструментов GNU из командной строки Windows.

Базовый синтаксис C ++

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

  • Объект — объекты имеют состояния и поведение. Пример: у собаки есть состояния — цвет, имя, порода, а также поведение — виляние, лай, еда. Объект является экземпляром класса.

  • Класс — класс может быть определен как шаблон / план, который описывает поведение / состояния, которые поддерживает объект этого типа.

  • Методы . Метод — это в основном поведение. Класс может содержать много методов. Именно в методах пишутся логики, манипулируются данными и выполняются все действия.

  • Переменные экземпляра — каждый объект имеет свой уникальный набор переменных экземпляра. Состояние объекта создается значениями, назначенными этим переменным экземпляра.

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

Класс — класс может быть определен как шаблон / план, который описывает поведение / состояния, которые поддерживает объект этого типа.

Методы . Метод — это в основном поведение. Класс может содержать много методов. Именно в методах пишутся логики, манипулируются данными и выполняются все действия.

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

Структура программы на C ++

Давайте посмотрим на простой код, который будет печатать слова Hello World .

Live Demo

#include <iostream>
using namespace std;

// main() is where program execution begins.
int main() {
   cout << "Hello World"; // prints Hello World
   return 0;
}

Давайте посмотрим на различные части вышеупомянутой программы —

  • Язык C ++ определяет несколько заголовков, которые содержат информацию, которая необходима или полезна для вашей программы. Для этой программы нужен заголовок <iostream> .

  • Строка, использующая пространство имен std; говорит компилятору использовать пространство имен std. Пространства имен являются относительно недавним дополнением к C ++.

  • Следующая строка ‘ // main () — это место, где начинается выполнение программы. ‘это однострочный комментарий, доступный в C ++. Однострочные комментарии начинаются с // и заканчиваются в конце строки.

  • Строка int main () — это основная функция, с которой начинается выполнение программы.

  • Следующая строка cout << «Hello World»; заставляет сообщение «Hello World» отображаться на экране.

  • Следующая строка возвращает 0; завершает функцию main () и заставляет ее возвращать значение 0 вызывающему процессу.

Язык C ++ определяет несколько заголовков, которые содержат информацию, которая необходима или полезна для вашей программы. Для этой программы нужен заголовок <iostream> .

Строка, использующая пространство имен std; говорит компилятору использовать пространство имен std. Пространства имен являются относительно недавним дополнением к C ++.

Следующая строка ‘ // main () — это место, где начинается выполнение программы. ‘это однострочный комментарий, доступный в C ++. Однострочные комментарии начинаются с // и заканчиваются в конце строки.

Строка int main () — это основная функция, с которой начинается выполнение программы.

Следующая строка cout << «Hello World»; заставляет сообщение «Hello World» отображаться на экране.

Следующая строка возвращает 0; завершает функцию main () и заставляет ее возвращать значение 0 вызывающему процессу.

Компиляция и выполнение программы C ++

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

  • Откройте текстовый редактор и добавьте код, как указано выше.

  • Сохраните файл как: hello.cpp

  • Откройте командную строку и перейдите в каталог, где вы сохранили файл.

  • Введите «g ++ hello.cpp» и нажмите Enter, чтобы скомпилировать ваш код. Если в вашем коде нет ошибок, командная строка переместит вас на следующую строку и сгенерирует исполняемый файл .out.

  • Теперь введите «a.out» для запуска вашей программы.

  • Вы сможете увидеть «Hello World», напечатанный на окне.

Откройте текстовый редактор и добавьте код, как указано выше.

Сохраните файл как: hello.cpp

Откройте командную строку и перейдите в каталог, где вы сохранили файл.

Введите «g ++ hello.cpp» и нажмите Enter, чтобы скомпилировать ваш код. Если в вашем коде нет ошибок, командная строка переместит вас на следующую строку и сгенерирует исполняемый файл .out.

Теперь введите «a.out» для запуска вашей программы.

Вы сможете увидеть «Hello World», напечатанный на окне.

$ g++ hello.cpp
$ ./a.out
Hello World

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

Вы можете компилировать программы на C / C ++, используя makefile. Для получения более подробной информации вы можете обратиться к нашему «Руководству по Makefile» .

Точки с запятой и блоки в C ++

В C ++ точка с запятой — это терминатор оператора. То есть каждое отдельное утверждение должно заканчиваться точкой с запятой. Это указывает на конец одного логического объекта.

Например, ниже приведены три разных утверждения —

x = y;
y = y + 1;
add(x, y);

Блок — это набор логически связанных операторов, которые заключены в открывающую и закрывающую скобки. Например —

{
   cout << "Hello World"; // prints Hello World
   return 0;
}

C ++ не распознает конец строки как терминатор. По этой причине не имеет значения, где вы помещаете оператор в строку. Например —

x = y;
y = y + 1;
add(x, y);

такой же как

x = y; y = y + 1; add(x, y);

Идентификаторы C ++

Идентификатор C ++ — это имя, используемое для идентификации переменной, функции, класса, модуля или любого другого пользовательского элемента. Идентификатор начинается с буквы от A до Z или от a до z или подчеркивания (_), за которым следуют ноль или более букв, подчеркиваний и цифр (от 0 до 9).

C ++ не допускает использование знаков препинания, таких как @, $ и% в идентификаторах. C ++ является регистрозависимым языком программирования. Таким образом, рабочая сила и рабочая сила — это два разных идентификатора в C ++.

Вот несколько примеров допустимых идентификаторов:

mohd       zara    abc   move_name  a_123
myname50   _temp   j     a23b9      retVal

C ++ Ключевые слова

В следующем списке показаны зарезервированные слова в C ++. Эти зарезервированные слова не могут использоваться как константы или переменные или любые другие имена идентификаторов.

как м еще новый этот
авто перечисление оператор бросать
BOOL явный частный правда
перерыв экспорт защищенный пытаться
дело внешний общественности ЬурейеЕ
ловить ложный регистр TypeId
голец поплавок reinterpret_cast имяТипа
учебный класс за вернуть союз
Const друг короткая неподписанный
const_cast идти к подписанный с помощью
Продолжить если размер виртуальный
дефолт в соответствии статический недействительным
удалять ИНТ static_cast летучий
делать долго структура wchar_t
двойной изменчивый переключатель в то время как
dynamic_cast Пространство имен шаблон

триграфы

Несколько символов имеют альтернативное представление, называемое последовательностью триграфа. Триграф — это трехсимвольная последовательность, представляющая один символ, и последовательность всегда начинается с двух вопросительных знаков.

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

Ниже приведены наиболее часто используемые последовательности триграфа.

триграф замена
знак равно #
?? / \
??» ^
?? ( [
??) ]
??! |
?? < {
??> }
?? — ~

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

Пробелы в C ++

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

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

Заявление 1

int age;

В приведенном выше утверждении должен быть хотя бы один символ пробела (обычно пробел) между int и age, чтобы компилятор мог их различать.

Заявление 2

fruit = apples + oranges;   // Get the total fruit

В приведенном выше утверждении 2 не нужно вводить пробельные символы между фруктами и = или между = и яблоками, хотя вы можете включить некоторые из них, если хотите, чтобы они были удобочитаемыми.

Комментарии в C ++

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

C ++ поддерживает однострочные и многострочные комментарии. Все символы, доступные внутри любого комментария, игнорируются компилятором C ++.

Комментарии C ++ начинаются с / * и заканчиваются * /. Например —

/* This is a comment */

/* C++ comments can also
   * span multiple lines
*/

Комментарий также может начинаться с //, продолжаясь до конца строки. Например —

Live Demo

#include <iostream>
using namespace std;

main() {
   cout << "Hello World"; // prints Hello World
   
   return 0;
}

Когда приведенный выше код скомпилирован, он игнорирует // печатает Hello World, и конечный исполняемый файл выдаст следующий результат —

Hello World

В комментариях / * и * / символы // не имеют особого значения. // в комментариях / * и * / не имеют особого значения. Таким образом, вы можете «вкладывать» один вид комментария в другой вид. Например —

/* Comment out printing of Hello World:

cout << "Hello World"; // prints Hello World

*/

Типы данных C ++

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

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

Примитивные встроенные типы

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

Тип Ключевое слово
логический BOOL
символ голец
целое число ИНТ
Плавающая запятая поплавок
Двойная точка с плавающей точкой двойной
бесполезный недействительным
Широкий характер wchar_t

Некоторые из базовых типов могут быть изменены с использованием одного или нескольких модификаторов этих типов —

  • подписанный
  • неподписанный
  • короткая
  • долго

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

Тип Типичная ширина бита Типичный диапазон
голец 1 байт От -127 до 127 или от 0 до 255
без знака 1 байт От 0 до 255
подписанный символ 1 байт От -127 до 127
ИНТ 4 байта От -2147483648 до 2147483647
без знака int 4 байта От 0 до 4294967295
подписанный int 4 байта От -2147483648 до 2147483647
короткий int 2bytes От -32768 до 32767
беззнаковый короткий int Спектр От 0 до 65 535
подписанный короткий int Спектр От -32768 до 32767
длинный инт 4 байта От -2 147 483 648 до 2 147 483 647
подписанный длинный int 4 байта такой же как long int
без знака длинный int 4 байта От 0 до 4 294 967 295
поплавок 4 байта +/- 3.4e +/- 38 (~ 7 цифр)
двойной 8bytes +/- 1.7e +/- 308 (~ 15 цифр)
длинный двойной 8bytes +/- 1.7e +/- 308 (~ 15 цифр)
wchar_t 2 или 4 байта 1 широкий символ

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

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

Live Demo

#include <iostream>
using namespace std;

int main() {
   cout << "Size of char : " << sizeof(char) << endl;
   cout << "Size of int : " << sizeof(int) << endl;
   cout << "Size of short int : " << sizeof(short int) << endl;
   cout << "Size of long int : " << sizeof(long int) << endl;
   cout << "Size of float : " << sizeof(float) << endl;
   cout << "Size of double : " << sizeof(double) << endl;
   cout << "Size of wchar_t : " << sizeof(wchar_t) << endl;
   
   return 0;
}

В этом примере используется endl , который вставляет символ новой строки после каждой строки, а оператор << используется для передачи нескольких значений на экран. Мы также используем оператор sizeof (), чтобы получить размер различных типов данных.

Когда приведенный выше код компилируется и выполняется, он дает следующий результат, который может варьироваться от машины к машине —

Size of char : 1
Size of int : 4
Size of short int : 2
Size of long int : 4
Size of float : 4
Size of double : 8
Size of wchar_t : 4

Объявления typedef

Вы можете создать новое имя для существующего типа, используя typedef . Ниже приведен простой синтаксис для определения нового типа с помощью typedef —

typedef type newname; 

Например, следующее говорит компилятору, что foot — это другое имя для int —

typedef int feet;

Теперь следующее объявление является абсолютно допустимым и создает целочисленную переменную с именем distance —

feet distance;

Перечисляемые типы

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

Создание перечисления требует использования ключевого слова enum . Общая форма типа перечисления —

enum enum-name { list of names } var-list; 

Здесь enum-name — это имя типа перечисления. Список имен разделен запятыми.

Например, следующий код определяет перечисление цветов, называемых цветами, и переменную c типа color. Наконец, с присваивается значение «синий».

enum color { red, green, blue } c;
c = blue;

По умолчанию значение первого имени равно 0, второе имя имеет значение 1, третье — 2 и т. Д. Но вы можете дать имя, конкретное значение, добавив инициализатор. Например, в следующем перечислении зеленый цвет будет иметь значение 5.

enum color { red, green = 5, blue };

Здесь синий будет иметь значение 6, потому что каждое имя будет на одно больше, чем предыдущее.

Типы переменных C ++

Переменная предоставляет нам именованное хранилище, которым наши программы могут манипулировать. Каждая переменная в C ++ имеет определенный тип, который определяет размер и расположение памяти переменной; диапазон значений, которые могут быть сохранены в этой памяти; и набор операций, которые могут быть применены к переменной.

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

Существуют следующие основные типы переменных в C ++, как описано в предыдущей главе:

Sr.No Тип и описание
1

BOOL

Хранит либо значение true, либо false.

2

голец

Обычно один октет (один байт). Это целочисленный тип.

3

ИНТ

Наиболее натуральный размер целого числа для машины.

4

поплавок

Значение с плавающей запятой одинарной точности.

5

двойной

Значение с плавающей запятой двойной точности.

6

недействительным

Представляет отсутствие типа.

7

wchar_t

Широкий тип символов.

BOOL

Хранит либо значение true, либо false.

голец

Обычно один октет (один байт). Это целочисленный тип.

ИНТ

Наиболее натуральный размер целого числа для машины.

поплавок

Значение с плавающей запятой одинарной точности.

двойной

Значение с плавающей запятой двойной точности.

недействительным

Представляет отсутствие типа.

wchar_t

Широкий тип символов.

C ++ также позволяет определять различные другие типы переменных, которые мы рассмотрим в последующих главах, таких как Enumeration, Pointer, Array, Reference, структуры данных и классы .

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

Определение переменной в C ++

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

type variable_list;

Здесь тип должен быть допустимым типом данных C ++, включая char, w_char, int, float, double, bool или любой определенный пользователем объект и т. Д., А variable_list может состоять из одного или нескольких имен идентификаторов, разделенных запятыми. Некоторые действительные объявления показаны здесь —

int    i, j, k;
char   c, ch;
float  f, salary;
double d;

Линия int i, j, k; оба объявляют и определяют переменные i, j и k; который инструктирует компилятор создавать переменные с именами i, j и k типа int.

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

type variable_name = value;

Вот некоторые примеры:

extern int d = 3, f = 5;    // declaration of d and f. 
int d = 3, f = 5;           // definition and initializing d and f. 
byte z = 22;                // definition and initializes z. 
char x = 'x';               // the variable x has the value 'x'.

Для определения без инициализатора: переменные со статической продолжительностью хранения неявно инициализируются с помощью NULL (все байты имеют значение 0); начальное значение всех других переменных не определено.

Объявление переменных в C ++

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

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

пример

Попробуйте следующий пример, где переменная была объявлена ​​вверху, но она была определена внутри основной функции —

Live Demo

#include <iostream>
using namespace std;

// Variable declaration:
extern int a, b;
extern int c;
extern float f;
  
int main () {
   // Variable definition:
   int a, b;
   int c;
   float f;
 
   // actual initialization
   a = 10;
   b = 20;
   c = a + b;
 
   cout << c << endl ;

   f = 70.0/3.0;
   cout << f << endl ;
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

30
23.3333

Та же концепция применяется к объявлению функции, когда вы предоставляете имя функции во время ее объявления, и ее фактическое определение может быть дано где-либо еще. Например —

// function declaration
int func();
int main() {
   // function call
   int i = func();
}

// function definition
int func() {
   return 0;
}

Lvalues ​​и Rvalues

В C ++ есть два вида выражений:

  • lvalue — Выражения, которые ссылаются на ячейку памяти, называются выражением «lvalue». Lvalue может отображаться как левая или правая сторона задания.

  • rvalue — термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Значение r — это выражение, которому не может быть присвоено значение, что означает, что значение r может появляться с правой, но не с левой стороны присвоения.

lvalue — Выражения, которые ссылаются на ячейку памяти, называются выражением «lvalue». Lvalue может отображаться как левая или правая сторона задания.

rvalue — термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Значение r — это выражение, которому не может быть присвоено значение, что означает, что значение r может появляться с правой, но не с левой стороны присвоения.

Переменные являются lvalues ​​и могут отображаться в левой части назначения. Числовые литералы являются r-значениями, поэтому не могут быть назначены и не могут отображаться слева. Следующее является действительным утверждением —

int g = 20;

Но следующее не является допустимым утверждением и приведет к ошибке времени компиляции:

10 = 20;

Переменная Область в C ++

Область действия — это область программы, и, в общем, есть три места, где переменные могут быть объявлены:

  • Внутри функции или блока, который называется локальными переменными,

  • В определении параметров функции это называется формальными параметрами.

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

Внутри функции или блока, который называется локальными переменными,

В определении параметров функции это называется формальными параметрами.

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

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

Локальные переменные

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

Live Demo

#include <iostream>
using namespace std;
 
int main () {
   // Local variable declaration:
   int a, b;
   int c;
 
   // actual initialization
   a = 10;
   b = 20;
   c = a + b;
 
   cout << c;
 
   return 0;
}

Глобальные переменные

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

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

Live Demo

#include <iostream>
using namespace std;
 
// Global variable declaration:
int g;
 
int main () {
   // Local variable declaration:
   int a, b;
 
   // actual initialization
   a = 10;
   b = 20;
   g = a + b;
  
   cout << g;
 
   return 0;
}

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

Live Demo

#include <iostream>
using namespace std;
 
// Global variable declaration:
int g = 20;
 
int main () {
   // Local variable declaration:
   int g = 10;
 
   cout << g;
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

10

Инициализация локальных и глобальных переменных

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

Тип данных Initializer
ИНТ 0
голец ‘\ 0’
поплавок 0
двойной 0
указатель НОЛЬ

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

C ++ Константы / Литералы

Константы относятся к фиксированным значениям, которые программа не может изменить, и они называются литералами .

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

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

Целочисленные литералы

Целочисленный литерал может быть десятичной, восьмеричной или шестнадцатеричной константой. Префикс указывает основание или основание: 0x или 0X для шестнадцатеричного, 0 для восьмеричного и ничего для десятичного.

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

Вот несколько примеров целочисленных литералов —

212         // Legal
215u        // Legal
0xFeeL      // Legal
078         // Illegal: 8 is not an octal digit
032UU       // Illegal: cannot repeat a suffix

Ниже приведены другие примеры различных типов литералов Integer:

85         // decimal
0213       // octal
0x4b       // hexadecimal
30         // int
30u        // unsigned int
30l        // long
30ul       // unsigned long

Литералы с плавающей точкой

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

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

Вот несколько примеров литералов с плавающей точкой —

3.14159       // Legal
314159E-5L    // Legal
510E          // Illegal: incomplete exponent
210f          // Illegal: no decimal or exponent
.e55          // Illegal: missing integer or fraction

Логические литералы

Есть два логических литерала, и они являются частью стандартных ключевых слов C ++ —

  • Значение true, представляющее истину.

  • Значение false, представляющее ложь.

Значение true, представляющее истину.

Значение false, представляющее ложь.

Не следует считать значение true равным 1, а значение false равным 0.

Символьные литералы

Символьные литералы заключены в одинарные кавычки. Если литерал начинается с L (только в верхнем регистре), он является литералом широких символов (например, L’x ‘) и должен храниться в переменной типа wchar_t . В противном случае это узкий символьный литерал (например, ‘x’), который может быть сохранен в простой переменной типа char .

Символьный литерал может быть простым символом (например, «x»), escape-последовательностью (например, «\ t») или универсальным символом (например, «\ u02C0»).

В C ++ есть определенные символы, когда им предшествует обратная косая черта, они будут иметь особое значение и использоваться для представления, например, новой строки (\ n) или табуляции (\ t). Здесь у вас есть список некоторых из таких кодов escape-последовательностей —

Последовательность побега Имея в виду
\\ \ персонаж
‘ персонаж
» персонаж
\? ? персонаж
\ а Оповещение или звонок
\ б возврат на одну позицию
\ е Форма подачи
\ п Новая линия
Возврат каретки
\ т Горизонтальная вкладка
\ v Вертикальная вкладка
\ ооо Восьмеричное число от одной до трех цифр
ххх , , Шестнадцатеричное число из одной или нескольких цифр

Ниже приведен пример, показывающий несколько символов escape-последовательности:

Live Demo

#include <iostream>
using namespace std;

int main() {
   cout << "Hello\tWorld\n\n";
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Hello   World

Строковые литералы

Строковые литералы заключены в двойные кавычки. Строка содержит символы, похожие на символьные литералы: простые символы, escape-последовательности и универсальные символы.

Вы можете разбить длинную строку на несколько строк, используя строковые литералы, и разделить их, используя пробелы.

Вот несколько примеров строковых литералов. Все три формы являются одинаковыми строками.

"hello, dear"

"hello, \

dear"

"hello, " "d" "ear"

Определение констант

В C ++ есть два простых способа определения констант:

  • Использование #define препроцессора.

  • Используя ключевое слово const .

Использование #define препроцессора.

Используя ключевое слово const .

Препроцессор #define

Ниже приведена форма для использования препроцессора #define для определения константы:

#define identifier value

Следующий пример объясняет это подробно —

Live Demo

#include <iostream>
using namespace std;

#define LENGTH 10   
#define WIDTH  5
#define NEWLINE '\n'

int main() {
   int area;  
   
   area = LENGTH * WIDTH;
   cout << area;
   cout << NEWLINE;
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

50

Ключевое слово const

Вы можете использовать префикс const для объявления констант определенного типа следующим образом:

const type variable = value;

Следующий пример объясняет это подробно —

Live Demo

#include <iostream>
using namespace std;

int main() {
   const int  LENGTH = 10;
   const int  WIDTH  = 5;
   const char NEWLINE = '\n';
   int area;  
   
   area = LENGTH * WIDTH;
   cout << area;
   cout << NEWLINE;
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

50

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

Типы модификаторов C ++

C ++ позволяет типам данных char, int и double иметь предшествующие им модификаторы. Модификатор используется для изменения значения базового типа, чтобы он более точно соответствовал потребностям различных ситуаций.

Модификаторы типов данных перечислены здесь —

  • подписанный
  • неподписанный
  • долго
  • короткая

Модификаторы sign, unsigned, long и short могут применяться к целочисленным базовым типам. Кроме того, подписанные и неподписанные могут быть применены к char, и long могут быть применены к double.

Модификаторы sign и unsigned также можно использовать в качестве префикса для длинных или коротких модификаторов. Например, unsigned long int .

C ++ позволяет использовать сокращенную запись для объявления целых чисел без знака, коротких или длинных . Вы можете просто использовать слово unsigned, short или long без int . Это автоматически подразумевает int . Например, следующие два оператора объявляют целочисленные переменные без знака.

unsigned x;
unsigned int y;

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

Live Demo

#include <iostream>
using namespace std;
 
/* This program shows the difference between
   * signed and unsigned integers.
*/
int main() {
   short int i;           // a signed short integer
   short unsigned int j;  // an unsigned short integer

   j = 50000;

   i = j;
   cout << i << " " << j;

   return 0;
}

Когда эта программа запущена, следующий вывод —

-15536 50000

Вышеуказанный результат объясняется тем, что битовая комбинация, которая представляет 50000 как короткое целое число без знака, интерпретируется как -15 536 по короткому.

Типовые классификаторы в C ++

Спецификаторы типов предоставляют дополнительную информацию о переменных, которым они предшествуют.

Sr.No Квалификатор и смысл
1

Const

Объекты типа const не могут быть изменены вашей программой во время выполнения.

2

летучий

Модификатор volatile сообщает компилятору, что значение переменной может быть изменено способами, явно не указанными программой.

3

ограничивать

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

Const

Объекты типа const не могут быть изменены вашей программой во время выполнения.

летучий

Модификатор volatile сообщает компилятору, что значение переменной может быть изменено способами, явно не указанными программой.

ограничивать

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

Классы хранения в C ++

Класс хранения определяет область действия (видимость) и время жизни переменных и / или функций в программе C ++. Эти спецификаторы предшествуют типу, который они изменяют. Существуют следующие классы хранения, которые можно использовать в программе C ++

  • авто
  • регистр
  • статический
  • внешний
  • изменчивый

Авто Класс Хранения

Класс автоматического хранения является классом хранения по умолчанию для всех локальных переменных.

{
   int mount;
   auto int month;
}

В приведенном выше примере определены две переменные с одним и тем же классом хранения, auto можно использовать только внутри функций, то есть локальные переменные.

Класс хранения регистра

Класс хранения регистров используется для определения локальных переменных, которые должны храниться в регистре, а не в ОЗУ. Это означает, что переменная имеет максимальный размер, равный размеру регистра (обычно одно слово), и к ней не может быть применен унарный оператор ‘&’ (так как она не имеет места в памяти).

{
   register int  miles;
}

Регистр следует использовать только для переменных, которые требуют быстрого доступа, таких как счетчики. Следует также отметить, что определение «регистр» не означает, что переменная будет храниться в регистре. Это означает, что он МОЖЕТ храниться в реестре в зависимости от аппаратного обеспечения и ограничений реализации.

Статический класс хранения

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

Статический модификатор также может применяться к глобальным переменным. Когда это сделано, область действия этой переменной будет ограничена файлом, в котором она объявлена.

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

Live Demo

#include <iostream>
 
// Function declaration
void func(void);
 
static int count = 10; /* Global variable */
 
main() {
   while(count--) {
      func();
   }
   
   return 0;
}

// Function definition
void func( void ) {
   static int i = 5; // local static variable
   i++;
   std::cout << "i is " << i ;
   std::cout << " and count is " << count << std::endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

i is 6 and count is 9
i is 7 and count is 8
i is 8 and count is 7
i is 9 and count is 6
i is 10 and count is 5
i is 11 and count is 4
i is 12 and count is 3
i is 13 and count is 2
i is 14 and count is 1
i is 15 and count is 0

Внешний класс хранения

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

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

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

Первый файл: main.cpp

#include <iostream>
int count ;
extern void write_extern();
 
main() {
   count = 5;
   write_extern();
}

Второй файл: support.cpp

#include <iostream>

extern int count;

void write_extern(void) {
   std::cout << "Count is " << count << std::endl;
}

Здесь ключевое слово extern используется для объявления счетчика в другом файле. Теперь скомпилируйте эти два файла следующим образом:

$g++ main.cpp support.cpp -o write

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

$./write
5

Изменяемый класс хранения

Спецификатор mutable применяется только к объектам класса, которые обсуждаются далее в этом руководстве. Это позволяет члену объекта переопределять функцию-член const. То есть изменяемый член может быть изменен с помощью функции-члена const.

Операторы в C ++

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

  • Арифметические Операторы
  • Операторы отношений
  • Логические Операторы
  • Битовые операторы
  • Операторы присваивания
  • Разные Операторы

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

Арифметические Операторы

Существуют следующие арифметические операторы, поддерживаемые языком C ++ —

Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
+ Добавляет два операнда А + Б даст 30
Вычитает второй операнд из первого A — B даст -10
* Умножает оба операнда А * Б даст 200
/ Делит числитель на числитель Б / у даст 2
% Оператор модуля и остаток от целочисленного деления B% A даст 0
++ Оператор приращения , увеличивает целочисленное значение на единицу А ++ даст 11
Оператор уменьшения, уменьшает целочисленное значение на единицу A— даст 9

Операторы отношений

В языке C ++ поддерживаются следующие реляционные операторы

Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
== Проверяет, равны ли значения двух операндов или нет, если да, тогда условие становится истинным. (A == B) не соответствует действительности.
знак равно Проверяет, равны ли значения двух операндов или нет, если значения не равны, тогда условие становится истинным. (A! = B) верно.
> Проверяет, больше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A> B) не соответствует действительности.
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A <B) верно.
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A> = B) не соответствует действительности.
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A <= B) верно.

Логические Операторы

Существуют следующие логические операторы, поддерживаемые языком C ++.

Предположим, что переменная A содержит 1, а переменная B содержит 0, тогда —

Показать примеры

оператор Описание пример
&& Называется логический оператор И. Если оба операнда отличны от нуля, условие становится истинным. (A && B) неверно.
|| Вызывается логическим оператором ИЛИ. Если любой из двух операндов отличен от нуля, условие становится истинным. (A || B) верно.
! Вызывается логическим оператором НЕ. Используйте для изменения логического состояния своего операнда. Если условие истинно, то оператор Логический НЕ будет делать ложь. ! (A && B) верно.

Битовые операторы

Побитовый оператор работает с битами и выполняет побитовую операцию. Таблицы истинности для &, | и ^ следующие:

п Q P & Q р | Q р ^ д
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Предположим, если А = 60; и B = 13; теперь в двоичном формате они будут выглядеть следующим образом —

A = 0011 1100

B = 0000 1101

——————

A & B = 0000 1100

A | B = 0011 1101

A ^ B = 0011 0001

~ A = 1100 0011

Побитовые операторы, поддерживаемые языком C ++, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда —

Показать примеры

оператор Описание пример
& Двоичный оператор AND немного копирует результат, если он существует в обоих операндах. (A & B) даст 12, что 0000 1100
| Оператор двоичного ИЛИ копирует немного, если он существует в любом из операндов. (A | B) даст 61, что составляет 0011 1101
^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^ B) даст 49, который является 0011 0001
~ Оператор дополнения двоичных единиц является унарным и имеет эффект «переворачивания» битов. (~ A) даст -61, что составляет 1100 0011 в форме дополнения 2 из-за двоичного числа со знаком.
<< Двоичный оператор левого сдвига. Значение левого операнда перемещается влево на количество битов, указанное правым операндом. << 2 даст 240, что составляет 1111 0000
>> Оператор двоичного правого сдвига. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >> 2 даст 15, что 0000 1111

Операторы присваивания

Существуют следующие операторы присваивания, поддерживаемые языком C ++ —

Показать примеры

оператор Описание пример
знак равно Простой оператор присваивания, присваивает значения от правых операндов к левому операнду. C = A + B назначит значение A + B в C
+ = Добавить оператор присваивания И, он добавляет правый операнд к левому операнду и присваивает результат левому операнду. C + = A эквивалентно C = C + A
знак равно Вычитание И оператор присваивания, вычитает правый операнд из левого операнда и присваивает результат левому операнду. C — = A эквивалентно C = C — A
знак равно Оператор присваивания умножения И, умножает правый операнд на левый операнд и присваивает результат левому операнду. C * = A эквивалентно C = C * A
знак равно Оператор деления И присваивания, делит левый операнд на правый операнд и присваивает результат левому операнду. C / = A эквивалентно C = C / A
знак равно Модуль и оператор присваивания. Он принимает модуль с использованием двух операндов и присваивает результат левому операнду. C% = A эквивалентно C = C% A
<< = Левый сдвиг И оператор присваивания. C << = 2 совпадает с C = C << 2
>> = Сдвиг вправо И оператор присваивания. C >> = 2 — это то же самое, что C = C >> 2
знак равно Побитовое И оператор присваивания. C & = 2 совпадает с C = C & 2
^ = Побитовое исключающее ИЛИ и оператор присваивания. C ^ = 2 совпадает с C = C ^ 2
| = Побитовое ИЛИ и оператор присваивания. C | = 2 — это то же самое, что C = C | 2

Разные Операторы

В следующей таблице перечислены некоторые другие операторы, которые поддерживает C ++.

Sr.No Оператор и описание
1

размер

Оператор sizeof возвращает размер переменной. Например, sizeof (a), где «a» является целым числом и вернет 4.

2

Состояние ? X: Y

Условный оператор (?) . Если Условие истинно, то оно возвращает значение X, в противном случае возвращает значение Y.

3

,

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

4

, (точка) и -> (стрелка)

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

5

В ролях

Операторы приведения преобразуют один тип данных в другой. Например, int (2.2000) вернет 2.

6

&

Оператор указателя & возвращает адрес переменной. Например, & a; даст фактический адрес переменной.

7

*

Оператор указателя * является указателем на переменную. Например * var; будет указатель на переменную var.

размер

Оператор sizeof возвращает размер переменной. Например, sizeof (a), где «a» является целым числом и вернет 4.

Состояние ? X: Y

Условный оператор (?) . Если Условие истинно, то оно возвращает значение X, в противном случае возвращает значение Y.

,

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

, (точка) и -> (стрелка)

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

В ролях

Операторы приведения преобразуют один тип данных в другой. Например, int (2.2000) вернет 2.

&

Оператор указателя & возвращает адрес переменной. Например, & a; даст фактический адрес переменной.

*

Оператор указателя * является указателем на переменную. Например * var; будет указатель на переменную var.

Приоритет операторов в C ++

Приоритет оператора определяет группировку терминов в выражении. Это влияет на то, как оценивается выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения —

Например, х = 7 + 3 * 2; здесь x назначено 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому он сначала умножается на 3 * 2, а затем прибавляется к 7.

Здесь операторы с самым высоким приоритетом отображаются вверху таблицы, а операторы с самым низким — внизу. Внутри выражения операторы с более высоким приоритетом будут оцениваться первыми.

Показать примеры

категория оператор Ассоциативность
постфикс () [] ->. ++ — — Слева направо
Одинарный + -! ~ ++ — — (тип) * & sizeof Справа налево
Multiplicative * /% Слева направо
присадка + — Слева направо
сдвиг << >> Слева направо
реляционный <<=>> = Слева направо
равенство ==! = Слева направо
Побитовое И & Слева направо
Побитовый XOR ^ Слева направо
Побитовое ИЛИ | Слева направо
Логическое И && Слева направо
Логическое ИЛИ || Слева направо
условный ?: Справа налево
присваивание = + = — = * = / =% = >> = << = & = ^ = | = Справа налево
запятая , Слева направо

Типы циклов C ++

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

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

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

Петлевая архитектура

Язык программирования C ++ предоставляет следующий тип циклов для обработки требований циклов.

Sr.No Тип и описание петли
1 в то время как цикл

Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

2 для цикла

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

3 делать … пока цикл

Как и оператор while, за исключением того, что он проверяет условие в конце тела цикла.

4 вложенные циклы

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

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

Как и оператор while, за исключением того, что он проверяет условие в конце тела цикла.

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Заявления о контроле цикла

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

C ++ поддерживает следующие операторы управления.

Sr.No Контрольное заявление и описание
1 заявление о нарушении

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

2 продолжить заявление

Заставляет петлю пропускать оставшуюся часть своего тела и немедленно проверять свое состояние перед повторением.

3 Перейти к заявлению

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

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

Заставляет петлю пропускать оставшуюся часть своего тела и немедленно проверять свое состояние перед повторением.

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

Бесконечный цикл

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

#include <iostream>
using namespace std;
 
int main () {
   for( ; ; ) {
      printf("This loop will run forever.\n");
   }

   return 0;
}

Когда условное выражение отсутствует, оно считается истинным. У вас может быть выражение инициализации и приращения, но программисты на C ++ чаще используют конструкцию for (;;) для обозначения бесконечного цикла.

ПРИМЕЧАНИЕ. — Вы можете завершить бесконечный цикл, нажав клавиши Ctrl + C.

C ++ принятия решений

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

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

C ++ принятие решений

Язык программирования C ++ предоставляет следующие типы операторов принятия решений.

Sr.No Заявление и описание
1 если заявление

Оператор if состоит из логического выражения, за которым следует одно или несколько операторов.

2 если … еще заявление

За оператором if может следовать необязательный оператор else, который выполняется, когда логическое выражение имеет значение false.

3 заявление о переключении

Оператор switch позволяет проверять переменную на соответствие списку значений.

4 вложенные операторы if

Вы можете использовать один оператор «if» или «else if» внутри другого оператора «if» или «else if».

5 вложенные операторы switch

Вы можете использовать один оператор «switch» внутри другого оператора «switch».

Оператор if состоит из логического выражения, за которым следует одно или несколько операторов.

За оператором if может следовать необязательный оператор else, который выполняется, когда логическое выражение имеет значение false.

Оператор switch позволяет проверять переменную на соответствие списку значений.

Вы можете использовать один оператор «if» или «else if» внутри другого оператора «if» или «else if».

Вы можете использовать один оператор «switch» внутри другого оператора «switch».

? : Оператор

Мы накрыли условного оператора «? : » В предыдущей главе, которая может быть использована для замены операторов if … else . Он имеет следующую общую форму —

Exp1 ? Exp2 : Exp3;

Exp1, Exp2 и Exp3 являются выражениями. Обратите внимание на использование и размещение толстой кишки.

Значение ‘?’ Выражение определяется следующим образом: Exp1 оценивается. Если это правда, тогда Exp2 вычисляется и становится значением всего ‘?’ выражение. Если Exp1 имеет значение false, то Exp3 оценивается, и его значение становится значением выражения.

Функции C ++

Функция — это группа операторов, которые вместе выполняют задачу. Каждая программа на C ++ имеет по крайней мере одну функцию, которая является main () , и все самые тривиальные программы могут определять дополнительные функции.

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

Объявление функции сообщает компилятору об имени функции, типе возврата и параметрах. Определение функции обеспечивает фактическое тело функции.

Стандартная библиотека C ++ предоставляет множество встроенных функций, которые может вызывать ваша программа. Например, функция strcat () для объединения двух строк, функция memcpy () для копирования одной области памяти в другую и многих других функций.

Функция известна под разными именами, например, метод, подпрограмма, процедура и т. Д.

Определение функции

Общая форма определения функции C ++ выглядит следующим образом:

return_type function_name( parameter list ) {
   body of the function
}

Определение функции C ++ состоит из заголовка функции и тела функции. Вот все части функции —

  • Тип возврата — функция может возвращать значение. Return_type — это тип данных значения, которое возвращает функция. Некоторые функции выполняют нужные операции без возврата значения. В этом случае return_type является ключевым словом void .

  • Имя функции — это фактическое имя функции. Имя функции и список параметров вместе составляют сигнатуру функции.

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

  • Тело функцииТело функции содержит набор операторов, которые определяют, что делает функция.

Тип возврата — функция может возвращать значение. Return_type — это тип данных значения, которое возвращает функция. Некоторые функции выполняют нужные операции без возврата значения. В этом случае return_type является ключевым словом void .

Имя функции — это фактическое имя функции. Имя функции и список параметров вместе составляют сигнатуру функции.

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

Тело функцииТело функции содержит набор операторов, которые определяют, что делает функция.

пример

Ниже приведен исходный код функции с именем max () . Эта функция принимает два параметра num1 и num2 и возвращает наибольшее из обоих:

// function returning the max between two numbers
 
int max(int num1, int num2) {
   // local variable declaration
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

Объявления функций

Объявление функции сообщает компилятору об имени функции и о том, как вызывать функцию. Фактическое тело функции может быть определено отдельно.

Объявление функции состоит из следующих частей:

return_type function_name( parameter list );

Для определенной выше функции max () ниже приводится объявление функции:

int max(int num1, int num2);

Имена параметров не важны в объявлении функции, требуется только их тип, поэтому следующее также является допустимым объявлением:

int max(int, int);

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

Вызов функции

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

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

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

Live Demo

#include <iostream>
using namespace std;
 
// function declaration
int max(int num1, int num2);
 
int main () {
   // local variable declaration:
   int a = 100;
   int b = 200;
   int ret;
 
   // calling a function to get max value.
   ret = max(a, b);
   cout << "Max value is : " << ret << endl;
 
   return 0;
}
 
// function returning the max between two numbers
int max(int num1, int num2) {
   // local variable declaration
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

Я сохранил функцию max () вместе с функцией main () и скомпилировал исходный код. Запустив финальный исполняемый файл, он даст следующий результат:

Max value is : 200

Аргументы функции

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

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

При вызове функции существует два способа передачи аргументов в функцию:

Sr.No Тип звонка и описание
1 Звонок по значению

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

2 Звонок по указателю

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

3 Звоните по ссылке

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

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

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

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

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

Значения по умолчанию для параметров

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

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

Live Demo

#include <iostream>
using namespace std;
 
int sum(int a, int b = 20) {
   int result;
   result = a + b;
  
   return (result);
}
int main () {
   // local variable declaration:
   int a = 100;
   int b = 200;
   int result;
 
   // calling a function to add the values.
   result = sum(a, b);
   cout << "Total value is :" << result << endl;

   // calling a function again as follows.
   result = sum(a);
   cout << "Total value is :" << result << endl;
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total value is :300
Total value is :120

Числа в C ++

Обычно, когда мы работаем с Numbers, мы используем примитивные типы данных, такие как int, short, long, float и double и т. Д. Типы данных number, их возможные значения и диапазоны чисел были объяснены при обсуждении типов данных C ++.

Определение чисел в C ++

Вы уже определили числа в различных примерах, приведенных в предыдущих главах. Вот еще один сводный пример для определения различных типов чисел в C ++ —

Live Demo

#include <iostream>
using namespace std;
 
int main () {
   // number definition:
   short  s;
   int    i;
   long   l;
   float  f;
   double d;
   
   // number assignments;
   s = 10;      
   i = 1000;    
   l = 1000000; 
   f = 230.47;  
   d = 30949.374;
   
   // number printing;
   cout << "short  s :" << s << endl;
   cout << "int    i :" << i << endl;
   cout << "long   l :" << l << endl;
   cout << "float  f :" << f << endl;
   cout << "double d :" << d << endl;
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

short  s :10
int    i :1000
long   l :1000000
float  f :230.47
double d :30949.4

Математические операции в C ++

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

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

Чтобы использовать эти функции, вам нужно включить файл математического заголовка <cmath> .

Sr.No Функция и цель
1

двойной cos (double);

Эта функция принимает угол (как двойной) и возвращает косинус.

2

двойной грех (двойной);

Эта функция принимает угол (как двойное) и возвращает синус.

3

двойной загар (двойной);

Эта функция принимает угол (как двойное) и возвращает касательную.

4

двойной журнал (двойной);

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

5

двойной пау (двойной, двойной);

Первое — это число, которое вы хотите поднять, а второе — это сила, которую вы хотите поднять.

6

двойной гипот (двойной, двойной);

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

7

двойной квадрат (двухместный);

Вы передаете этой функции число, и оно дает вам квадратный корень.

8

int abs (int);

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

9

двойные fabs (двойной);

Эта функция возвращает абсолютное значение любого переданного ей десятичного числа.

10

двойной этаж (двухместный);

Находит целое число, которое меньше или равно аргументу, переданному ему.

двойной cos (double);

Эта функция принимает угол (как двойной) и возвращает косинус.

двойной грех (двойной);

Эта функция принимает угол (как двойное) и возвращает синус.

двойной загар (двойной);

Эта функция принимает угол (как двойное) и возвращает касательную.

двойной журнал (двойной);

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

двойной пау (двойной, двойной);

Первое — это число, которое вы хотите поднять, а второе — это сила, которую вы хотите поднять.

двойной гипот (двойной, двойной);

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

двойной квадрат (двухместный);

Вы передаете этой функции число, и оно дает вам квадратный корень.

int abs (int);

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

двойные fabs (двойной);

Эта функция возвращает абсолютное значение любого переданного ей десятичного числа.

двойной этаж (двухместный);

Находит целое число, которое меньше или равно аргументу, переданному ему.

Ниже приведен простой пример, демонстрирующий несколько математических операций:

Live Demo

#include <iostream>
#include <cmath>
using namespace std;
 
int main () {
   // number definition:
   short  s = 10;
   int    i = -1000;
   long   l = 100000;
   float  f = 230.47;
   double d = 200.374;

   // mathematical operations;
   cout << "sin(d) :" << sin(d) << endl;
   cout << "abs(i)  :" << abs(i) << endl;
   cout << "floor(d) :" << floor(d) << endl;
   cout << "sqrt(f) :" << sqrt(f) << endl;
   cout << "pow( d, 2) :" << pow(d, 2) << endl;
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

sign(d)     :-0.634939
abs(i)      :1000
floor(d)    :200
sqrt(f)     :15.1812
pow( d, 2 ) :40149.7

Случайные числа в C ++

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

Ниже приведен простой пример генерации нескольких случайных чисел. В этом примере функция time () используется для получения количества секунд вашего системного времени, для случайного заполнения функции rand () —

Live Demo

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;
 
int main () {
   int i,j;
 
   // set the seed
   srand( (unsigned)time( NULL ) );

   /* generate 10  random numbers. */
   for( i = 0; i < 10; i++ ) {
      // generate actual random number
      j = rand();
      cout <<" Random Number : " << j << endl;
   }

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Random Number : 1748144778
Random Number : 630873888
Random Number : 2134540646
Random Number : 219404170
Random Number : 902129458
Random Number : 920445370
Random Number : 1319072661
Random Number : 257938873
Random Number : 1256201101
Random Number : 580322989

C ++ Массивы

C ++ предоставляет структуру данных, массив , в котором хранится последовательная коллекция фиксированного размера элементов одного типа. Массив используется для хранения коллекции данных, но часто более полезно думать о массиве как о коллекции переменных одного типа.

Вместо того, чтобы объявлять отдельные переменные, такие как number0, number1, … и number99, вы объявляете одну переменную массива, такую ​​как числа, и используете числа [0], числа [1] и …, числа [99] для представления отдельные переменные. Определенный элемент в массиве доступен по индексу.

Все массивы состоят из смежных областей памяти. Самый низкий адрес соответствует первому элементу, а самый высокий адрес — последнему.

Объявление массивов

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

type arrayName [ arraySize ];

Это называется одномерным массивом. ArraySize должен быть целочисленной константой, большей нуля, и тип может быть любым допустимым типом данных C ++. Например, чтобы объявить массив из 10 элементов с именем balance типа double, используйте этот оператор —

double balance[10];

Инициализация массивов

Вы можете инициализировать элементы массива C ++ либо один за другим, либо используя один оператор следующим образом:

double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};

Число значений в фигурных скобках {} не может быть больше, чем количество элементов, которые мы объявляем для массива в квадратных скобках []. Ниже приведен пример назначения одного элемента массива:

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

double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};

Вы создадите точно такой же массив, как и в предыдущем примере.

balance[4] = 50.0;

Приведенный выше оператор присваивает элементу номер 5 в массиве значение 50,0. Массив с 4- м индексом будет 5- м , т. Е. Последним элементом, поскольку все массивы имеют 0 в качестве индекса их первого элемента, который также называется базовым индексом. Ниже приведено графическое представление того же массива, который мы обсуждали выше:

Презентация массива

Доступ к элементам массива

Доступ к элементу осуществляется путем индексации имени массива. Это делается путем помещения индекса элемента в квадратные скобки после имени массива. Например —

double salary = balance[9];

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

Live Demo

#include <iostream>
using namespace std;
 
#include <iomanip>
using std::setw;
 
int main () {

   int n[ 10 ]; // n is an array of 10 integers
 
   // initialize elements of array n to 0          
   for ( int i = 0; i < 10; i++ ) {
      n[ i ] = i + 100; // set element at location i to i + 100
   }
   cout << "Element" << setw( 13 ) << "Value" << endl;
 
   // output each array element's value                      
   for ( int j = 0; j < 10; j++ ) {
      cout << setw( 7 )<< j << setw( 13 ) << n[ j ] << endl;
   }
 
   return 0;
}

Эта программа использует функцию setw () для форматирования вывода. Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Element        Value
      0          100
      1          101
      2          102
      3          103
      4          104
      5          105
      6          106
      7          107
      8          108
      9          109

Массивы в C ++

Массивы важны для C ++ и должны требовать большего количества деталей. Есть несколько важных понятий, которые должны быть понятны программисту C ++:

Sr.No Концепция и описание
1 Многомерные массивы

C ++ поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

2 Указатель на массив

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

3 Передача массивов в функции

Вы можете передать функции указатель на массив, указав имя массива без индекса.

4 Возвращаем массив из функций

C ++ позволяет функции возвращать массив.

C ++ поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

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

Вы можете передать функции указатель на массив, указав имя массива без индекса.

C ++ позволяет функции возвращать массив.

Строки C ++

C ++ обеспечивает следующие два типа строковых представлений —

  • Строка символов в стиле C
  • Тип класса string, представленный в стандарте C ++.

Строка символов C-Style

Строка символов в стиле C возникла в языке C и продолжает поддерживаться в C ++. Эта строка на самом деле является одномерным массивом символов, который заканчивается нулевым символом ‘\ 0’. Таким образом, строка с нулевым символом в конце содержит символы, которые составляют строку, за которой следует ноль .

Следующее объявление и инициализация создают строку, состоящую из слова «Hello». Чтобы держать нулевой символ в конце массива, размер массива символов, содержащего строку, на один больше, чем количество символов в слове «Hello».

 char приветствие [6] = {'H', 'e', ​​'l', 'l', 'o', '\ 0'};

Если вы следуете правилу инициализации массива, вы можете написать приведенное выше утверждение следующим образом:

 char приветствие [] = "Привет";

Следующее представление памяти определенной выше строки в C / C ++ —

Строковая презентация в C / C ++

На самом деле, вы не помещаете нулевой символ в конец строковой константы. Компилятор C ++ автоматически помещает ‘\ 0’ в конец строки, когда инициализирует массив. Давайте попробуем напечатать вышеупомянутую строку —

Live Demo

 #include <iostream>

 использование пространства имен std;

 int main () {

    char приветствие [6] = {'H', 'e', ​​'l', 'l', 'o', '\ 0'};

    cout << "Приветственное сообщение:";
    cout << приветствие << endl;

    вернуть 0;
 }

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

 Приветственное сообщение: Привет

C ++ поддерживает широкий спектр функций, которые обрабатывают строки с нулевым символом в конце —

Sr.No Функция и цель
1

strcpy (s1, s2);

Копирует строку s2 в строку s1.

2

strcat (s1, s2);

Объединяет строку s2 в конец строки s1.

3

StrLen (S1);

Возвращает длину строки s1.

4

strcmp (s1, s2);

Возвращает 0, если s1 и s2 одинаковы; меньше 0, если s1 <s2; больше 0, если s1> s2.

5

strchr (s1, ch);

Возвращает указатель на первое вхождение символа ch в строке s1.

6

strstr (s1, s2);

Возвращает указатель на первое вхождение строки s2 в строку s1.

strcpy (s1, s2);

Копирует строку s2 в строку s1.

strcat (s1, s2);

Объединяет строку s2 в конец строки s1.

StrLen (S1);

Возвращает длину строки s1.

strcmp (s1, s2);

Возвращает 0, если s1 и s2 одинаковы; меньше 0, если s1 <s2; больше 0, если s1> s2.

strchr (s1, ch);

Возвращает указатель на первое вхождение символа ch в строке s1.

strstr (s1, s2);

Возвращает указатель на первое вхождение строки s2 в строку s1.

Следующий пример использует несколько из вышеупомянутых функций —

Live Demo

 #include <iostream>
 #include <cstring>

 использование пространства имен std;

 int main () {

    char str1 [10] = "Привет";
    char str2 [10] = "Мир";
    char str3 [10];
    int len;

    // копируем str1 в str3
    strcpy (str3, str1);
    cout << "strcpy (str3, str1):" << str3 << endl;

    // объединяет str1 и str2
    strcat (str1, str2);
    cout << "strcat (str1, str2):" << str1 << endl;

    // общая длина str1 после объединения
    len = strlen (str1);
    cout << "strlen (str1):" << len << endl;

    вернуть 0;
 }

Когда приведенный выше код компилируется и выполняется, он выдает результат, который выглядит следующим образом:

 strcpy (str3, str1): Привет
 strcat (str1, str2): HelloWorld
 Стрлен (str1): 10

Строковый класс в C ++

Стандартная библиотека C ++ предоставляет тип строкового класса, который поддерживает все операции, упомянутые выше, и, кроме того, гораздо больше функциональности. Давайте проверим следующий пример —

Live Demo

 #include <iostream>
 #include <string>

 использование пространства имен std;

 int main () {

    string str1 = "Hello";
    строка str2 = "Мир";
    строка str3;
    int len;

    // копируем str1 в str3
    str3 = str1;
    cout << "str3:" << str3 << endl;

    // объединяет str1 и str2
    str3 = str1 + str2;
    cout << "str1 + str2:" << str3 << endl;

    // общая длина str3 после конкатенации
    len = str3.size ();
    cout << "str3.size ():" << len << endl;

    вернуть 0;
 }

Когда приведенный выше код компилируется и выполняется, он выдает результат, который выглядит следующим образом:

 str3: Привет
 str1 + str2: HelloWorld
 str3.size (): 10

Указатели C ++

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

Как вы знаете, каждая переменная является ячейкой памяти, и каждая ячейка памяти имеет свой адрес, к которому можно обратиться, используя оператор амперсанда (&), который обозначает адрес в памяти. Рассмотрим следующее, которое выведет адрес определенных переменных:

Live Demo

#include <iostream>

using namespace std;
int main () {
   int  var1;
   char var2[10];

   cout << "Address of var1 variable: ";
   cout << &var1 << endl;

   cout << "Address of var2 variable: ";
   cout << &var2 << endl;

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Address of var1 variable: 0xbfebd5c0
Address of var2 variable: 0xbfebd5b6

Что такое указатели?

Указатель — это переменная, значением которой является адрес другой переменной. Как и любая переменная или константа, вы должны объявить указатель, прежде чем вы сможете работать с ним. Общая форма объявления переменной указателя —

type *var-name;

Здесь тип — это базовый тип указателя; это должен быть допустимый тип C ++, а var-name — это имя переменной-указателя. Звездочка, которую вы использовали для объявления указателя, та же, что и для умножения. Однако в этом утверждении звездочка используется для обозначения переменной в качестве указателя. Следующее является действительным объявлением указателя —

int    *ip;    // pointer to an integer
double *dp;    // pointer to a double
float  *fp;    // pointer to a float
char   *ch     // pointer to character

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

Использование указателей в C ++

Есть несколько важных операций, которые мы будем делать с указателями очень часто. (а) Мы определяем переменную указателя. (б) Присвоить адрес переменной указателю. (c) Наконец, получите доступ к значению по адресу, доступному в переменной указателя. Это делается с помощью унарного оператора *, который возвращает значение переменной, расположенной по адресу, указанному ее операндом. Следующий пример использует эти операции —

Live Demo

#include <iostream>

using namespace std;

int main () {
   int  var = 20;   // actual variable declaration.
   int  *ip;        // pointer variable 

   ip = &var;       // store address of var in pointer variable

   cout << "Value of var variable: ";
   cout << var << endl;

   // print the address stored in ip pointer variable
   cout << "Address stored in ip variable: ";
   cout << ip << endl;

   // access the value at the address available in pointer
   cout << "Value of *ip variable: ";
   cout << *ip << endl;

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он выдает результат, который выглядит следующим образом:

Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20

Указатели в C ++

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

Sr.No Концепция и описание
1 Нулевые указатели

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

2 Указатель Арифметика

Существует четыре арифметических оператора, которые можно использовать в указателях: ++, -, +, —

3 Указатели против массивов

Существует тесная связь между указателями и массивами.

4 Массив указателей

Вы можете определить массивы для хранения нескольких указателей.

5 Указатель на указатель

C ++ позволяет вам иметь указатель на указатель и так далее.

6 Передача указателей на функции

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

7 Возврат указателя из функций

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

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

Существует четыре арифметических оператора, которые можно использовать в указателях: ++, -, +, —

Существует тесная связь между указателями и массивами.

Вы можете определить массивы для хранения нескольких указателей.

C ++ позволяет вам иметь указатель на указатель и так далее.

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

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

C ++ Ссылки

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

Ссылки против указателей

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

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

  • Как только ссылка инициализируется на объект, она не может быть изменена для ссылки на другой объект. Указатели можно указывать на другой объект в любое время.

  • Ссылка должна быть инициализирована при ее создании. Указатели могут быть инициализированы в любое время.

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

Как только ссылка инициализируется на объект, она не может быть изменена для ссылки на другой объект. Указатели можно указывать на другой объект в любое время.

Ссылка должна быть инициализирована при ее создании. Указатели могут быть инициализированы в любое время.

Создание ссылок в C ++

Думайте о названии переменной как о метке, прикрепленной к расположению переменной в памяти. Затем вы можете думать о ссылке как о второй метке, прикрепленной к этой ячейке памяти. Таким образом, вы можете получить доступ к содержимому переменной через исходное имя переменной или ссылку. Например, предположим, у нас есть следующий пример —

int i = 17;

Мы можем объявить ссылочные переменные для i следующим образом.

int& r = i;

Прочитайте & в этих декларациях в качестве ссылки . Таким образом, прочитайте первое объявление как «r является целочисленной ссылкой, инициализированной в i», и прочитайте второе объявление как «s является двойной ссылкой, инициализированной в d». Следующий пример использует ссылки на int и double —

Live Demo

#include <iostream>
 
using namespace std;
 
int main () {
   // declare simple variables
   int    i;
   double d;
 
   // declare reference variables
   int&    r = i;
   double& s = d;
   
   i = 5;
   cout << "Value of i : " << i << endl;
   cout << "Value of i reference : " << r  << endl;
 
   d = 11.7;
   cout << "Value of d : " << d << endl;
   cout << "Value of d reference : " << s  << endl;
   
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Value of i : 5
Value of i reference : 5
Value of d : 11.7
Value of d reference : 11.7

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

Sr.No Концепция и описание
1 Ссылки как параметры

C ++ поддерживает передачу ссылок в качестве параметра функции более безопасно, чем параметры.

2 Ссылка как возвращаемое значение

Вы можете вернуть ссылку из функции C ++, как и любой другой тип данных.

C ++ поддерживает передачу ссылок в качестве параметра функции более безопасно, чем параметры.

Вы можете вернуть ссылку из функции C ++, как и любой другой тип данных.

C ++ Дата и время

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

Существует четыре связанных с временем типа: clock_t, time_t, size_t и tm . Типы — clock_t, size_t и time_t могут представлять системное время и дату в виде целого числа.

Тип структуры tm содержит дату и время в форме структуры C, имеющей следующие элементы:

struct tm {
   int tm_sec;   // seconds of minutes from 0 to 61
   int tm_min;   // minutes of hour from 0 to 59
   int tm_hour;  // hours of day from 0 to 24
   int tm_mday;  // day of month from 1 to 31
   int tm_mon;   // month of year from 0 to 11
   int tm_year;  // year since 1900
   int tm_wday;  // days since sunday
   int tm_yday;  // days since January 1st
   int tm_isdst; // hours of daylight savings time
}

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

Sr.No Функция и цель
1

time_t time (time_t * время);

Возвращает текущее календарное время системы в количестве секунд, прошедших с 1 января 1970 года. Если у системы нет времени, возвращается .1.

2

char * ctime (const time_t * time);

Возвращает указатель на строку формы день месяц год часы: минуты: секунды год \ n \ 0 .

3

struct tm * localtime (const time_t * time);

Это возвращает указатель на структуру tm, представляющую местное время.

4

clock_t clock (void);

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

5

char * asctime (const struct tm * time);

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

6

struct tm * gmtime (const time_t * time);

Это возвращает указатель на время в виде структуры tm. Время представляется в формате всемирного координированного времени (UTC), которое по сути является средним временем по Гринвичу (GMT).

7

time_t mktime (struct tm * time);

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

8

двойной difftime (time_t time2, time_t time1);

Эта функция вычисляет разницу в секундах между временем1 и временем2.

9

size_t strftime ();

Эта функция может использоваться для форматирования даты и времени в определенном формате.

time_t time (time_t * время);

Возвращает текущее календарное время системы в количестве секунд, прошедших с 1 января 1970 года. Если у системы нет времени, возвращается .1.

char * ctime (const time_t * time);

Возвращает указатель на строку формы день месяц год часы: минуты: секунды год \ n \ 0 .

struct tm * localtime (const time_t * time);

Это возвращает указатель на структуру tm, представляющую местное время.

clock_t clock (void);

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

char * asctime (const struct tm * time);

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

struct tm * gmtime (const time_t * time);

Это возвращает указатель на время в виде структуры tm. Время представляется в формате всемирного координированного времени (UTC), которое по сути является средним временем по Гринвичу (GMT).

time_t mktime (struct tm * time);

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

двойной difftime (time_t time2, time_t time1);

Эта функция вычисляет разницу в секундах между временем1 и временем2.

size_t strftime ();

Эта функция может использоваться для форматирования даты и времени в определенном формате.

Текущая дата и время

Предположим, вы хотите получить текущую системную дату и время либо в виде местного времени, либо в формате всемирного координированного времени (UTC). Ниже приведен пример для достижения того же —

Live Demo

#include <iostream>
#include <ctime>

using namespace std;

int main() {
   // current date/time based on current system
   time_t now = time(0);
   
   // convert now to string form
   char* dt = ctime(&now);

   cout << "The local date and time is: " << dt << endl;

   // convert now to tm struct for UTC
   tm *gmtm = gmtime(&now);
   dt = asctime(gmtm);
   cout << "The UTC date and time is:"<< dt << endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

The local date and time is: Sat Jan  8 20:07:41 2011

The UTC date and time is:Sun Jan  9 03:07:41 2011

Формат времени с использованием struct tm

Структура tm очень важна при работе с датой и временем в C или C ++. Эта структура содержит дату и время в форме структуры C, как упомянуто выше. Большинство функций, связанных со временем, использует структуру tm. Ниже приведен пример, который использует различные функции, связанные с датой и временем, и структуру tm.

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

Live Demo

#include <iostream>
#include <ctime>

using namespace std;

int main() {
   // current date/time based on current system
   time_t now = time(0);

   cout << "Number of sec since January 1,1970:" << now << endl;

   tm *ltm = localtime(&now);

   // print various components of tm structure.
   cout << "Year" << 1970 + ltm->tm_year<<endl;
   cout << "Month: "<< 1 + ltm->tm_mon<< endl;
   cout << "Day: "<<  ltm->tm_mday << endl;
   cout << "Time: "<< 1 + ltm->tm_hour << ":";
   cout << 1 + ltm->tm_min << ":";
   cout << 1 + ltm->tm_sec << endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Number of sec since January 1, 1970:1294548238
Year: 2011
Month: 1
Day: 8
Time: 22: 44:59

C ++ Basic Input / Output

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

C ++ ввод / вывод происходит в потоках, которые представляют собой последовательности байтов. Если байты передаются из устройства, такого как клавиатура, дисковод, сетевое соединение и т. Д., В основную память, это называется операцией ввода, и если байты передаются из основной памяти в устройство, такое как экран дисплея, принтер, дисковод или сетевое соединение и т. д., это называется операцией вывода .

Заголовочные файлы библиотеки ввода / вывода

Существуют следующие заголовочные файлы, важные для программ на C ++:

Sr.No Заголовочный файл, функция и описание
1

<iostream>

Этот файл определяет объекты cin, cout, cerr и clog , которые соответствуют стандартному входному потоку, стандартному выходному потоку, небуферизованному стандартному потоку ошибок и буферизованному стандартному потоку ошибок, соответственно.

2

<iomanip>

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

3

<fstream>

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

<iostream>

Этот файл определяет объекты cin, cout, cerr и clog , которые соответствуют стандартному входному потоку, стандартному выходному потоку, небуферизованному стандартному потоку ошибок и буферизованному стандартному потоку ошибок, соответственно.

<iomanip>

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

<fstream>

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

Стандартный поток вывода (cout)

Предопределенный объект cout является экземпляром класса ostream . Говорят, что объект cout «подключен» к стандартному устройству вывода, которым обычно является экран дисплея. Cout используется вместе с оператором вставки потока, который записывается как <<, что на два знака меньше, чем показано в следующем примере.

Live Demo

#include <iostream>
 
using namespace std;
 
int main() {
   char str[] = "Hello C++";
 
   cout << "Value of str is : " << str << endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Value of str is : Hello C++

Компилятор C ++ также определяет тип данных переменной для вывода и выбирает соответствующий оператор вставки потока для отображения значения. Оператор << перегружен для вывода элементов данных встроенных типов integer, float, double, строк и значений указателей.

Оператор вставки << может использоваться более одного раза в одном выражении, как показано выше, а endl используется для добавления новой строки в конце строки.

Стандартный поток ввода (cin)

Предопределенный объект cin является экземпляром класса istream . Говорят, что объект cin прикреплен к стандартному устройству ввода, которым обычно является клавиатура. Cin используется вместе с оператором извлечения потока, который записывается как >>, что на два больше знака, как показано в следующем примере.

Live Demo

#include <iostream>
 
using namespace std;
 
int main() {
   char name[50];
 
   cout << "Please enter your name: ";
   cin >> name;
   cout << "Your name is: " << name << endl;
 
}

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

Please enter your name: cplusplus
Your name is: cplusplus

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

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

cin >> name >> age;

Это будет эквивалентно следующим двум утверждениям —

cin >> name;
cin >> age;

Стандартный поток ошибок (cerr)

Предопределенный объект cerr является экземпляром класса ostream . Считается, что объект cerr присоединен к стандартному устройству ошибок, которое также является экраном дисплея, но объект cerr не буферизован, и каждая вставка потока в cerr приводит к немедленному отображению его вывода.

Cerr также используется вместе с оператором вставки потока, как показано в следующем примере.

Live Demo

#include <iostream>
 
using namespace std;
 
int main() {
   char str[] = "Unable to read....";
 
   cerr << "Error message : " << str << endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Error message : Unable to read....

Стандартный поток журнала (засорение)

Предопределенный объект clog является экземпляром класса ostream . Говорят, что объект засорения прикреплен к стандартному устройству ошибки, которое также является экраном дисплея, но засорение объекта буферизуется. Это означает, что каждая вставка для засорения может привести к тому, что ее вывод будет храниться в буфере до тех пор, пока буфер не будет заполнен или пока буфер не будет очищен.

Засорение также используется вместе с оператором вставки потока, как показано в следующем примере.

Live Demo

#include <iostream>
 
using namespace std;
 
int main() {
   char str[] = "Unable to read....";
 
   clog << "Error message : " << str << endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Error message : Unable to read....

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

Структуры данных C ++

Массивы C / C ++ позволяют вам определять переменные, которые объединяют несколько элементов данных одного типа, но структура — это другой тип данных, определяемый пользователем, который позволяет комбинировать элементы данных разных типов.

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

  • заглавие
  • автор
  • Предмет
  • ID книги

Определение структуры

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

struct [structure tag] {
   member definition;
   member definition;
   ...
   member definition;
} [one or more structure variables];  

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

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;  

Доступ к членам структуры

Чтобы получить доступ к любому члену структуры, мы используем оператор доступа к члену (.) . Оператор доступа к элементу кодируется как точка между именем структурной переменной и элементом структуры, к которому мы хотим получить доступ. Вы должны использовать ключевое слово struct для определения переменных типа структуры. Ниже приведен пример, объясняющий использование структуры:

Live Demo

#include <iostream>
#include <cstring>
 
using namespace std;
 
struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main() {
   struct Books Book1;        // Declare Book1 of type Book
   struct Books Book2;        // Declare Book2 of type Book
 
   // book 1 specification
   strcpy( Book1.title, "Learn C++ Programming");
   strcpy( Book1.author, "Chand Miyan"); 
   strcpy( Book1.subject, "C++ Programming");
   Book1.book_id = 6495407;

   // book 2 specification
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Yakit Singha");
   strcpy( Book2.subject, "Telecom");
   Book2.book_id = 6495700;
 
   // Print Book1 info
   cout << "Book 1 title : " << Book1.title <<endl;
   cout << "Book 1 author : " << Book1.author <<endl;
   cout << "Book 1 subject : " << Book1.subject <<endl;
   cout << "Book 1 id : " << Book1.book_id <<endl;

   // Print Book2 info
   cout << "Book 2 title : " << Book2.title <<endl;
   cout << "Book 2 author : " << Book2.author <<endl;
   cout << "Book 2 subject : " << Book2.subject <<endl;
   cout << "Book 2 id : " << Book2.book_id <<endl;

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Book 1 title : Learn C++ Programming
Book 1 author : Chand Miyan
Book 1 subject : C++ Programming
Book 1 id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Yakit Singha
Book 2 subject : Telecom
Book 2 id : 6495700

Структуры как аргументы функций

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

Live Demo

#include <iostream>
#include <cstring>
 
using namespace std;
void printBook( struct Books book );

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main() {
   struct Books Book1;        // Declare Book1 of type Book
   struct Books Book2;        // Declare Book2 of type Book
 
   // book 1 specification
   strcpy( Book1.title, "Learn C++ Programming");
   strcpy( Book1.author, "Chand Miyan"); 
   strcpy( Book1.subject, "C++ Programming");
   Book1.book_id = 6495407;

   // book 2 specification
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Yakit Singha");
   strcpy( Book2.subject, "Telecom");
   Book2.book_id = 6495700;
 
   // Print Book1 info
   printBook( Book1 );

   // Print Book2 info
   printBook( Book2 );

   return 0;
}
void printBook( struct Books book ) {
   cout << "Book title : " << book.title <<endl;
   cout << "Book author : " << book.author <<endl;
   cout << "Book subject : " << book.subject <<endl;
   cout << "Book id : " << book.book_id <<endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700

Указатели на структуры

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

struct Books *struct_pointer;

Теперь вы можете сохранить адрес структурной переменной в указанной выше переменной-указателе. Чтобы найти адрес структурной переменной, поместите оператор & перед именем структуры следующим образом:

struct_pointer = &Book1;

Чтобы получить доступ к членам структуры, используя указатель на эту структуру, вы должны использовать оператор -> следующим образом —

struct_pointer->title;

Давайте перепишем приведенный выше пример, используя указатель структуры, надеюсь, вам будет легко понять концепцию —

Live Demo

#include <iostream>
#include <cstring>
 
using namespace std;
void printBook( struct Books *book );

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
int main() {
   struct Books Book1;        // Declare Book1 of type Book
   struct Books Book2;        // Declare Book2 of type Book
 
   // Book 1 specification
   strcpy( Book1.title, "Learn C++ Programming");
   strcpy( Book1.author, "Chand Miyan"); 
   strcpy( Book1.subject, "C++ Programming");
   Book1.book_id = 6495407;

   // Book 2 specification
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Yakit Singha");
   strcpy( Book2.subject, "Telecom");
   Book2.book_id = 6495700;
 
   // Print Book1 info, passing address of structure
   printBook( &Book1 );

   // Print Book1 info, passing address of structure
   printBook( &Book2 );

   return 0;
}

// This function accept pointer to structure as parameter.
void printBook( struct Books *book ) {
   cout << "Book title : " << book->title <<endl;
   cout << "Book author : " << book->author <<endl;
   cout << "Book subject : " << book->subject <<endl;
   cout << "Book id : " << book->book_id <<endl;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700

Ключевое слово typedef

Существует более простой способ определения структур или «псевдонимов», которые вы создаете. Например —

typedef struct {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} Books;

Теперь вы можете напрямую использовать Books для определения переменных типа Books без использования ключевого слова struct. Ниже приведен пример —

Books Book1, Book2;

Вы можете использовать ключевое слово typedef для неструктур, а также:

typedef long int *pint32;
 
pint32 x, y, z;

x, y и z — все указатели на длинные целые.

C ++ Классы и Объекты

Основная цель программирования на C ++ состоит в том, чтобы добавить объектную ориентацию к языку программирования C, а классы — это центральная особенность C ++, которая поддерживает объектно-ориентированное программирование и часто называется пользовательскими типами.

Класс используется для указания формы объекта, и он объединяет представление данных и методы для манипулирования этими данными в одном аккуратном пакете. Данные и функции внутри класса называются членами класса.

Определения класса C ++

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

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

class Box {
   public:
      double length;   // Length of a box
      double breadth;  // Breadth of a box
      double height;   // Height of a box
};

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

Определить объекты C ++

Класс предоставляет чертежи для объектов, поэтому в основном объект создается из класса. Мы объявляем объекты класса точно так же, как мы объявляем переменные базовых типов. Следующие операторы объявляют два объекта класса Box —

Box Box1;          // Declare Box1 of type Box
Box Box2;          // Declare Box2 of type Box

Оба объекта Box1 и Box2 будут иметь собственную копию элементов данных.

Доступ к членам данных

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

Live Demo

#include <iostream>

using namespace std;

class Box {
   public:
      double length;   // Length of a box
      double breadth;  // Breadth of a box
      double height;   // Height of a box
};

int main() {
   Box Box1;        // Declare Box1 of type Box
   Box Box2;        // Declare Box2 of type Box
   double volume = 0.0;     // Store the volume of a box here
 
   // box 1 specification
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;

   // box 2 specification
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
   
   // volume of box 1
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Volume of Box1 : " << volume <<endl;

   // volume of box 2
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Volume of Box2 : " << volume <<endl;
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Volume of Box1 : 210
Volume of Box2 : 1560

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

Классы и объекты в деталях

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

Sr.No Концепция и описание
1 Функции члена класса

Функция-член класса — это функция, которая имеет свое определение или свой прототип в определении класса, как и любая другая переменная.

2 Модификаторы доступа к классу

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

3 Конструктор и деструктор

Конструктор класса — это специальная функция в классе, которая вызывается при создании нового объекта класса. Деструктор также является специальной функцией, которая вызывается при удалении созданного объекта.

4 Копировать конструктор

Конструктор копирования — это конструктор, который создает объект, инициализируя его объектом того же класса, который был создан ранее.

5 Функции друзей

Функция друга допускает полный доступ к закрытым и защищенным членам класса.

6 Встроенные функции

С помощью встроенной функции компилятор пытается развернуть код в теле функции вместо вызова функции.

7 этот указатель

Каждый объект имеет специальный указатель this, который указывает на сам объект.

8 Указатель на классы C ++

Указатель на класс выполняется точно так же, как указатель на структуру. На самом деле класс — это просто структура с функциями в нем.

9 Статические члены класса

И члены-данные, и члены-функции класса могут быть объявлены как статические.

Функция-член класса — это функция, которая имеет свое определение или свой прототип в определении класса, как и любая другая переменная.

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

Конструктор класса — это специальная функция в классе, которая вызывается при создании нового объекта класса. Деструктор также является специальной функцией, которая вызывается при удалении созданного объекта.

Конструктор копирования — это конструктор, который создает объект, инициализируя его объектом того же класса, который был создан ранее.

Функция друга допускает полный доступ к закрытым и защищенным членам класса.

С помощью встроенной функции компилятор пытается развернуть код в теле функции вместо вызова функции.

Каждый объект имеет специальный указатель this, который указывает на сам объект.

Указатель на класс выполняется точно так же, как указатель на структуру. На самом деле класс — это просто структура с функциями в нем.

И члены-данные, и члены-функции класса могут быть объявлены как статические.

C ++ Наследование

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

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

Идея наследования реализует отношения. Например, млекопитающее IS-A животное, собака IS-A млекопитающее, следовательно, собака IS-A животное, а также и так далее.

Базовые и производные классы

Класс может быть производным от нескольких классов, что означает, что он может наследовать данные и функции от нескольких базовых классов. Чтобы определить производный класс, мы используем список деривации классов, чтобы указать базовый класс (ы). Список деривации классов называет один или несколько базовых классов и имеет вид —

class derived-class: access-specifier base-class

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

Рассмотрим базовый класс Shape и его производный класс Rectangle следующим образом:

Live Demo

#include <iostream>
 
using namespace std;

// Base class
class Shape {
   public:
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }
      
   protected:
      int width;
      int height;
};

// Derived class
class Rectangle: public Shape {
   public:
      int getArea() { 
         return (width * height); 
      }
};

int main(void) {
   Rectangle Rect;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total area: 35

Контроль доступа и наследование

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

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

Доступ общественности защищенный частный
Тот же класс да да да
Производные классы да да нет
Вне классов да нет нет

Производный класс наследует все методы базового класса со следующими исключениями:

  • Конструкторы, деструкторы и конструкторы копий базового класса.
  • Перегруженные операторы базового класса.
  • Функции друга базового класса.

Тип наследования

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

Мы почти не используем защищенное или частное наследование, но обычно используется публичное наследование. При использовании другого типа наследования применяются следующие правила:

  • Открытое наследование. При получении класса из открытого базового класса открытые члены базового класса становятся открытыми членами производного класса, а защищенные члены базового класса становятся защищенными членами производного класса. Закрытые члены базового класса никогда не доступны напрямую из производного класса, но могут быть доступны через вызовы открытых и защищенных членов базового класса.

  • Защищенное наследование. При наследовании от защищенного базового класса открытые и защищенные члены базового класса становятся защищенными членами производного класса.

  • Частное наследование. При наследовании от частного базового класса открытые и защищенные члены базового класса становятся частными членами производного класса.

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

Защищенное наследование. При наследовании от защищенного базового класса открытые и защищенные члены базового класса становятся защищенными членами производного класса.

Частное наследование. При наследовании от частного базового класса открытые и защищенные члены базового класса становятся частными членами производного класса.

Множественное наследование

Класс C ++ может наследовать членов от более чем одного класса, и вот расширенный синтаксис —

class derived-class: access baseA, access baseB....

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

Live Demo

#include <iostream>
 
using namespace std;

// Base class Shape
class Shape {
   public:
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }
      
   protected:
      int width;
      int height;
};

// Base class PaintCost
class PaintCost {
   public:
      int getCost(int area) {
         return area * 70;
      }
};

// Derived class
class Rectangle: public Shape, public PaintCost {
   public:
      int getArea() {
         return (width * height); 
      }
};

int main(void) {
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   area = Rect.getArea();
   
   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   // Print the total cost of painting
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total area: 35
Total paint cost: $2450

Перегрузка C ++ (оператор и функция)

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

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

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

Перегрузка функций в C ++

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

Ниже приведен пример, в котором одна и та же функция print () используется для печати разных типов данных:

Live Demo

#include <iostream>
using namespace std;
 
class printData {
   public:
      void print(int i) {
        cout << "Printing int: " << i << endl;
      }
      void print(double  f) {
        cout << "Printing float: " << f << endl;
      }
      void print(char* c) {
        cout << "Printing character: " << c << endl;
      }
};

int main(void) {
   printData pd;
 
   // Call print to print integer
   pd.print(5);
   
   // Call print to print float
   pd.print(500.263);
   
   // Call print to print character
   pd.print("Hello C++");
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Printing int: 5
Printing float: 500.263
Printing character: Hello C++

Перегрузка операторов в C ++

Вы можете переопределить или перегрузить большинство встроенных операторов, доступных в C ++. Таким образом, программист может использовать операторы с пользовательскими типами.

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

Box operator+(const Box&);

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

Box operator+(const Box&, const Box&);

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

Live Demo

#include <iostream>
using namespace std;

class Box {
   public:
      double getVolume(void) {
         return length * breadth * height;
      }
      void setLength( double len ) {
         length = len;
      }
      void setBreadth( double bre ) {
         breadth = bre;
      }
      void setHeight( double hei ) {
         height = hei;
      }
      
      // Overload + operator to add two Box objects.
      Box operator+(const Box& b) {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
      
   private:
      double length;      // Length of a box
      double breadth;     // Breadth of a box
      double height;      // Height of a box
};

// Main function for the program
int main() {
   Box Box1;                // Declare Box1 of type Box
   Box Box2;                // Declare Box2 of type Box
   Box Box3;                // Declare Box3 of type Box
   double volume = 0.0;     // Store the volume of a box here
 
   // box 1 specification
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // box 2 specification
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // volume of box 1
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // volume of box 2
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;

   // Add two object as follows:
   Box3 = Box1 + Box2;

   // volume of box 3
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

Перегружаемый / Non-overloadableOperators

Ниже приведен список операторов, которые могут быть перегружены:

+ * / % ^
& | ~ ! , знак равно
< > <= > = ++
<< >> == знак равно && ||
+ = знак равно знак равно знак равно ^ = знак равно
| = знак равно << = >> = [] ()
-> -> * новый новый [] удалять удалять []

Ниже приведен список операторов, которые не могут быть перегружены —

:: . * , ?:

Примеры перегрузки операторов

Вот несколько примеров перегрузки операторов, которые помогут вам понять концепцию.

Sr.No Операторы и пример
1 Перегрузка унарных операторов
2 Перегрузка бинарных операторов
3 Перегрузка реляционных операторов
4 Перегрузка операторов ввода / вывода
5 ++ и — Перегрузка операторов
6 Перегрузка операторов присваивания
7 Вызов функции () Перегрузка оператора
8 Подписка [] Перегрузка оператора
9 Оператор доступа члена класса -> перегрузка

Полиморфизм в C ++

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

C ++ полиморфизм означает, что вызов функции-члена приведет к выполнению другой функции в зависимости от типа объекта, который вызывает функцию.

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

Live Demo

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
      
   public:
      Shape( int a = 0, int b = 0){
         width = a;
         height = b;
      }
      int area() {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape {
   public:
      Rectangle( int a = 0, int b = 0):Shape(a, b) { }
      
      int area () { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};

class Triangle: public Shape {
   public:
      Triangle( int a = 0, int b = 0):Shape(a, b) { }
      
      int area () { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};

// Main function for the program
int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

   // store the address of Rectangle
   shape = &rec;
   
   // call rectangle area.
   shape->area();

   // store the address of Triangle
   shape = &tri;
   
   // call triangle area.
   shape->area();
   
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Parent class area :
Parent class area :

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

Но теперь давайте внесем небольшую модификацию в нашу программу и предшествуем объявлению area () в классе Shape с ключевым словом virtual, чтобы оно выглядело так:

class Shape {
   protected:
      int width, height;
      
   public:
      Shape( int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      virtual int area() {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

После этой небольшой модификации, когда предыдущий пример кода скомпилирован и выполнен, он дает следующий результат —

Rectangle class area
Triangle class area

На этот раз компилятор просматривает содержимое указателя, а не его тип. Следовательно, поскольку адреса объектов классов tri и rec хранятся в форме *, вызывается соответствующая функция area ().

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

Виртуальная функция

Виртуальная функция — это функция в базовом классе, которая объявлена ​​с использованием ключевого слова virtual . Определение в базовом классе виртуальной функции с другой версией в производном классе сигнализирует компилятору, что нам не нужна статическая связь для этой функции.

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

Чистые виртуальные функции

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

Мы можем изменить виртуальную функцию area () в базовом классе на следующую:

class Shape {
   protected:
      int width, height;

   public:
      Shape(int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      
      // pure virtual function
      virtual int area() = 0;
};

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

Абстракция данных в C ++

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

Абстракция данных — это метод программирования (и проектирования), основанный на разделении интерфейса и реализации.

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

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

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

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

В C ++ мы используем классы для определения наших собственных абстрактных типов данных (ADT). Вы можете использовать объект cout класса ostream для потоковой передачи данных в стандартный вывод, например так:

Live Demo

#include <iostream>
using namespace std;

int main() {
   cout << "Hello C++" <<endl;
   return 0;
}

Здесь вам не нужно понимать, как cout отображает текст на экране пользователя. Вам нужно знать только открытый интерфейс, и базовая реализация cout может быть изменена.

Ярлыки доступа обеспечивают принудительную абстракцию

В C ++ мы используем метки доступа для определения абстрактного интерфейса с классом. Класс может содержать ноль или более меток доступа —

  • Члены, обозначенные общедоступным ярлыком, доступны для всех частей программы. Представление типа абстракции данных определяется его открытыми членами.

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

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

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

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

Преимущества абстракции данных

Абстракция данных обеспечивает два важных преимущества:

  • Внутренние классы защищены от непреднамеренных ошибок на уровне пользователя, которые могут повредить состояние объекта.

  • Реализация класса может со временем развиваться в ответ на изменяющиеся требования или сообщения об ошибках, не требуя изменения в коде пользовательского уровня.

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

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

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

Пример абстракции данных

Любая программа на C ++, где вы реализуете класс с открытыми и закрытыми членами, является примером абстракции данных. Рассмотрим следующий пример —

Live Demo

#include <iostream>
using namespace std;

class Adder {
   public:
      // constructor
      Adder(int i = 0) {
         total = i;
      }
      
      // interface to outside world
      void addNum(int number) {
         total += number;
      }
      
      // interface to outside world
      int getTotal() {
         return total;
      };
      
   private:
      // hidden data from outside world
      int total;
};

int main() {
   Adder a;
   
   a.addNum(10);
   a.addNum(20);
   a.addNum(30);

   cout << "Total " << a.getTotal() <<endl;
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total 60

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

Разработка стратегии

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

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

Инкапсуляция данных в C ++

Все программы на C ++ состоят из следующих двух основных элементов:

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

  • Данные программы. Данные — это информация о программе, на которую влияют функции программы.

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

Данные программы. Данные — это информация о программе, на которую влияют функции программы.

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

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

C ++ поддерживает свойства инкапсуляции и сокрытия данных посредством создания пользовательских типов, называемых классами . Мы уже изучили, что класс может содержать частных, защищенных и открытых членов. По умолчанию все элементы, определенные в классе, являются частными. Например —

class Box {
   public:
      double getVolume(void) {
         return length * breadth * height;
      }

   private:
      double length;      // Length of a box
      double breadth;     // Breadth of a box
      double height;      // Height of a box
};

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

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

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

Пример инкапсуляции данных

Любая программа на C ++, в которой вы реализуете класс с открытыми и закрытыми членами, является примером инкапсуляции данных и абстракции данных. Рассмотрим следующий пример —

Live Demo

#include <iostream>
using namespace std;

class Adder {
   public:
      // constructor
      Adder(int i = 0) {
         total = i;
      }
      
      // interface to outside world
      void addNum(int number) {
         total += number;
      }
      
      // interface to outside world
      int getTotal() {
         return total;
      };
   
   private:
      // hidden data from outside world
      int total;
};

int main() {
   Adder a;
   
   a.addNum(10);
   a.addNum(20);
   a.addNum(30);

   cout << "Total " << a.getTotal() <<endl;
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total 60

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

Разработка стратегии

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

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

Интерфейсы в C ++ (Абстрактные классы)

Интерфейс описывает поведение или возможности класса C ++ без привязки к конкретной реализации этого класса.

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

Класс становится абстрактным, объявляя по крайней мере одну из его функций чисто виртуальной функцией. Чистая виртуальная функция указывается путем помещения «= 0» в ее объявление следующим образом:

class Box {
   public:
      // pure virtual function
      virtual double getVolume() = 0;
      
   private:
      double length;      // Length of a box
      double breadth;     // Breadth of a box
      double height;      // Height of a box
};

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

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

Классы, которые можно использовать для создания объектов, называются конкретными классами .

Пример абстрактного класса

Рассмотрим следующий пример, где родительский класс предоставляет интерфейс к базовому классу для реализации функции с именем getArea ()

Live Demo

#include <iostream>
 
using namespace std;
 
// Base class
class Shape {
   public:
      // pure virtual function providing interface framework.
      virtual int getArea() = 0;
      void setWidth(int w) {
         width = w;
      }
   
      void setHeight(int h) {
         height = h;
      }
   
   protected:
      int width;
      int height;
};
 
// Derived classes
class Rectangle: public Shape {
   public:
      int getArea() { 
         return (width * height); 
      }
};

class Triangle: public Shape {
   public:
      int getArea() { 
         return (width * height)/2; 
      }
};
 
int main(void) {
   Rectangle Rect;
   Triangle  Tri;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
   
   // Print the area of the object.
   cout << "Total Rectangle area: " << Rect.getArea() << endl;

   Tri.setWidth(5);
   Tri.setHeight(7);
   
   // Print the area of the object.
   cout << "Total Triangle area: " << Tri.getArea() << endl; 

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total Rectangle area: 35
Total Triangle area: 17

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

Разработка стратегии

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

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

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

C ++ файлы и потоки

До сих пор мы использовали стандартную библиотеку iostream , которая предоставляет методы cin и cout для чтения из стандартного ввода и записи в стандартный вывод соответственно.

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

Sr.No Тип данных и описание
1

ofstream

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

2

ifstream

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

3

fstream

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

ofstream

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

ifstream

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

fstream

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

Для выполнения обработки файлов в C ++ файлы заголовков <iostream> и <fstream> должны быть включены в исходный файл C ++.

Открытие файла

Файл должен быть открыт перед тем, как вы сможете читать из него или писать в него. Любой объект ofstream или fstream может быть использован для открытия файла для записи. И если поток объекта используется, чтобы открыть файл только для чтения.

Ниже приведен стандартный синтаксис функции open (), которая является членом объектов fstream, ifstream и ofstream.

void open(const char *filename, ios::openmode mode);

Здесь первый аргумент указывает имя и местоположение файла, который нужно открыть, а второй аргумент функции-члена open () определяет режим, в котором файл должен быть открыт.

Sr.No Флаг и описание режима
1

ИОС :: приложение

Добавить режим. Весь вывод в этот файл будет добавлен в конец.

2

ИОС :: ели

Откройте файл для вывода и переместите элемент управления чтения / записи в конец файла.

3

ИОС :: в

Откройте файл для чтения.

4

ИОС :: из

Откройте файл для записи.

5

ИОС :: TRUNC

Если файл уже существует, его содержимое будет обрезано перед открытием файла.

ИОС :: приложение

Добавить режим. Весь вывод в этот файл будет добавлен в конец.

ИОС :: ели

Откройте файл для вывода и переместите элемент управления чтения / записи в конец файла.

ИОС :: в

Откройте файл для чтения.

ИОС :: из

Откройте файл для записи.

ИОС :: TRUNC

Если файл уже существует, его содержимое будет обрезано перед открытием файла.

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

ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );

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

fstream  afile;
afile.open("file.dat", ios::out | ios::in );

Закрытие файла

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

Ниже приведен стандартный синтаксис для функции close (), которая является членом объектов fstream, ifstream и ofstream.

void close();

Запись в файл

При программировании на C ++ вы записываете информацию в файл из вашей программы, используя оператор вставки потока (<<), так же, как вы используете этот оператор для вывода информации на экран. Единственное отличие состоит в том, что вы используете объект ofstream или fstream вместо объекта cout .

Чтение из файла

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

Пример чтения и записи

Ниже приводится программа C ++, которая открывает файл в режиме чтения и записи. После записи информации, введенной пользователем, в файл с именем afile.dat, программа считывает информацию из файла и выводит ее на экран —

Live Demo

#include <fstream>
#include <iostream>
using namespace std;
 
int main () {
   char data[100];

   // open a file in write mode.
   ofstream outfile;
   outfile.open("afile.dat");

   cout << "Writing to the file" << endl;
   cout << "Enter your name: "; 
   cin.getline(data, 100);

   // write inputted data into the file.
   outfile << data << endl;

   cout << "Enter your age: "; 
   cin >> data;
   cin.ignore();
   
   // again write inputted data into the file.
   outfile << data << endl;

   // close the opened file.
   outfile.close();

   // open a file in read mode.
   ifstream infile; 
   infile.open("afile.dat"); 
 
   cout << "Reading from the file" << endl; 
   infile >> data; 

   // write the data at the screen.
   cout << data << endl;
   
   // again read the data from the file and display it.
   infile >> data; 
   cout << data << endl; 

   // close the opened file.
   infile.close();

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он производит следующий пример ввода и вывода —

$./a.out
Writing to the file
Enter your name: Zara
Enter your age: 9
Reading from the file
Zara
9

Приведенные выше примеры используют дополнительные функции из объекта cin, такие как функция getline () для чтения строки извне и функция ignore () для игнорирования дополнительных символов, оставленных предыдущим оператором чтения.

Указатели положения файла

И istream, и ostream предоставляют функции-члены для изменения положения указателя положения файла. Эти функции-члены являются seekg («seek get») для istream и seekp («seek put») для ostream.

Аргумент для поиска и поиска обычно является длинным целым числом. Второй аргумент может быть указан для указания направления поиска. Направление поиска может быть ios :: beg (по умолчанию) для позиционирования относительно начала потока, ios :: cur для позиционирования относительно текущей позиции в потоке или ios :: end для позиционирования относительно конца поток.

Указатель положения файла представляет собой целочисленное значение, которое указывает местоположение в файле в виде количества байтов от начального местоположения файла. Некоторые примеры позиционирования «get» указателя позиции файла:

// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n );

// position n bytes forward in fileObject
fileObject.seekg( n, ios::cur );

// position n bytes back from end of fileObject
fileObject.seekg( n, ios::end );

// position at end of fileObject
fileObject.seekg( 0, ios::end );

Обработка исключений в C ++

Исключением является проблема, возникающая при выполнении программы. Исключение C ++ — это ответ на исключительное обстоятельство, которое возникает во время работы программы, например, попытка деления на ноль.

Исключения предоставляют способ передачи управления из одной части программы в другую. Обработка исключений в C ++ основана на трех ключевых словах: try, catch и throw .

  • throw — программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова throw .

  • catch — программа ловит исключение с помощью обработчика исключений в том месте программы, где вы хотите решить проблему. Ключевое слово catch указывает на перехват исключения.

  • try — блок try идентифицирует блок кода, для которого будут активированы определенные исключения. За ним следует один или несколько блоков улова.

throw — программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова throw .

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

try — блок try идентифицирует блок кода, для которого будут активированы определенные исключения. За ним следует один или несколько блоков улова.

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

try {
   // protected code
} catch( ExceptionName e1 ) {
   // catch block
} catch( ExceptionName e2 ) {
   // catch block
} catch( ExceptionName eN ) {
   // catch block
}

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

Бросать исключения

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

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

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

Ловить исключения

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

try {
   // protected code
} catch( ExceptionName e ) {
  // code to handle ExceptionName exception
}

Выше код будет ловить исключение типа ExceptionName . Если вы хотите указать, что блок catch должен обрабатывать исключение любого типа, которое выдается в блоке try, вы должны поместить многоточие, …, в круглые скобки, содержащие объявление исключения, следующим образом:

try {
   // protected code
} catch(...) {
  // code to handle any exception
}

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

Live Demo

#include <iostream>
using namespace std;

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main () {
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
      z = division(x, y);
      cout << z << endl;
   } catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}

Поскольку мы вызываем исключение типа const char * , поэтому, перехватывая это исключение, мы должны использовать const char * в блоке catch. Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Division by zero condition!

Стандартные исключения C ++

C ++ предоставляет список стандартных исключений, определенных в <exception>, которые мы можем использовать в наших программах. Они расположены в иерархии родительско-дочерних классов, показанной ниже —

C ++ Иерархия исключений

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

Sr.No Исключение и описание
1

станд :: исключение

Исключение и родительский класс из всех стандартных исключений C ++.

2

станд :: bad_alloc

Это может быть брошено новым .

3

станд :: bad_cast

Это может быть брошено при помощи dynamic_cast .

4

станд :: bad_exception

Это полезное устройство для обработки неожиданных исключений в программе на C ++.

5

станд :: bad_typeid

Это может быть брошено typeid .

6

станд :: logic_error

Исключение, которое теоретически можно обнаружить, прочитав код.

7

станд :: domain_error

Это исключение, возникающее при использовании математически неверного домена.

8

станд :: invalid_argument

Это брошено из-за неправильных аргументов.

9

станд :: length_error

Выдается при создании слишком большой строки std ::.

10

станд :: out_of_range

Это может быть сгенерировано методом ‘at’, например, std :: vector и std :: bitset <> :: operator [] ().

11

станд :: runtime_error

Исключение, которое теоретически не может быть обнаружено путем чтения кода.

12

станд :: overflow_error

Это выбрасывается, если происходит математическое переполнение.

13

станд :: range_error

Это происходит, когда вы пытаетесь сохранить значение вне диапазона.

14

станд :: underflow_error

Это выбрасывается, если происходит математический недостаток.

станд :: исключение

Исключение и родительский класс из всех стандартных исключений C ++.

станд :: bad_alloc

Это может быть брошено новым .

станд :: bad_cast

Это может быть брошено при помощи dynamic_cast .

станд :: bad_exception

Это полезное устройство для обработки неожиданных исключений в программе на C ++.

станд :: bad_typeid

Это может быть брошено typeid .

станд :: logic_error

Исключение, которое теоретически можно обнаружить, прочитав код.

станд :: domain_error

Это исключение, возникающее при использовании математически неверного домена.

станд :: invalid_argument

Это брошено из-за неправильных аргументов.

станд :: length_error

Выдается при создании слишком большой строки std ::.

станд :: out_of_range

Это может быть сгенерировано методом ‘at’, например, std :: vector и std :: bitset <> :: operator [] ().

станд :: runtime_error

Исключение, которое теоретически не может быть обнаружено путем чтения кода.

станд :: overflow_error

Это выбрасывается, если происходит математическое переполнение.

станд :: range_error

Это происходит, когда вы пытаетесь сохранить значение вне диапазона.

станд :: underflow_error

Это выбрасывается, если происходит математический недостаток.

Определить новые исключения

Вы можете определять свои собственные исключения, наследуя и переопределяя функциональность класса исключений . Ниже приведен пример, который показывает, как вы можете использовать класс std :: exception для реализации вашего собственного исключения стандартным способом —

Live Demo

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

struct MyException : public exception {
   const char * what () const throw () {
      return "C++ Exception";
   }
};
 
int main() {
   try {
      throw MyException();
   } catch(MyException& e) {
      std::cout << "MyException caught" << std::endl;
      std::cout << e.what() << std::endl;
   } catch(std::exception& e) {
      //Other errors
   }
}

Это даст следующий результат —

MyException caught
C++ Exception

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

C ++ Динамическая Память

Хорошее понимание того, как динамическая память действительно работает в C ++, необходимо для того, чтобы стать хорошим программистом C ++. Память в вашей C ++ программе делится на две части —

  • Стек — все переменные, объявленные внутри функции, будут занимать память из стека.

  • Куча — это неиспользуемая память программы и может использоваться для динамического выделения памяти при запуске программы.

Стек — все переменные, объявленные внутри функции, будут занимать память из стека.

Куча — это неиспользуемая память программы и может использоваться для динамического выделения памяти при запуске программы.

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

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

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

новые и удаленные операторы

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

new data-type;

Здесь тип данных может быть любым встроенным типом данных, включая массив, или любые определенные пользователем типы данных, включая класс или структуру. Давайте начнем со встроенных типов данных. Например, мы можем определить указатель на тип double и затем запросить выделение памяти во время выполнения. Мы можем сделать это используя оператор new со следующими утверждениями:

double* pvalue  = NULL; // Pointer initialized with null
pvalue  = new double;   // Request memory for the variable

Память, возможно, не была распределена успешно, если свободное хранилище было использовано. Поэтому рекомендуется проверять, возвращает ли новый оператор указатель NULL, и предпринимать соответствующие действия, как показано ниже:

double* pvalue  = NULL;
if( !(pvalue  = new double )) {
   cout << "Error: out of memory." <<endl;
   exit(1);
}

Функция malloc () из C все еще существует в C ++, но рекомендуется избегать использования функции malloc (). Основное преимущество new перед malloc () состоит в том, что new не просто выделяет память, он создает объекты, которые являются основной целью C ++.

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

delete pvalue;        // Release memory pointed to by pvalue

Давайте изложим вышеизложенные понятия и сформируем следующий пример, чтобы показать, как работают «new» и «delete»:

Live Demo

#include <iostream>
using namespace std;

int main () {
   double* pvalue  = NULL; // Pointer initialized with null
   pvalue  = new double;   // Request memory for the variable
 
   *pvalue = 29494.99;     // Store value at allocated address
   cout << "Value of pvalue : " << *pvalue << endl;

   delete pvalue;         // free up the memory.

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Value of pvalue : 29495

Динамическое выделение памяти для массивов

Предположим, вы хотите выделить память для массива символов, то есть строки из 20 символов. Используя тот же синтаксис, который мы использовали выше, мы можем динамически распределять память, как показано ниже.

char* pvalue  = NULL;         // Pointer initialized with null
pvalue  = new char[20];       // Request memory for the variable

Чтобы удалить массив, который мы только что создали, выражение будет выглядеть так:

delete [] pvalue;             // Delete array pointed to by pvalue

Следуя аналогичному универсальному синтаксису оператора new, вы можете выделить многомерный массив следующим образом:

double** pvalue  = NULL;      // Pointer initialized with null 
pvalue  = new double [3][4];  // Allocate memory for a 3x4 array 

Однако синтаксис для освобождения памяти для многомерного массива все равно останется таким же, как и выше —

delete [] pvalue;            // Delete array pointed to by pvalue

Динамическое выделение памяти для объектов

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

Live Demo

#include <iostream>
using namespace std;

class Box {
   public:
      Box() { 
         cout << "Constructor called!" <<endl; 
      }
      ~Box() { 
         cout << "Destructor called!" <<endl; 
      }
};
int main() {
   Box* myBoxArray = new Box[4];
   delete [] myBoxArray; // Delete array

   return 0;
}

Если бы вам нужно было выделить массив из четырех объектов Box, конструктор Simple был бы вызван четыре раза, и, аналогично, при удалении этих объектов деструктор также будет вызываться одинаковое количество раз.

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!

Пространства имен в C ++

Рассмотрим ситуацию, когда у нас есть два человека с одним и тем же именем, Зара, в одном классе. Всякий раз, когда нам необходимо их разграничить, нам нужно будет использовать некоторую дополнительную информацию вместе с их названием, например, район, если они живут в другом районе, имя их матери или отца и т. Д.

Такая же ситуация может возникнуть в ваших приложениях C ++. Например, вы можете писать какой-то код, который имеет функцию с именем xyz (), и есть другая доступная библиотека, которая также имеет такую ​​же функцию xyz (). Теперь у компилятора нет возможности узнать, на какую версию функции xyz () вы ссылаетесь в своем коде.

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

Определение пространства имен

Определение пространства имен начинается с ключевого слова namespace, за которым следует имя пространства имен следующим образом:

namespace namespace_name {
   // code declarations
}

Чтобы вызвать версию функции или переменной с поддержкой пространства имен, добавьте (: 🙂 имя пространства имен следующим образом:

name::code;  // code could be variable or function.

Давайте посмотрим, как пространство имен охватывает сущности, включая переменные и функции —

Live Demo

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
}

// second name space
namespace second_space {
   void func() {
      cout << "Inside second_space" << endl;
   }
}

int main () {
   // Calls function from first name space.
   first_space::func();
   
   // Calls function from second name space.
   second_space::func(); 

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Inside first_space
Inside second_space

Директива using

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

Live Demo

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
}

// second name space
namespace second_space {
   void func() {
      cout << "Inside second_space" << endl;
   }
}

using namespace first_space;
int main () {
   // This calls function from first name space.
   func();
   
   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Inside first_space

Директива using может также использоваться для ссылки на определенный элемент в пространстве имен. Например, если единственная часть пространства имен std, которую вы намереваетесь использовать, это cout, вы можете обратиться к ней следующим образом:

using std::cout;

Последующий код может ссылаться на cout, не добавляя пространство имен, но другие элементы в пространстве имен std по- прежнему должны быть явными, как показано ниже:

Live Demo

#include <iostream>
using std::cout;

int main () {
   cout << "std::endl is used with std!" << std::endl;
   
   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

std::endl is used with std!

Имена, введенные в директиве using, подчиняются нормальным правилам области видимости. Имя видно с точки зрения директивы using до конца области, в которой находится директива. Объекты с тем же именем, определенные во внешней области видимости, скрыты.

Несмежные пространства имен

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

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

namespace namespace_name {
   // code declarations
}

Вложенные пространства имен

Пространства имен могут быть вложенными, где вы можете определить одно пространство имен внутри другого пространства имен следующим образом:

namespace namespace_name1 {
   // code declarations
   namespace namespace_name2 {
      // code declarations
   }
}

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

// to access members of namespace_name2
using namespace namespace_name1::namespace_name2;

// to access members of namespace:name1
using namespace namespace_name1;

В вышеприведенных утверждениях, если вы используете namespace_name1, тогда он сделает элементы namespace_name2 доступными в области видимости следующим образом:

Live Demo

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
   
   // second name space
   namespace second_space {
      void func() {
         cout << "Inside second_space" << endl;
      }
   }
}

using namespace first_space::second_space;
int main () {
   // This calls function from second name space.
   func();
   
   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Inside second_space

Шаблоны C ++

Шаблоны являются основой общего программирования, которое включает в себя написание кода способом, независимым от какого-либо конкретного типа.

Шаблон — это план или формула для создания универсального класса или функции. Контейнеры библиотеки, такие как итераторы и алгоритмы, являются примерами общего программирования и были разработаны с использованием шаблонной концепции.

Существует одно определение каждого контейнера, например, вектора , но мы можем определить много разных видов векторов, например, вектор <int> или вектор <string> .

Вы можете использовать шаблоны для определения функций, а также классов, давайте посмотрим, как они работают —

Шаблон функции

Общая форма определения шаблонной функции показана здесь —

template <class type> ret-type func-name(parameter list) {
   // body of function
} 

Здесь type — это имя-заполнитель для типа данных, используемого функцией. Это имя может использоваться в определении функции.

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

Live Demo

#include <iostream>
#include <string>

using namespace std;

template <typename T>
inline T const& Max (T const& a, T const& b) { 
   return a < b ? b:a; 
}

int main () {
   int i = 39;
   int j = 20;
   cout << "Max(i, j): " << Max(i, j) << endl; 

   double f1 = 13.5; 
   double f2 = 20.7; 
   cout << "Max(f1, f2): " << Max(f1, f2) << endl; 

   string s1 = "Hello"; 
   string s2 = "World"; 
   cout << "Max(s1, s2): " << Max(s1, s2) << endl; 

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

Шаблон класса

Так же, как мы можем определять шаблоны функций, мы также можем определять шаблоны классов. Общая форма объявления универсального класса показана здесь —

template <class type> class class-name {
   .
   .
   .
}

Здесь type — это имя типа заполнителя, которое будет указано при создании экземпляра класса. Вы можете определить более одного общего типа данных, используя список через запятую.

Ниже приведен пример определения класса Stack <> и реализации универсальных методов для выталкивания и извлечения элементов из стека.

Live Demo

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>

using namespace std;

template <class T>
class Stack { 
   private: 
      vector<T> elems;    // elements 

   public: 
      void push(T const&);  // push element 
      void pop();               // pop element 
      T top() const;            // return top element 
      
      bool empty() const {      // return true if empty.
         return elems.empty(); 
      } 
}; 

template <class T>
void Stack<T>::push (T const& elem) { 
   // append copy of passed element 
   elems.push_back(elem);    
} 

template <class T>
void Stack<T>::pop () { 
   if (elems.empty()) { 
      throw out_of_range("Stack<>::pop(): empty stack"); 
   }
   
   // remove last element 
   elems.pop_back();         
} 

template <class T>
T Stack<T>::top () const { 
   if (elems.empty()) { 
      throw out_of_range("Stack<>::top(): empty stack"); 
   }
   
   // return copy of last element 
   return elems.back();      
} 

int main() { 
   try {
      Stack<int>         intStack;  // stack of ints 
      Stack<string> stringStack;    // stack of strings 

      // manipulate int stack 
      intStack.push(7); 
      cout << intStack.top() <<endl; 

      // manipulate string stack 
      stringStack.push("hello"); 
      cout << stringStack.top() << std::endl; 
      stringStack.pop(); 
      stringStack.pop(); 
   } catch (exception const& ex) { 
      cerr << "Exception: " << ex.what() <<endl; 
      return -1;
   } 
} 

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

7
hello
Exception: Stack<>::pop(): empty stack

Препроцессор C ++

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

Все директивы препроцессора начинаются с #, и перед директивой препроцессора в строке могут появляться только символы пробела. Директивы препроцессора не являются операторами C ++, поэтому они не заканчиваются точкой с запятой (;).

Вы уже видели директиву #include во всех примерах. Этот макрос используется для включения заголовочного файла в исходный файл.

Существует ряд директив препроцессора, поддерживаемых C ++, таких как #include, #define, #if, #else, #line и т. Д. Давайте рассмотрим важные директивы —

Препроцессор #define

Директива препроцессора #define создает символические константы. Символическая константа называется макросом, а общая форма директивы —

#define macro-name replacement-text 

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

#include <iostream>
using namespace std;

#define PI 3.14159

int main () {
   cout << "Value of PI :" << PI << endl; 

   return 0;
}

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

$gcc -E test.cpp > test.p

...
int main () {
   cout << "Value of PI :" << 3.14159 << endl; 
   return 0;
}

Функциональные макросы

Вы можете использовать #define для определения макроса, который будет принимать аргумент следующим образом:

Live Demo

#include <iostream>
using namespace std;

#define MIN(a,b) (((a)<(b)) ? a : b)

int main () {
   int i, j;
   
   i = 100;
   j = 30;
   
   cout <<"The minimum is " << MIN(i, j) << endl;

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

The minimum is 30

Условная компиляция

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

Условная конструкция препроцессора очень похожа на структуру выбора «если». Рассмотрим следующий код препроцессора —

#ifndef NULL
   #define NULL 0
#endif

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

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;
#endif

Это приводит к тому, что оператор cerr компилируется в программе, если символическая константа DEBUG была определена перед директивой #ifdef DEBUG. Вы можете использовать отметку #if 0, чтобы закомментировать часть программы следующим образом:

#if 0
   code prevented from compiling
#endif

Давайте попробуем следующий пример —

Live Demo

#include <iostream>
using namespace std;
#define DEBUG

#define MIN(a,b) (((a)<(b)) ? a : b)

int main () {
   int i, j;
   
   i = 100;
   j = 30;

#ifdef DEBUG
   cerr <<"Trace: Inside main function" << endl;
#endif

#if 0
   /* This is commented part */
   cout << MKSTR(HELLO C++) << endl;
#endif

   cout <<"The minimum is " << MIN(i, j) << endl;

#ifdef DEBUG
   cerr <<"Trace: Coming out of main function" << endl;
#endif

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

The minimum is 30
Trace: Inside main function
Trace: Coming out of main function

Операторы # и ##

Операторы препроцессора # и ## доступны в C ++ и ANSI / ISO C. Оператор # вызывает преобразование текстового токена замены в строку, заключенную в кавычки.

Рассмотрим следующее определение макроса —

Live Demo

#include <iostream>
using namespace std;

#define MKSTR( x ) #x

int main () {

   cout << MKSTR(HELLO C++) << endl;

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

HELLO C++

Давайте посмотрим, как это работает. Просто понять, что препроцессор C ++ переворачивает черту —

cout << MKSTR(HELLO C++) << endl;

Выше линия будет превращена в следующую строку —

cout << "HELLO C++" << endl;

Оператор ## используется для объединения двух токенов. Вот пример —

#define CONCAT( x, y )  x ## y

Когда в программе появляется CONCAT, его аргументы объединяются и используются для замены макроса. Например, CONCAT (HELLO, C ++) заменяется на «HELLO C ++» в программе следующим образом.

Live Demo

#include <iostream>
using namespace std;

#define concat(a, b) a ## b
int main() {
   int xy = 100;
   
   cout << concat(x, y);
   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

100

Давайте посмотрим, как это работает. Легко понять, что препроцессор C ++ преобразует —

cout << concat(x, y);

Выше строка будет преобразована в следующую строку —

cout << xy;

Предопределенные макросы C ++

C ++ предоставляет ряд предопределенных макросов, упомянутых ниже —

Sr.No Макрос и описание
1

__ЛИНИЯ__

Он содержит номер текущей строки программы, когда она компилируется.

2

__ФАЙЛ__

Это содержит текущее имя файла программы, когда это компилируется.

3

__ДАТА__

Он содержит строку вида месяц / день / год, которая является датой перевода исходного файла в объектный код.

4

__ВРЕМЯ__

Он содержит строку вида час: минута: секунда, которая является временем компиляции программы.

__ЛИНИЯ__

Он содержит номер текущей строки программы, когда она компилируется.

__ФАЙЛ__

Это содержит текущее имя файла программы, когда это компилируется.

__ДАТА__

Он содержит строку вида месяц / день / год, которая является датой перевода исходного файла в объектный код.

__ВРЕМЯ__

Он содержит строку вида час: минута: секунда, которая является временем компиляции программы.

Давайте посмотрим пример для всех вышеупомянутых макросов —

Live Demo

#include <iostream>
using namespace std;

int main () {
   cout << "Value of __LINE__ : " << __LINE__ << endl;
   cout << "Value of __FILE__ : " << __FILE__ << endl;
   cout << "Value of __DATE__ : " << __DATE__ << endl;
   cout << "Value of __TIME__ : " << __TIME__ << endl;

   return 0;
}

Если мы скомпилируем и запустим приведенный выше код, это даст следующий результат —

Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48

C ++ Обработка сигналов

Сигналы — это прерывания, доставляемые процессу операционной системой, которые могут преждевременно завершить программу. Вы можете генерировать прерывания, нажав Ctrl + C в системах UNIX, LINUX, Mac OS X или Windows.

Есть сигналы, которые не могут быть перехвачены программой, но есть следующий список сигналов, которые вы можете поймать в своей программе и которые могут предпринять соответствующие действия на основе сигнала. Эти сигналы определены в заголовочном файле C ++ <csignal>.

Sr.No Сигнал и описание
1

SIGABRT

Аварийное завершение программы, например, вызов для прерывания .

2

SIGFPE

Ошибочная арифметическая операция, такая как деление на ноль или операция, приводящая к переполнению.

3

SIGILL

Обнаружение незаконной инструкции.

4

SIGINT

Получение интерактивного сигнала внимания.

5

SIGSEGV

Неверный доступ к хранилищу.

6

SIGTERM

Запрос на прекращение отправлен в программу.

SIGABRT

Аварийное завершение программы, например, вызов для прерывания .

SIGFPE

Ошибочная арифметическая операция, такая как деление на ноль или операция, приводящая к переполнению.

SIGILL

Обнаружение незаконной инструкции.

SIGINT

Получение интерактивного сигнала внимания.

SIGSEGV

Неверный доступ к хранилищу.

SIGTERM

Запрос на прекращение отправлен в программу.

Функция сигнала ()

C ++ библиотека обработки сигналов предоставляет сигнал функции для перехвата неожиданных событий. Ниже приводится синтаксис функции signal ():

void (*signal (int sig, void (*func)(int)))(int); 

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

Напишем простую программу на C ++, где мы будем ловить сигнал SIGINT с помощью функции signal (). Какой бы сигнал вы ни хотели поймать в своей программе, вы должны зарегистрировать этот сигнал, используя функцию сигнала, и связать его с обработчиком сигнала. Изучите следующий пример —

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler( int signum ) {
   cout << "Interrupt signal (" << signum << ") received.\n";

   // cleanup and close up stuff here  
   // terminate program  

   exit(signum);  
}

int main () {
   // register signal SIGINT and signal handler  
   signal(SIGINT, signalHandler);  

   while(1) {
      cout << "Going to sleep...." << endl;
      sleep(1);
   }

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Going to sleep....
Going to sleep....
Going to sleep....

Теперь нажмите Ctrl + c, чтобы прервать программу, и вы увидите, что ваша программа поймает сигнал и выйдет, напечатав что-то следующим образом:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

Функция повышения ()

Вы можете генерировать сигналы с помощью функции lift () , которая принимает целочисленный номер сигнала в качестве аргумента и имеет следующий синтаксис.

int raise (signal sig);

Здесь sig — это номер сигнала для отправки любого из сигналов: SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP. Ниже приведен пример, где мы поднимаем сигнал внутренне, используя функцию поднимать () следующим образом:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler( int signum ) {
   cout << "Interrupt signal (" << signum << ") received.\n";

   // cleanup and close up stuff here  
   // terminate program  

   exit(signum);  
}

int main () {
   int i = 0;
   // register signal SIGINT and signal handler  
   signal(SIGINT, signalHandler);  

   while(++i) {
      cout << "Going to sleep...." << endl;
      if( i == 3 ) {
         raise( SIGINT);
      }
      sleep(1);
   }

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он выдает следующий результат и будет автоматически получен:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

C ++ Многопоточность

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

Многозадачность на основе процессов обрабатывает параллельное выполнение программ. Многозадачность на основе потоков имеет дело с параллельным выполнением частей одной и той же программы.

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

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

В этом руководстве предполагается, что вы работаете в ОС Linux, и мы собираемся написать многопоточную программу на C ++ с использованием POSIX. POSIX Threads, или Pthreads, предоставляет API, который доступен во многих Unix-подобных системах POSIX, таких как FreeBSD, NetBSD, GNU / Linux, Mac OS X и Solaris.

Создание тем

Следующая процедура используется для создания потока POSIX —

#include <pthread.h>
pthread_create (thread, attr, start_routine, arg) 

Здесь pthread_create создает новый поток и делает его исполняемым. Эта процедура может вызываться любое количество раз из любого места в вашем коде. Вот описание параметров —

Sr.No Параметр и описание
1

нить

Непрозрачный уникальный идентификатор для нового потока, возвращаемого подпрограммой.

2

атр

Непрозрачный объект атрибута, который можно использовать для установки атрибутов потока. Вы можете указать объект атрибутов потока или NULL для значений по умолчанию.

3

start_routine

Подпрограмма C ++, которую поток выполнит, как только он будет создан.

4

Arg

Единственный аргумент, который может быть передан start_routine. Он должен быть передан по ссылке как приведение указателя типа void. NULL может использоваться, если аргумент не передается.

нить

Непрозрачный уникальный идентификатор для нового потока, возвращаемого подпрограммой.

атр

Непрозрачный объект атрибута, который можно использовать для установки атрибутов потока. Вы можете указать объект атрибутов потока или NULL для значений по умолчанию.

start_routine

Подпрограмма C ++, которую поток выполнит, как только он будет создан.

Arg

Единственный аргумент, который может быть передан start_routine. Он должен быть передан по ссылке как приведение указателя типа void. NULL может использоваться, если аргумент не передается.

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

Завершающие Темы

Существует следующая процедура, которую мы используем для завершения потока POSIX —

#include <pthread.h>
pthread_exit (status) 

Здесь pthread_exit используется для явного выхода из потока. Как правило, процедура pthread_exit () вызывается после того, как поток завершил свою работу и больше не требуется для существования.

Если main () завершает работу перед созданными потоками и завершается с помощью pthread_exit (), другие потоки продолжат выполняться. В противном случае они будут автоматически завершены, когда main () завершит работу.

пример

Этот простой пример кода создает 5 потоков с помощью процедуры pthread_create (). Каждый поток печатает «Hello World!» сообщение, а затем завершается вызовом pthread_exit ().

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

void *PrintHello(void *threadid) {
   long tid;
   tid = (long)threadid;
   cout << "Hello World! Thread ID, " << tid << endl;
   pthread_exit(NULL);
}

int main () {
   pthread_t threads[NUM_THREADS];
   int rc;
   int i;
   
   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Скомпилируйте следующую программу, используя библиотеку -lpthread, следующим образом:

$gcc test.cpp -lpthread

Теперь выполните вашу программу, которая дает следующий вывод —

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4

Передача аргументов в потоки

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

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

struct thread_data {
   int  thread_id;
   char *message;
};

void *PrintHello(void *threadarg) {
   struct thread_data *my_data;
   my_data = (struct thread_data *) threadarg;

   cout << "Thread ID : " << my_data->thread_id ;
   cout << " Message : " << my_data->message << endl;

   pthread_exit(NULL);
}

int main () {
   pthread_t threads[NUM_THREADS];
   struct thread_data td[NUM_THREADS];
   int rc;
   int i;

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout <<"main() : creating thread, " << i << endl;
      td[i].thread_id = i;
      td[i].message = "This is message";
      rc = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]);
      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message

Присоединение и отсоединение потоков

Существуют следующие две процедуры, которые мы можем использовать для присоединения или отсоединения потоков:

pthread_join (threadid, status) 
pthread_detach (threadid) 

Подпрограмма pthread_join () блокирует вызывающий поток до тех пор, пока указанный поток ‘threadid’ не завершится. Когда поток создается, один из его атрибутов определяет, является ли он присоединяемым или отсоединенным. Только потоки, созданные как присоединяемые, могут быть присоединены. Если поток создается как отдельный, он никогда не может быть присоединен.

В этом примере показано, как ожидать завершения потока с помощью процедуры соединения Pthread.

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS 5

void *wait(void *t) {
   int i;
   long tid;

   tid = (long)t;

   sleep(1);
   cout << "Sleeping in thread " << endl;
   cout << "Thread with id : " << tid << "  ...exiting " << endl;
   pthread_exit(NULL);
}

int main () {
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // Initialize and set thread joinable
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], &attr, wait, (void *)i );

      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // free attribute and wait for the other threads
   pthread_attr_destroy(&attr);
   for( i = 0; i < NUM_THREADS; i++ ) {
      rc = pthread_join(threads[i], &status);
      if (rc) {
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0  exiting with status :0
Main: completed thread id :1  exiting with status :0
Main: completed thread id :2  exiting with status :0
Main: completed thread id :3  exiting with status :0
Main: completed thread id :4  exiting with status :0
Main: program exiting.

Веб-программирование на C ++

Что такое CGI?

  • Common Gateway Interface, или CGI, представляет собой набор стандартов, определяющих, как происходит обмен информацией между веб-сервером и пользовательским сценарием.

  • Спецификации CGI в настоящее время поддерживаются NCSA, и NCSA определяет CGI следующим образом:

  • Common Gateway Interface, или CGI, является стандартом для внешних программ-шлюзов для взаимодействия с информационными серверами, такими как HTTP-серверы.

  • Текущая версия — CGI / 1.1, а CGI / 1.2 находится в стадии разработки.

Common Gateway Interface, или CGI, представляет собой набор стандартов, определяющих, как происходит обмен информацией между веб-сервером и пользовательским сценарием.

Спецификации CGI в настоящее время поддерживаются NCSA, и NCSA определяет CGI следующим образом:

Common Gateway Interface, или CGI, является стандартом для внешних программ-шлюзов для взаимодействия с информационными серверами, такими как HTTP-серверы.

Текущая версия — CGI / 1.1, а CGI / 1.2 находится в стадии разработки.

Просмотр веб-страниц

Чтобы понять концепцию CGI, давайте посмотрим, что происходит, когда мы нажимаем гиперссылку для просмотра определенной веб-страницы или URL-адреса.

  • Ваш браузер связывается с веб-сервером HTTP и запрашивает URL, т.е. имя файла.

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

  • Веб-браузер принимает ответ от веб-сервера и отображает полученный файл или сообщение об ошибке на основе полученного ответа.

Ваш браузер связывается с веб-сервером HTTP и запрашивает URL, т.е. имя файла.

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

Веб-браузер принимает ответ от веб-сервера и отображает полученный файл или сообщение об ошибке на основе полученного ответа.

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

Common Gateway Interface (CGI) — это стандартный протокол, позволяющий приложениям (называемым CGI-программами или CGI-скриптами) взаимодействовать с веб-серверами и клиентами. Эти CGI-программы могут быть написаны на Python, PERL, Shell, C или C ++ и т. Д.

Диаграмма архитектуры CGI

Следующая простая программа показывает простую архитектуру CGI —

CGI Архитектура

Конфигурация веб-сервера

Прежде чем приступить к программированию CGI, убедитесь, что ваш веб-сервер поддерживает CGI и настроен на обработку программ CGI. Все программы CGI, которые должны выполняться сервером HTTP, хранятся в предварительно настроенном каталоге. Этот каталог называется CGI-каталогом и по соглашению называется / var / www / cgi-bin. По соглашению CGI-файлы будут иметь расширение .cgi , хотя они исполняемые C ++.

По умолчанию веб-сервер Apache настроен для запуска программ CGI в / var / www / cgi-bin. Если вы хотите указать любой другой каталог для запуска ваших CGI-скриптов, вы можете изменить следующий раздел в файле httpd.conf —

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>
 
<Directory "/var/www/cgi-bin">
   Options All
</Directory>

Здесь я предполагаю, что у вас есть веб-сервер, запущенный и работающий успешно, и вы можете запустить любую другую программу CGI, такую ​​как Perl или Shell и т. Д.

Первая программа CGI

Рассмотрим следующее содержание программы на C ++ —

#include <iostream>
using namespace std;

int main () {
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Hello World - First CGI Program</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<h2>Hello World! This is my first CGI program</h2>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Скомпилируйте приведенный выше код и назовите исполняемый файл как cplusplus.cgi. Этот файл хранится в каталоге / var / www / cgi-bin и имеет следующий контент. Перед запуском программы CGI убедитесь, что у вас есть режим изменения файла, используя команду UNIX chmod 755 cplusplus.cgi, чтобы сделать файл исполняемым.

Моя первая CGI программа

Вышеприведенная программа на C ++ представляет собой простую программу, которая записывает свои выходные данные в файл STDOUT, т.е. на экран. Существует одна важная и дополнительная функция, которая заключается в печати первой строки Content-type: text / html \ r \ n \ r \ n . Эта строка отправляется обратно в браузер и указывает тип контента, который будет отображаться на экране браузера. Теперь вы, должно быть, поняли основную концепцию CGI и можете написать множество сложных CGI-программ на Python. Программа C ++ CGI может взаимодействовать с любой другой внешней системой, такой как СУБД, для обмена информацией.

Заголовок HTTP

Строка Content-type: text / html \ r \ n \ r \ n является частью заголовка HTTP, который отправляется браузеру для понимания содержимого. Весь заголовок HTTP будет в следующей форме —

HTTP Field Name: Field Content
 
For Example
Content-type: text/html\r\n\r\n

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

Sr.No Заголовок и описание
1

Тип содержимого:

Строка MIME, определяющая формат возвращаемого файла. Примером является Content-type: text / html.

2

Истекает: Дата

Дата, когда информация становится недействительной. Это должно использоваться браузером, чтобы решить, когда страница должна быть обновлена. Допустимая строка даты должна быть в формате 01 января 1998 12:00:00 по Гринвичу.

3

Расположение: URL

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

4

Последнее изменение: Дата

Дата последней модификации ресурса.

5

Длина содержимого: N

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

6

Набор Cookie: Строка

Установите cookie, пропущенный через строку .

Тип содержимого:

Строка MIME, определяющая формат возвращаемого файла. Примером является Content-type: text / html.

Истекает: Дата

Дата, когда информация становится недействительной. Это должно использоваться браузером, чтобы решить, когда страница должна быть обновлена. Допустимая строка даты должна быть в формате 01 января 1998 12:00:00 по Гринвичу.

Расположение: URL

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

Последнее изменение: Дата

Дата последней модификации ресурса.

Длина содержимого: N

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

Набор Cookie: Строка

Установите cookie, пропущенный через строку .

Переменные среды CGI

Все программы CGI будут иметь доступ к следующим переменным среды. Эти переменные играют важную роль при написании любой CGI-программы.

Sr.No Имя и описание переменной
1

ТИП СОДЕРЖИМОГО

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

2

CONTENT_LENGTH

Длина информации запроса, которая доступна только для запросов POST.

3

HTTP_COOKIE

Возвращает установленные куки в виде пары ключ-значение.

4

HTTP_USER_AGENT

Поле заголовка запроса User-Agent содержит информацию о пользовательском агенте, создавшем запрос. Это имя веб-браузера.

5

PATH_INFO

Путь для скрипта CGI.

6

СТРОКА ЗАПРОСА

Информация в кодировке URL, отправляемая с запросом метода GET.

7

REMOTE_ADDR

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

8

УДАЛЕННЫЙ УЗЕЛ

Полное имя хоста, сделавшего запрос. Если эта информация недоступна, тогда REMOTE_ADDR может использоваться для получения IR-адреса.

9

REQUEST_METHOD

Метод, использованный для запроса. Наиболее распространенными методами являются GET и POST.

10

SCRIPT_FILENAME

Полный путь к скрипту CGI.

11

SCRIPT_NAME

Название скрипта CGI.

12

НАЗВАНИЕ СЕРВЕРА

Имя хоста или IP-адрес сервера.

13

SERVER_SOFTWARE

Название и версия программного обеспечения, на котором работает сервер.

ТИП СОДЕРЖИМОГО

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

CONTENT_LENGTH

Длина информации запроса, которая доступна только для запросов POST.

HTTP_COOKIE

Возвращает установленные куки в виде пары ключ-значение.

HTTP_USER_AGENT

Поле заголовка запроса User-Agent содержит информацию о пользовательском агенте, создавшем запрос. Это имя веб-браузера.

PATH_INFO

Путь для скрипта CGI.

СТРОКА ЗАПРОСА

Информация в кодировке URL, отправляемая с запросом метода GET.

REMOTE_ADDR

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

УДАЛЕННЫЙ УЗЕЛ

Полное имя хоста, сделавшего запрос. Если эта информация недоступна, тогда REMOTE_ADDR может использоваться для получения IR-адреса.

REQUEST_METHOD

Метод, использованный для запроса. Наиболее распространенными методами являются GET и POST.

SCRIPT_FILENAME

Полный путь к скрипту CGI.

SCRIPT_NAME

Название скрипта CGI.

НАЗВАНИЕ СЕРВЕРА

Имя хоста или IP-адрес сервера.

SERVER_SOFTWARE

Название и версия программного обеспечения, на котором работает сервер.

Вот небольшая программа CGI, чтобы перечислить все переменные CGI.

#include <iostream>
#include <stdlib.h>
using namespace std;

const string ENV[ 24 ] = {
   "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",   
   "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",             
   "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",         
   "HTTP_HOST", "HTTP_USER_AGENT", "PATH",            
   "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",      
   "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
   "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",      
   "SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",     
   "SERVER_SIGNATURE","SERVER_SOFTWARE" };   

int main () {
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI Environment Variables</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<table border = \"0\" cellspacing = \"2\">";

   for ( int i = 0; i < 24; i++ ) {
      cout << "<tr><td>" << ENV[ i ] << "</td><td>";
      
      // attempt to retrieve value of environment variable
      char *value = getenv( ENV[ i ].c_str() );  
      if ( value != 0 ) {
         cout << value;                                 
      } else {
         cout << "Environment variable does not exist.";
      }
      cout << "</td></tr>\n";
   }
   
   cout << "</table><\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

C ++ CGI Library

Для реальных примеров вам потребуется выполнить много операций в вашей CGI-программе. Существует библиотека CGI, написанная для программы C ++, которую вы можете скачать с ftp://ftp.gnu.org/gnu/cgicc/ и выполнить шаги по установке библиотеки —

$tar xzf cgicc-X.X.X.tar.gz 
$cd cgicc-X.X.X/ 
$./configure --prefix=/usr 
$make
$make install

Вы можете проверить соответствующую документацию, доступную на C ++ CGI Lib Documentation .

GET и POST методы

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

Передача информации с использованием метода GET

Метод GET отправляет закодированную информацию пользователя, добавленную к запросу страницы. Страница и закодированная информация разделены знаком? персонаж следующим образом —

http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2

Метод GET является методом по умолчанию для передачи информации из браузера на веб-сервер, и он создает длинную строку, которая появляется в поле «Местоположение:» вашего браузера. Никогда не используйте метод GET, если у вас есть пароль или другая конфиденциальная информация для передачи на сервер. Метод GET имеет ограничение по размеру, и вы можете передать до 1024 символов в строке запроса.

При использовании метода GET информация передается с использованием http-заголовка QUERY_STRING и будет доступна в вашей программе CGI через переменную среды QUERY_STRING.

Вы можете передавать информацию, просто объединяя пары ключ-значение с любым URL-адресом или используя HTML-теги <FORM> для передачи информации, используя метод GET.

Пример простого URL: метод Get

Вот простой URL, который передаст два значения программе hello_get.py с помощью метода GET.

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

Ниже приведена программа для создания CGI-программы cpp_get.cgi для обработки входных данных, данных веб-браузером. Мы собираемся использовать библиотеку C ++ CGI, которая упрощает доступ к передаваемой информации —

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>  

using namespace std;
using namespace cgicc;

int main () {
   Cgicc formData;
   
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Using GET and POST Methods</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("first_name");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "First name: " << **fi << endl;  
   } else {
      cout << "No text entered for first name" << endl;  
   }
   
   cout << "<br/>\n";
   fi = formData.getElement("last_name");  
   if( !fi->isEmpty() &&fi != (*formData).end()) {  
      cout << "Last name: " << **fi << endl;  
   } else {
      cout << "No text entered for last name" << endl;  
   }
   
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Теперь скомпилируйте вышеуказанную программу следующим образом:

$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

Сгенерируйте cpp_get.cgi и поместите его в каталог CGI и попробуйте получить доступ по следующей ссылке —

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

Это приведет к следующему результату —

First name: ZARA 
Last name: ALI 

Пример простой формы: метод GET

Вот простой пример, который передает два значения, используя HTML FORM и кнопку отправки. Мы будем использовать тот же сценарий CGI cpp_get.cgi для обработки этого ввода.

<form action = "/cgi-bin/cpp_get.cgi" method = "get">
   First Name: <input type = "text" name = "first_name">  <br />
 
   Last Name: <input type = "text" name = "last_name" />
   <input type = "submit" value = "Submit" />
</form>

Вот фактический результат вышеприведенной формы. Вы вводите имя и фамилию, а затем нажимаете кнопку «Отправить», чтобы увидеть результат.

Имя: Фамилия:

Передача информации с использованием метода POST

Обычно более надежным методом передачи информации в CGI-программу является метод POST. Это упаковывает информацию точно так же, как методы GET, но вместо отправки ее в виде текстовой строки после символа? в URL он отправляет его как отдельное сообщение. Это сообщение поступает в CGI-скрипт в виде стандартного ввода.

Та же самая программа cpp_get.cgi также будет обрабатывать метод POST. Давайте возьмем тот же пример, что и выше, который передает два значения, используя HTML FORM и кнопку submit, но на этот раз с методом POST следующим образом:

<form action = "/cgi-bin/cpp_get.cgi" method = "post">
   First Name: <input type = "text" name = "first_name"><br />
   Last Name: <input type = "text" name = "last_name" />
 
   <input type = "submit" value = "Submit" />
</form>

Вот фактический результат вышеприведенной формы. Вы вводите имя и фамилию, а затем нажимаете кнопку «Отправить», чтобы увидеть результат.

Имя: Фамилия:

Передача данных флажка в программу CGI

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

Вот пример HTML-кода для формы с двумя флажками —

<form action = "/cgi-bin/cpp_checkbox.cgi" method = "POST" target = "_blank">
   <input type = "checkbox" name = "maths" value = "on" /> Maths
   <input type = "checkbox" name = "physics" value = "on" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

Результатом этого кода является следующая форма —

математика физика

Ниже приведена программа на C ++, которая сгенерирует скрипт cpp_checkbox.cgi для обработки входных данных, данных веб-браузером с помощью кнопки-флажка.

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main () {
   Cgicc formData;
   bool maths_flag, physics_flag;

   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Checkbox Data to CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   maths_flag = formData.queryCheckbox("maths");
   if( maths_flag ) {  
      cout << "Maths Flag: ON " << endl;  
   } else {
      cout << "Maths Flag: OFF " << endl;  
   }
   cout << "<br/>\n";

   physics_flag = formData.queryCheckbox("physics");
   if( physics_flag ) {  
      cout << "Physics Flag: ON " << endl;  
   } else {
      cout << "Physics Flag: OFF " << endl;  
   }
   
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Передача данных переключателей в программу CGI

Радиокнопки используются, когда требуется выбрать только одну опцию.

Вот пример HTML-кода для формы с двумя переключателями —

<form action = "/cgi-bin/cpp_radiobutton.cgi" method = "post" target = "_blank">
   <input type = "radio" name = "subject" value = "maths" checked = "checked"/> Maths 
   <input type = "radio" name = "subject" value = "physics" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

Результатом этого кода является следующая форма —

математика физика

Ниже приведена программа на C ++, которая сгенерирует скрипт cpp_radiobutton.cgi для обработки ввода, передаваемого веб-браузером через переключатели.

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main () {
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Radio Button Data to CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("subject");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Radio box selected: " << **fi << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Передача данных текстовой области в программу CGI

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

Вот пример HTML-кода для формы с полем TEXTAREA —

<form action = "/cgi-bin/cpp_textarea.cgi" method = "post" target = "_blank">
   <textarea name = "textcontent" cols = "40" rows = "4">
      Type your text here...
   </textarea>
   <input type = "submit" value = "Submit" />
</form>

Результатом этого кода является следующая форма —

Ниже приведена программа на C ++, которая сгенерирует скрипт cpp_textarea.cgi для обработки ввода, получаемого веб-браузером через текстовую область.

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main () {
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Text Area Data to CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("textcontent");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Text Content: " << **fi << endl;  
   } else {
      cout << "No text entered" << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Передача выпадающих данных в программу CGI

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

Вот пример HTML-кода для формы с одним выпадающим списком —

<form action = "/cgi-bin/cpp_dropdown.cgi" method = "post" target = "_blank">
   <select name = "dropdown">
      <option value = "Maths" selected>Maths</option>
      <option value = "Physics">Physics</option>
   </select>
   
   <input type = "submit" value = "Submit"/>
</form>

Результатом этого кода является следующая форма —

Ниже приведена программа на C ++, которая сгенерирует скрипт cpp_dropdown.cgi для обработки входных данных, предоставленных веб-браузером через раскрывающийся список.

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main () {
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Drop Down Box Data to CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   form_iterator fi = formData.getElement("dropdown");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Value Selected: " << **fi << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Использование Cookies в CGI

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

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

Как это устроено

Ваш сервер отправляет некоторые данные в браузер посетителя в виде файла cookie. Браузер может принять куки. Если это так, он сохраняется в виде простой текстовой записи на жестком диске посетителя. Теперь, когда посетитель заходит на другую страницу вашего сайта, файл cookie становится доступным для поиска. После получения ваш сервер знает / запоминает, что было сохранено.

Cookies — это запись данных в виде простого текста из 5 полей переменной длины —

  • Истекает — показывает дату истечения срока действия куки. Если это поле пустое, срок действия файла cookie истечет, когда посетитель выйдет из браузера.

  • Домен — показывает доменное имя вашего сайта.

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

  • Безопасный — если в этом поле содержится слово «безопасный», тогда cookie может быть получен только с безопасного сервера. Если это поле пустое, такого ограничения не существует.

  • Имя = значение — файлы cookie устанавливаются и извлекаются в форме пар ключ-значение.

Истекает — показывает дату истечения срока действия куки. Если это поле пустое, срок действия файла cookie истечет, когда посетитель выйдет из браузера.

Домен — показывает доменное имя вашего сайта.

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

Безопасный — если в этом поле содержится слово «безопасный», тогда cookie может быть получен только с безопасного сервера. Если это поле пустое, такого ограничения не существует.

Имя = значение — файлы cookie устанавливаются и извлекаются в форме пар ключ-значение.

Настройка Cookies

Отправить куки в браузер очень просто. Эти файлы cookie будут отправлены вместе с заголовком HTTP до того, как будет заполнен тип контента. Предполагая, что вы хотите установить идентификатор пользователя и пароль в качестве файлов cookie. Таким образом, настройка куки будет выполнена следующим образом

#include <iostream>
using namespace std;

int main () {
   cout << "Set-Cookie:UserID = XYZ;\r\n";
   cout << "Set-Cookie:Password = XYZ123;\r\n";
   cout << "Set-Cookie:Domain = www.tutorialspoint.com;\r\n";
   cout << "Set-Cookie:Path = /perl;\n";
   cout << "Content-type:text/html\r\n\r\n";

   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Cookies in CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   cout << "Setting cookies" << endl;  
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Из этого примера вы должны понимать, как устанавливать файлы cookie. Мы используем HTTP-заголовок Set-Cookie для установки файлов cookie.

Здесь необязательно устанавливать атрибуты cookie, такие как Expires, Domain и Path. Примечательно, что куки устанавливаются перед отправкой волшебной строки «Content-type: text / html \ r \ n \ r \ n .

Скомпилируйте вышеуказанную программу для создания setcookies.cgi и попробуйте установить куки, используя следующую ссылку. Он установит четыре куки на вашем компьютере —

/cgi-bin/setcookies.cgi

Получение куки

Легко получить все установленные куки. Файлы cookie хранятся в переменной среды CGI HTTP_COOKIE и имеют следующую форму.

key1 = value1; key2 = value2; key3 = value3....

Вот пример того, как получить куки.

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main () {
   Cgicc cgi;
   const_cookie_iterator cci;

   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Cookies in CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<table border = \"0\" cellspacing = \"2\">";
   
   // get environment variables
   const CgiEnvironment& env = cgi.getEnvironment();

   for( cci = env.getCookieList().begin();
   cci != env.getCookieList().end(); 
   ++cci ) {
      cout << "<tr><td>" << cci->getName() << "</td><td>";
      cout << cci->getValue();                                 
      cout << "</td></tr>\n";
   }
   
   cout << "</table><\n";
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

Теперь скомпилируйте вышеуказанную программу для создания getcookies.cgi и попробуйте получить список всех файлов cookie, доступных на вашем компьютере —

/cgi-bin/getcookies.cgi

Это создаст список всех четырех файлов cookie, установленных в предыдущем разделе, и всех других файлов cookie, установленных на вашем компьютере —

UserID XYZ 
Password XYZ123 
Domain www.tutorialspoint.com 
Path /perl 

Пример загрузки файла

Для загрузки файла в HTML-форме атрибут enctype должен иметь значение multipart / form-data . Тег ввода с типом файла создаст кнопку «Обзор».

<html>
   <body>
      <form enctype = "multipart/form-data" action = "/cgi-bin/cpp_uploadfile.cgi"
         method = "post">
         <p>File: <input type = "file" name = "userfile" /></p>
         <p><input type = "submit" value = "Upload" /></p>
      </form>
   </body>
</html>

Результатом этого кода является следующая форма —

Файл:

Файл:

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

Вот скрипт cpp_uploadfile.cpp для обработки загрузки файла:

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main () {
   Cgicc cgi;

   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>File Upload in CGI</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";

   // get list of files to be uploaded
   const_file_iterator file = cgi.getFile("userfile");
   if(file != cgi.getFiles().end()) {
      // send data type at cout.
      cout << HTTPContentHeader(file->getDataType());
      // write content at cout.
      file->writeToStream(cout);
   }
   cout << "<File uploaded successfully>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

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

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