Обзор 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 .
#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 */
Комментарий также может начинаться с //, продолжаясь до конца строки. Например —
#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 широкий символ |
Размер переменных может отличаться от приведенного в таблице выше, в зависимости от компилятора и компьютера, который вы используете.
Ниже приведен пример, который даст правильный размер различных типов данных на вашем компьютере.
#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 ++, но она может быть определена только один раз в файле, функции или блоке кода.
пример
Попробуйте следующий пример, где переменная была объявлена вверху, но она была определена внутри основной функции —
#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 ++
Область действия — это область программы, и, в общем, есть три места, где переменные могут быть объявлены:
-
Внутри функции или блока, который называется локальными переменными,
-
В определении параметров функции это называется формальными параметрами.
-
Снаружи всех функций, которые называются глобальными переменными.
Внутри функции или блока, который называется локальными переменными,
В определении параметров функции это называется формальными параметрами.
Снаружи всех функций, которые называются глобальными переменными.
Мы узнаем, что такое функция и ее параметр в следующих главах. Здесь давайте объясним, что такое локальные и глобальные переменные.
Локальные переменные
Переменные, которые объявлены внутри функции или блока, являются локальными переменными. Они могут использоваться только операторами, которые находятся внутри этой функции или блока кода. Локальные переменные не известны функциям вне их собственных. Ниже приведен пример использования локальных переменных:
#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; }
Глобальные переменные
Глобальные переменные определяются вне всех функций, обычно в верхней части программы. Глобальные переменные будут сохранять свое значение на протяжении всей жизни вашей программы.
Глобальная переменная может быть доступна любой функции. То есть глобальная переменная доступна для использования во всей вашей программе после ее объявления. Ниже приведен пример использования глобальных и локальных переменных:
#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; }
Программа может иметь одинаковые имена для локальных и глобальных переменных, но предпочтение будет отдаваться значению локальной переменной внутри функции. Например —
#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-последовательности:
#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
Следующий пример объясняет это подробно —
#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;
Следующий пример объясняет это подробно —
#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 ++, вы должны запустить следующую короткую программу:
#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 используется в элементе данных класса, он вызывает совместное использование только одной копии этого члена всеми объектами его класса.
#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 ++ предоставляет следующие типы операторов принятия решений.
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 или когда достигается закрывающая фигурная скобка завершения функции, она возвращает управление программой обратно в основную программу.
Чтобы вызвать функцию, вам просто нужно передать необходимые параметры вместе с именем функции, и если функция возвращает значение, вы можете сохранить возвращаемое значение. Например —
#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 () используется тот же метод.
Значения по умолчанию для параметров
Когда вы определяете функцию, вы можете указать значение по умолчанию для каждого из последних параметров. Это значение будет использоваться, если соответствующий аргумент оставлен пустым при вызове функции.
Это делается с помощью оператора присваивания и присвоения значений аргументам в определении функции. Если значение для этого параметра не передается при вызове функции, используется заданное значение по умолчанию, но если указано значение, это значение по умолчанию игнорируется и вместо него используется переданное значение. Рассмотрим следующий пример —
#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 ++ —
#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 (двойной);
Эта функция возвращает абсолютное значение любого переданного ей десятичного числа.
двойной этаж (двухместный);
Находит целое число, которое меньше или равно аргументу, переданному ему.
Ниже приведен простой пример, демонстрирующий несколько математических операций:
#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 () —
#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. Ниже приведен пример, который будет использовать все три вышеупомянутых понятия, а именно. декларация, назначение и доступ к массивам —
#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 ++ автоматически помещает ‘\ 0’ в конец строки, когда инициализирует массив. Давайте попробуем напечатать вышеупомянутую строку —
#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.
Следующий пример использует несколько из вышеупомянутых функций —
#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 ++ предоставляет тип строкового класса, который поддерживает все операции, упомянутые выше, и, кроме того, гораздо больше функциональности. Давайте проверим следующий пример —
#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 ++, такие как динамическое выделение памяти, не могут быть выполнены без них.
Как вы знаете, каждая переменная является ячейкой памяти, и каждая ячейка памяти имеет свой адрес, к которому можно обратиться, используя оператор амперсанда (&), который обозначает адрес в памяти. Рассмотрим следующее, которое выведет адрес определенных переменных:
#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) Наконец, получите доступ к значению по адресу, доступному в переменной указателя. Это делается с помощью унарного оператора *, который возвращает значение переменной, расположенной по адресу, указанному ее операндом. Следующий пример использует эти операции —
#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 —
#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). Ниже приведен пример для достижения того же —
#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 и о том, как получить доступ к элементам структуры с помощью оператора стрелки ->.
#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 используется вместе с оператором вставки потока, который записывается как <<, что на два знака меньше, чем показано в следующем примере.
#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 используется вместе с оператором извлечения потока, который записывается как >>, что на два больше знака, как показано в следующем примере.
#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 также используется вместе с оператором вставки потока, как показано в следующем примере.
#include <iostream> using namespace std; int main() { char str[] = "Unable to read...."; cerr << "Error message : " << str << endl; }
Когда приведенный выше код компилируется и выполняется, он дает следующий результат —
Error message : Unable to read....
Стандартный поток журнала (засорение)
Предопределенный объект clog является экземпляром класса ostream . Говорят, что объект засорения прикреплен к стандартному устройству ошибки, которое также является экраном дисплея, но засорение объекта буферизуется. Это означает, что каждая вставка для засорения может привести к тому, что ее вывод будет храниться в буфере до тех пор, пока буфер не будет заполнен или пока буфер не будет очищен.
Засорение также используется вместе с оператором вставки потока, как показано в следующем примере.
#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 для определения переменных типа структуры. Ниже приведен пример, объясняющий использование структуры:
#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
Структуры как аргументы функций
Вы можете передать структуру в качестве аргумента функции так же, как и любую другую переменную или указатель. Вы будете обращаться к структурным переменным аналогично тому, как вы это делали в приведенном выше примере:
#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;
Давайте перепишем приведенный выше пример, используя указатель структуры, надеюсь, вам будет легко понять концепцию —
#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 будут иметь собственную копию элементов данных.
Доступ к членам данных
Доступ к открытым данным членов объектов класса можно получить с помощью оператора прямого доступа к члену (.). Давайте попробуем следующий пример, чтобы прояснить ситуацию:
#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 следующим образом:
#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....
Если доступ является одним из общедоступных, защищенных или закрытых и будет предоставляться для каждого базового класса, и они будут разделены запятой, как показано выше. Давайте попробуем следующий пример —
#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 () используется для печати разных типов данных:
#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&);
Ниже приведен пример, демонстрирующий концепцию оператора по загрузке с использованием функции-члена. Здесь объект передается в качестве аргумента, свойства которого будут доступны с помощью этого объекта, а объект, который вызовет этот оператор, может быть доступен с помощью этого оператора, как объяснено ниже —
#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
Ниже приведен список операторов, которые могут быть перегружены:
+ | — | * | / | % | ^ |
& | | | ~ | ! | , | знак равно |
< | > | <= | > = | ++ | — |
<< | >> | == | знак равно | && | || |
+ = | знак равно | знак равно | знак равно | ^ = | знак равно |
| = | знак равно | << = | >> = | [] | () |
-> | -> * | новый | новый [] | удалять | удалять [] |
Ниже приведен список операторов, которые не могут быть перегружены —
:: | . * | , | ?: |
Примеры перегрузки операторов
Вот несколько примеров перегрузки операторов, которые помогут вам понять концепцию.
Полиморфизм в C ++
Слово полиморфизм означает наличие многих форм. Как правило, полиморфизм возникает, когда существует иерархия классов, и они связаны наследованием.
C ++ полиморфизм означает, что вызов функции-члена приведет к выполнению другой функции в зависимости от типа объекта, который вызывает функцию.
Рассмотрим следующий пример, где базовый класс был получен двумя другими классами:
#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 для потоковой передачи данных в стандартный вывод, например так:
#include <iostream> using namespace std; int main() { cout << "Hello C++" <<endl; return 0; }
Здесь вам не нужно понимать, как cout отображает текст на экране пользователя. Вам нужно знать только открытый интерфейс, и базовая реализация cout может быть изменена.
Ярлыки доступа обеспечивают принудительную абстракцию
В C ++ мы используем метки доступа для определения абстрактного интерфейса с классом. Класс может содержать ноль или более меток доступа —
-
Члены, обозначенные общедоступным ярлыком, доступны для всех частей программы. Представление типа абстракции данных определяется его открытыми членами.
-
Члены, определенные с частной меткой, не доступны для кода, который использует класс. Закрытые разделы скрывают реализацию от кода, который использует тип.
Члены, обозначенные общедоступным ярлыком, доступны для всех частей программы. Представление типа абстракции данных определяется его открытыми членами.
Члены, определенные с частной меткой, не доступны для кода, который использует класс. Закрытые разделы скрывают реализацию от кода, который использует тип.
Нет ограничений на частоту появления метки доступа. Каждая метка доступа определяет уровень доступа следующих определений членов. Указанный уровень доступа остается в силе до тех пор, пока не встретится следующая метка доступа или пока не появится закрывающая правая скобка тела класса.
Преимущества абстракции данных
Абстракция данных обеспечивает два важных преимущества:
-
Внутренние классы защищены от непреднамеренных ошибок на уровне пользователя, которые могут повредить состояние объекта.
-
Реализация класса может со временем развиваться в ответ на изменяющиеся требования или сообщения об ошибках, не требуя изменения в коде пользовательского уровня.
Внутренние классы защищены от непреднамеренных ошибок на уровне пользователя, которые могут повредить состояние объекта.
Реализация класса может со временем развиваться в ответ на изменяющиеся требования или сообщения об ошибках, не требуя изменения в коде пользовательского уровня.
Определяя элементы данных только в закрытом разделе класса, автор класса может вносить изменения в данные. Если реализация изменяется, необходимо изучить только код класса, чтобы увидеть, как это может повлиять на изменение. Если данные являются общедоступными, то любая функция, которая напрямую обращается к членам данных старого представления, может быть нарушена.
Пример абстракции данных
Любая программа на C ++, где вы реализуете класс с открытыми и закрытыми членами, является примером абстракции данных. Рассмотрим следующий пример —
#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 ++, в которой вы реализуете класс с открытыми и закрытыми членами, является примером инкапсуляции данных и абстракции данных. Рассмотрим следующий пример —
#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 () —
#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, программа считывает информацию из файла и выводит ее на экран —
#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.
#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>, которые мы можем использовать в наших программах. Они расположены в иерархии родительско-дочерних классов, показанной ниже —
Вот небольшое описание каждого исключения, упомянутого в приведенной выше иерархии:
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 для реализации вашего собственного исключения стандартным способом —
#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»:
#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
Динамическое выделение памяти для объектов
Объекты ничем не отличаются от простых типов данных. Например, рассмотрим следующий код, где мы собираемся использовать массив объектов для пояснения концепции:
#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.
Давайте посмотрим, как пространство имен охватывает сущности, включая переменные и функции —
#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 . Эта директива сообщает компилятору, что последующий код использует имена в указанном пространстве имен. Таким образом, пространство имен подразумевается для следующего кода:
#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 по- прежнему должны быть явными, как показано ниже:
#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 доступными в области видимости следующим образом:
#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 — это имя-заполнитель для типа данных, используемого функцией. Это имя может использоваться в определении функции.
Ниже приведен пример шаблона функции, который возвращает максимум два значения:
#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 <> и реализации универсальных методов для выталкивания и извлечения элементов из стека.
#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 для определения макроса, который будет принимать аргумент следующим образом:
#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
Давайте попробуем следующий пример —
#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. Оператор # вызывает преобразование текстового токена замены в строку, заключенную в кавычки.
Рассмотрим следующее определение макроса —
#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 ++» в программе следующим образом.
#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 |
__ВРЕМЯ__ Он содержит строку вида час: минута: секунда, которая является временем компиляции программы. |
__ЛИНИЯ__
Он содержит номер текущей строки программы, когда она компилируется.
__ФАЙЛ__
Это содержит текущее имя файла программы, когда это компилируется.
__ДАТА__
Он содержит строку вида месяц / день / год, которая является датой перевода исходного файла в объектный код.
__ВРЕМЯ__
Он содержит строку вида час: минута: секунда, которая является временем компиляции программы.
Давайте посмотрим пример для всех вышеупомянутых макросов —
#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, которые должны выполняться сервером 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 и попробуйте установить куки, используя следующую ссылку. Он установит четыре куки на вашем компьютере —
Получение куки
Легко получить все установленные куки. Файлы 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, доступных на вашем компьютере —
Это создаст список всех четырех файлов 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, но вы можете открыть свой файловый поток и сохранить содержимое загруженного файла в файл в нужном месте.
Надеюсь, вам понравился этот урок. Если да, пожалуйста, отправьте нам свой отзыв.