Cplusplus-quick-guide
C ++の概要
C ++は、静的に型付けされ、コンパイルされた、汎用、大文字と小文字を区別する、自由形式のプログラミング言語であり、手続き型のオブジェクト指向の汎用プログラミングをサポートします。
C ++は、高レベルと低レベルの両方の言語機能の組み合わせで構成されるため、*中間レベル*言語と見なされます。
C は1979年にニュージャージー州マレーヒルのベル研究所でBjarne Stroustrupが開発したC言語の拡張機能であり、当初はC with Classesという名前でしたが、1983年にC と改名されました。
C はCのスーパーセットであり、事実上すべての正当なCプログラムは正当なC プログラムです。
注意-プログラミング言語は、実行時ではなくコンパイル時の型チェックが実行されるときに静的型付けを使用すると言われています。
オブジェクト指向プログラミング
C ++は、オブジェクト指向開発の4つの柱を含むオブジェクト指向プログラミングを完全にサポートします-
- カプセル化
- データ隠蔽
- 継承
- 多型
標準ライブラリ
標準C ++は3つの重要な部分で構成されています-
- 変数、データ型、リテラルなどを含むすべての構成要素を提供するコア言語。
- ファイル、文字列などを操作する豊富な関数セットを提供するC ++標準ライブラリ
- データ構造などを操作する豊富なメソッドセットを提供する標準テンプレートライブラリ(STL)
ANSI標準
ANSI標準は、C ++の移植性を確保するための試みです。 Microsoftのコンパイラ用に作成したコードは、Mac、UNIX、Windowsボックス、またはAlphaのコンパイラを使用して、エラーなしでコンパイルされます。
ANSI規格はしばらくの間安定しており、すべての主要なC ++コンパイラメーカーはANSI規格をサポートしています。
C ++の学習
C ++を学習する際の最も重要なことは、概念に焦点を当てることです。
プログラミング言語を学習する目的は、優れたプログラマーになることです。つまり、新しいシステムの設計と実装、および古いシステムの保守をより効果的にすることです。
C ++は、さまざまなプログラミングスタイルをサポートしています。 Fortran、C、Smalltalkなどのスタイルで、任意の言語で記述できます。 各スタイルは、ランタイムとスペースの効率を維持しながら、目的を効果的に達成できます。
C ++の使用
C ++は、本質的にすべてのアプリケーションドメインで数十万人のプログラマーによって使用されています。
C ++は、リアルタイムの制約の下でハードウェアの直接操作に依存するデバイスドライバーやその他のソフトウェアを作成するために非常に使用されています。
C ++は、基本概念の教育を成功させるのに十分なほどきれいであるため、教育および研究に広く使用されています。
これらのシステムの主要なユーザーインターフェイスはC で記述されているため、Apple MacintoshまたはWindowsを実行しているPCのいずれかを使用している人はC を間接的に使用しています。
C ++環境のセットアップ
ローカル環境のセットアップ
それでもC ++の環境をセットアップする場合は、コンピューターに次の2つのソフトウェアが必要です。
テキストエディタ
これは、プログラムの入力に使用されます。 いくつかのエディターの例には、Windows Notepad、OS Editコマンド、Brief、Epsilon、EMACS、vimまたはviが含まれます。
テキストエディタの名前とバージョンは、オペレーティングシステムによって異なる場合があります。 たとえば、Windowsではメモ帳が使用され、LinuxまたはUNIXと同様に、vimまたはviがWindowsで使用できます。
エディターで作成するファイルはソースファイルと呼ばれ、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を入手する最も簡単な方法は、AppleのWebサイトからXcode開発環境をダウンロードし、簡単なインストール手順に従うことです。
Xcodeは現在、https://developer.apple.com/technologies/tools/[developer.apple.com/technologies/tools/]で入手できます。
Windowsインストール
WindowsにGCCをインストールするには、MinGWをインストールする必要があります。 MinGWをインストールするには、MinGWホームページhttp://www.mingw.org [www.mingw.org]にアクセスし、MinGWダウンロードページへのリンクをたどってください。 MinGW- <バージョン> .exeという名前のMinGWインストールプログラムの最新バージョンをダウンロードします。
MinGWのインストール中に、少なくともgcc-core、gcc-g ++、binutils、およびMinGWランタイムをインストールする必要がありますが、さらにインストールすることもできます。
MinGWインストールのbinサブディレクトリを 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> が必要です。
- using namespace std; という行は、std名前空間を使用するようコンパイラーに指示しています。 名前空間はC ++に比較的最近追加されたものです。
- 次の行 '//main()は、プログラムの実行が開始される場所です。'は、C ++で使用可能な1行のコメントです。 単一行コメントは//で始まり、行末で停止します。
- 行* int main()*は、プログラムの実行を開始するメイン関数です。
- 次の行 cout << "Hello World"; は、メッセージ "Hello World"を画面に表示します。
- 次の行 return 0; はmain()関数を終了し、呼び出しプロセスに値0を返します。
C ++プログラムのコンパイルと実行
ファイルを保存し、プログラムをコンパイルして実行する方法を見てみましょう。 以下の手順に従ってください-
- テキストエディターを開き、上記のようにコードを追加します。
- ファイルをhello.cppとして保存します
- コマンドプロンプトを開き、ファイルを保存したディレクトリに移動します。
- 「g ++ hello.cpp」と入力し、Enterキーを押してコードをコンパイルします。 コードにエラーがない場合、コマンドプロンプトは次の行に進み、a.out実行可能ファイルを生成します。
- ここで、「a.out」と入力してプログラムを実行します。
- ウィンドウに「Hello World」と表示されます。
$ g++ hello.cpp
$ ./a.out
Hello World
g ++がパスにあり、hello.cppファイルを含むディレクトリで実行されていることを確認してください。
makefileを使用してC/C ++プログラムをコンパイルできます。 詳細については、リンク:/makefile/index ['Makefile Tutorial']を確認してください。
C ++のセミコロンとブロック
C ++では、セミコロンはステートメントターミネータです。 つまり、個々のステートメントはセミコロンで終了する必要があります。 1つの論理エンティティの終わりを示します。
たとえば、以下は3つの異なるステートメントです-
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個以上の文字、アンダースコア、および数字(0〜9)が続きます。
C では、識別子内で@、$、%などの句読点文字を使用できません。 C は、大文字と小文字を区別するプログラミング言語です。 したがって、 Manpower と manpower は、C ++の2つの異なる識別子です。
ここに受け入れ可能な識別子のいくつかの例があります-
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
C ++キーワード
次のリストは、C ++の予約語を示しています。 これらの予約語は、定数、変数、またはその他の識別子名として使用できません。
asm | else | new | this |
auto | enum | operator | throw |
bool | explicit | private | true |
break | export | protected | try |
case | extern | public | typedef |
catch | false | register | typeid |
char | float | reinterpret_cast | typename |
class | for | return | union |
const | friend | short | unsigned |
const_cast | goto | signed | using |
continue | if | sizeof | virtual |
default | inline | static | void |
delete | int | static_cast | volatile |
do | long | struct | wchar_t |
double | mutable | switch | while |
dynamic_cast | namespace | template |
トライグラフ
いくつかの文字には、トライグラフシーケンスと呼ばれる代替表現があります。 3文字表記は、1文字を表す3文字のシーケンスであり、シーケンスは常に2つの疑問符で始まります。
トライグラフは、文字列リテラルや文字リテラル内、コメント内、プリプロセッサディレクティブ内など、表示される場所で展開されます。
以下は、最も頻繁に使用されるトライグラフシーケンスです-
Trigraph | Replacement |
---|---|
??= | # |
??/ | \ |
??' | ^ |
??( | [ |
??) | ] |
??! | |
??< | |
\{ | ??> |
} | ??- |
すべてのコンパイラーはトライグラフをサポートしておらず、混乱する性質があるため、使用することはお勧めしません。
C ++の空白
コメントが含まれている可能性のある空白のみを含む行は空白行と呼ばれ、C ++コンパイラはそれを完全に無視します。
空白は、C ++で使用される用語で、空白、タブ、改行文字、コメントを表します。 空白は、ステートメントの一部を別の部分から分離し、コンパイラーがステートメント内の1つの要素(intなど)がどこで終わり、次の要素が始まるかをコンパイラーが識別できるようにします。
ステートメント1
int age;
上記のステートメントでは、コンパイラーが区別できるように、intとageの間に少なくとも1つの空白文字(通常はスペース)が必要です。
ステートメント2
fruit = apples + oranges; //Get the total fruit
上記のステートメント2では、fruitと=、または=とappleの間に空白文字は必要ありませんが、読みやすくするために空白文字を自由に含めることができます。
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 は、プログラマーに豊富な品揃えの組み込みおよびユーザー定義のデータ型を提供します。 次の表は、7つの基本的なC データ型を示しています-
Type | Keyword |
---|---|
Boolean | bool |
Character | char |
Integer | int |
Floating point | float |
Double floating point | double |
Valueless | void |
Wide character | wchar_t |
基本的なタイプのいくつかは、これらのタイプ修飾子の1つ以上を使用して変更することができます-
- 署名済み
- 署名なし
- ショート
- long
次の表は、変数の種類、メモリに値を保存するのに必要なメモリ量、およびそのような種類の変数に保存できる最大値と最小値を示しています。
Type | Typical Bit Width | Typical Range |
---|---|---|
char | 1byte | -127 to 127 or 0 to 255 |
unsigned char | 1byte | 0 to 255 |
signed char | 1byte | -127 to 127 |
int | 4bytes | -2147483648 to 2147483647 |
unsigned int | 4bytes | 0 to 4294967295 |
signed int | 4bytes | -2147483648 to 2147483647 |
short int | 2bytes | -32768 to 32767 |
unsigned short int | 2bytes | 0 to 65,535 |
signed short int | 2bytes | -32768 to 32767 |
long int | 8bytes | -2,147,483,648 to 2,147,483,647 |
signed long int | 8bytes | same as long int |
unsigned long int | 8bytes | 0 to 4,294,967,295 |
long long int | 8bytes | -(2^63) to (2^63)-1 |
unsigned long long int | 8bytes | 0 to 18,446,744,073,709,551,615 |
float | 4bytes | |
double | 8bytes | |
long double | 12bytes | |
wchar_t | 2 or 4 bytes | 1 wide character |
変数のサイズは、コンパイラーと使用しているコンピューターによって、上記の表に示されているものと異なる場合があります。
以下は、コンピューター上のさまざまなデータ型の正しいサイズを生成する例です。
#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;
たとえば、以下はフィートがintの別の名前であることをコンパイラに伝えます-
typedef int feet;
さて、次の宣言は完全に正当であり、距離と呼ばれる整数変数を作成します-
feet distance;
列挙型
列挙型は、オプションの型名と、型の値として使用できるゼロ個以上の識別子のセットを宣言します。 各列挙子は、型が列挙である定数です。
列挙を作成するには、キーワード enum を使用する必要があります。 列挙型の一般的な形式は-
enum enum-name { list of names } var-list;
ここで、enum-nameは列挙型の名前です。 名前のリストはカンマ区切りです。
たとえば、次のコードは、colorsと呼ばれる色の列挙とcolor型の変数cを定義しています。 最後に、cには値「blue」が割り当てられます。
enum color { red, green, blue } c;
c = blue;
デフォルトでは、最初の名前の値は0、2番目の名前の値は1、3番目の名前の値は2というようになります。 ただし、初期化子を追加することで、名前、特定の値を指定できます。 たとえば、次の列挙では、 green の値は5です。
enum color { red, green = 5, blue };
ここで、 blue の値は6です。これは、各名前がその前の名前よりも1つ大きいためです。
C ++変数タイプ
変数は、プログラムが操作できる名前付きストレージを提供します。 C ++の各変数には特定のタイプがあり、変数のメモリのサイズとレイアウトを決定します。そのメモリ内に保存できる値の範囲。変数に適用できる一連の操作。
変数の名前は、文字、数字、およびアンダースコア文字で構成できます。 文字またはアンダースコアで始まる必要があります。 C ++では大文字と小文字が区別されるため、大文字と小文字は区別されます-
前の章で説明したように、C ++には次の基本的な変数タイプがあります-
Sr.No | Type & Description |
---|---|
1 |
bool 値trueまたはfalseを格納します。 |
2 |
char 通常、単一のオクテット(1バイト)。 これは整数型です。 |
3 |
int マシンの整数の最も自然なサイズ。 |
4 |
float 単精度浮動小数点値。 |
5 |
double 倍精度の浮動小数点値。 |
6 |
void タイプがないことを表します。 |
7 |
wchar_t ワイド文字タイプ。 |
C ++では、他のさまざまなタイプの変数を定義することもできます。これについては、列挙、ポインター、配列、参照、データ構造、*クラス*などの後続の章で説明します。
次のセクションでは、さまざまなタイプの変数を定義、宣言、および使用する方法について説明します。
C ++の変数定義
変数定義は、変数用に作成するストレージの場所と量をコンパイラーに指示します。 変数の定義は、データ型を指定し、次のようにその型の1つ以上の変数のリストが含まれています-
type variable_list;
ここで、 type は、char、w_char、int、float、double、boolまたは任意のユーザー定義オブジェクトなどを含む有効なC ++データ型である必要があり、 variable_list はコンマで区切られた1つ以上の識別子名で構成されます。 いくつかの有効な宣言がここに示されています-
int i, j, k;
char c, ch;
float f, salary;
double d;
行 int i、j、k; は、変数i、jおよびkを宣言および定義します。これは、int型のi、j、kという名前の変数を作成するようコンパイラーに指示します。
変数は、宣言で初期化(初期値を割り当て)できます。 初期化子は、等号とそれに続く定数式で構成されます-
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 ++での変数宣言
変数宣言は、指定された型と名前を持つ変数が1つ存在することをコンパイラに保証するため、コンパイラは、変数に関する完全な詳細を必要とせずに、さらにコンパイルを進めることができます。 変数宣言はコンパイル時にのみ意味を持ち、コンパイラはプログラムのリンク時に実際の変数定義を必要とします。
変数宣言は、複数のファイルを使用していて、プログラムのリンク時に使用できるファイルの1つで変数を定義するときに役立ちます。 extern キーワードを使用して、任意の場所で変数を宣言します。 ただし、C ++プログラムでは変数を複数回宣言できますが、ファイル、関数、またはコードブロックで定義できるのは1回だけです。
例
変数が上部で宣言されているが、メイン関数内で定義されている次の例を試してください-
#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;
}
左辺値と右辺値
C ++には2種類の式があります-
- lvalue -メモリ位置を参照する式は「lvalue」式と呼ばれます。 左辺値は、割り当ての左辺または右辺として表示される場合があります。
- rvalue -rvalueという用語は、メモリ内のあるアドレスに格納されているデータ値を指します。 右辺値は、値を割り当てることができない式です。つまり、右辺に割り当てることができますが、割り当ての左側ではありません。
変数は左辺値であるため、割り当ての左側に表示される場合があります。 数値リテラルは右辺値であるため、割り当てられない可能性があり、左側に表示できません。 以下は有効なステートメントです-
int g = 20;
しかし、次は有効なステートメントではなく、コンパイル時エラーを生成します-
10 = 20;
C ++の変数スコープ
スコープは、プログラムの領域であり、おおまかに言えば、変数を宣言できる3つの場所があります-
- ローカル変数と呼ばれる関数またはブロック内で、
- 仮パラメータと呼ばれる関数パラメータの定義。
- グローバル変数と呼ばれるすべての関数の外側。
関数とそのパラメーターについては、以降の章で学習します。 ここで、ローカル変数とグローバル変数について説明します。
ローカル変数
関数またはブロック内で宣言される変数はローカル変数です。 それらは、その関数またはコードブロック内にあるステートメントでのみ使用できます。 ローカル変数は、自身の外部の関数には認識されません。 以下は、ローカル変数を使用した例です-
#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
ローカル変数とグローバル変数の初期化
ローカル変数が定義されると、システムによって初期化されません。自分で初期化する必要があります。 グローバル変数は、次のように定義すると、システムによって自動的に初期化されます-
Data Type | Initializer |
---|---|
int | 0 |
char | '\0' |
float | 0 |
double | 0 |
pointer | NULL |
変数を適切に初期化するのは良いプログラミング手法です。そうしないと、プログラムで予期しない結果が生じることがあります。
C ++定数/リテラル
定数は、プログラムが変更できない固定値を指し、*リテラル*と呼ばれます。
定数は、基本的なデータ型のいずれかであり、整数数値、浮動小数点数値、文字、文字列、ブール値に分割できます。
繰り返しますが、定数は通常の変数と同様に扱われますが、定義後に値を変更することはできません。
整数リテラル
整数リテラルは、10進、8進、または16進定数です。 プレフィックスは、基数または基数を指定します。16進数の場合は0xまたは0X、8進数の場合は0、10進数の場合は何もありません。
整数リテラルには、UとLを組み合わせたサフィックスを付けることもできます。それぞれ、符号なしとロングを表します。 接尾辞は大文字でも小文字でも、任意の順序で指定できます。
ここに整数リテラルのいくつかの例があります-
212 //Legal
215u //Legal
0xFeeL //Legal
078 //Illegal: 8 is not an octal digit
032UU //Illegal: cannot repeat a suffix
以下は、整数リテラルのさまざまなタイプの他の例です-
85 //decimal
0213 //octal
0x4b //hexadecimal
30 //int
30u //unsigned int
30l //long
30ul //unsigned long
浮動小数点リテラル
浮動小数点リテラルには、整数部、小数点、小数部、指数部があります。 浮動小数点リテラルは、10進数形式または指数形式で表現できます。
小数点形式を使用して表す場合は、小数点、指数、またはその両方を含める必要があり、指数形式を使用して表す場合は、整数部、小数部、またはその両方を含める必要があります。 符号付き指数は、eまたはEによって導入されます。
浮動小数点リテラルの例をいくつか示します-
3.14159 //Legal
314159E-5L //Legal
510E //Illegal: incomplete exponent
210f //Illegal: no decimal or exponent
.e55 //Illegal: missing integer or fraction
ブールリテラル
2つのブールリテラルがあり、それらは標準のC ++キーワードの一部です-
- trueを表す true の値。
- falseを表す false の値。
trueの値が1に、falseの値が0に等しいとは考えないでください。
文字リテラル
文字リテラルは単一引用符で囲まれます。 リテラルがL(大文字のみ)で始まる場合、それはワイド文字リテラル(例:L’x ')であり、 wchar_t タイプのvariableに格納する必要があります。 それ以外の場合は、ナロー文字リテラル(例: 'x')であり、 char 型の単純な変数に格納できます。
文字リテラルは、プレーン文字(例: 'x')、エスケープシーケンス(例: '\ t')、またはユニバーサル文字(例: '\ u02C0')です。
C ++には特定の文字があり、バックスラッシュが前に付いている場合は特別な意味を持ち、改行(\ n)またはタブ(\ t)のような表現に使用されます。 ここでは、そのようなエスケープシーケンスコードのいくつかのリストを持っています-
Escape sequence | Meaning |
---|---|
\\ | \ character |
\' | ' character |
\" | " character |
\? | ? character |
\a | Alert or bell |
\b | Backspace |
\f | Form feed |
\n | Newline |
\r | Carriage return |
\t | Horizontal tab |
\v | Vertical tab |
\ooo | Octal number of one to three digits |
\xhh . . . | Hexadecimal number of one or more digits |
以下は、いくつかのエスケープシーケンス文字を示す例です-
#include <iostream>
using namespace std;
int main() {
cout << "Hello\tWorld\n\n";
return 0;
}
上記のコードをコンパイルして実行すると、次の結果が生成されます-
Hello World
文字列リテラル
文字列リテラルは二重引用符で囲みます。 文字列には、文字リテラルに類似した文字が含まれます:プレーン文字、エスケープシーケンス、およびユニバーサル文字。
文字列リテラルを使用して長い行を複数の行に分割し、空白を使用してそれらを区切ることができます。
文字列リテラルの例を次に示します。 3つの形式はすべて同じ文字列です。
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
定数の定義
C ++には定数を定義する2つの簡単な方法があります-
- *#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
CAPITALSで定数を定義することは、優れたプログラミング手法であることに注意してください。
C ++修飾子タイプ
C ++では、* char、int、、および *double データ型の前に修飾子を付けることができます。 修飾子は、さまざまな状況のニーズにより正確に適合するように、ベースタイプの意味を変更するために使用されます。
データ型修飾子はここにリストされています-
- 署名済み
- 署名なし
- long
- ショート
修飾子* signed、unsigned、long、および *short は、整数の基本型に適用できます。 さらに、 signed および unsigned はcharに適用でき、 long はdoubleに適用できます。
修飾子 signed および unsigned は、 long または short 修飾子の接頭辞としても使用できます。 たとえば、 unsigned long int 。
C ++では、* unsigned、short、、または *long 整数を宣言するための短縮表記が可能です。 int なしで、単語* unsigned、short、または long、を使用できます。 自動的に *int を意味します。 たとえば、次の2つのステートメントは両方とも符号なし整数変数を宣言しています。
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
上記の結果は、短い符号なし整数として50,000を表すビットパターンが、短い-15,536として解釈されるためです。
C ++の型修飾子
型修飾子は、先行する変数に関する追加情報を提供します。
Sr.No | Qualifier & Meaning |
---|---|
1 |
const タイプ const のオブジェクトは、実行中にプログラムによって変更することはできません。 |
2 |
volatile 修飾子 volatile は、プログラムによって明示的に指定されていない方法で変数の値が変更される可能性があることをコンパイラーに伝えます。 |
3 |
restrict
|
C ++のストレージクラス
ストレージクラスは、C プログラム内の変数や関数のスコープ(可視性)と寿命を定義します。 これらの指定子は、変更するタイプの前にあります。 次のストレージクラスがあり、C プログラムで使用できます。
- auto
- 登録
- 静的
- 外面
- 可変
自動ストレージクラス
*auto* ストレージクラスは、すべてのローカル変数のデフォルトストレージクラスです。
{
int mount;
auto int month;
}
上記の例では、同じストレージクラスを持つ2つの変数を定義しています。autoは関数内でのみ使用できます。つまり、ローカル変数です。
レジスタストレージクラス
*register* ストレージクラスは、RAMではなくレジスタに保存するローカル変数を定義するために使用されます。 これは、変数の最大サイズがレジスタサイズ(通常は1ワード)に等しく、単項 '&'演算子を適用できないことを意味します(メモリ位置がないため)。
{
register int miles;
}
レジスタは、カウンタなどの迅速なアクセスを必要とする変数にのみ使用する必要があります。 また、「レジスタ」を定義しても、変数がレジスタに格納されるわけではないことに注意してください。 これは、ハードウェアと実装の制限に応じて、レジスタに格納される可能性があることを意味します。
静的ストレージクラス
*static* ストレージクラスは、プログラムの有効期間中にローカル変数を作成および破棄するのではなく、スコープに出入りするたびにローカル変数を保持するようコンパイラーに指示します。 したがって、ローカル変数を静的にすると、関数呼び出し間で値を維持できます。
static修飾子は、グローバル変数にも適用できます。 これが行われると、その変数のスコープは、それが宣言されているファイルに制限されます。
C ++では、静的がクラスデータメンバーで使用されると、そのメンバーの1つのコピーのみがそのクラスのすべてのオブジェクトで共有されます。
#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_は別のファイルでグローバル変数または関数を宣言するために使用されます。
extern修飾子は、以下で説明するように、同じグローバル変数または関数を共有する2つ以上のファイルがある場合に最も一般的に使用されます。
最初のファイル:main.cpp
#include <iostream>
int count ;
extern void write_extern();
main() {
count = 5;
write_extern();
}
2番目のファイル:support.cpp
#include <iostream>
extern int count;
void write_extern(void) {
std::cout << "Count is " << count << std::endl;
}
ここでは、_extern_キーワードを使用して、別のファイルでカウントを宣言しています。 今、次のようにこれらの2つのファイルをコンパイルします-
$g++ main.cpp support.cpp -o write
これは、*書き込み*実行可能プログラムを生成し、*書き込み*を実行し、次のように結果を確認しようとします-
$./write
5
可変ストレージクラス
*mutable* 指定子は、このチュートリアルで後述するクラスオブジェクトにのみ適用されます。 オブジェクトのメンバーがconstメンバー関数をオーバーライドできます。 つまり、可変メンバーはconstメンバー関数によって変更できます。
C ++の演算子
演算子は、特定の数学的または論理的な操作を実行するようコンパイラーに指示する記号です。 C ++は組み込み演算子が豊富であり、次の種類の演算子を提供します-
- 算術演算子
- 関係演算子
- 論理演算子
- ビット演算子
- 割り当て演算子
- その他の演算子
この章では、算術、関係、論理、ビット単位、割り当て、およびその他の演算子を1つずつ調べます。
算術演算子
C ++言語でサポートされている次の算術演算子があります-
変数Aが10を保持し、変数Bが20を保持すると仮定します-
リンク:/cplusplus/cpp_arithmatic_operators [例を表示]
Operator | Description | Example |
---|---|---|
+ | Adds two operands | A + B will give 30 |
- | Subtracts second operand from the first | A - B will give -10 |
* | Multiplies both operands | A* B will give 200 |
/ | Divides numerator by de-numerator | B/A will give 2 |
% | Modulus Operator and remainder of after an integer division | B % A will give 0 |
++ | Increment operator, increases integer value by one | A++ will give 11 |
— | Decrement operator, decreases integer value by one | A-- will give 9 |
関係演算子
C ++言語でサポートされている次の関係演算子があります
変数Aが10を保持し、変数Bが20を保持すると仮定します-
リンク:/cplusplus/cpp_relational_operators [例を表示]
Operator | Description | Example |
---|---|---|
== | Checks if the values of two operands are equal or not, if yes then condition becomes true. | (A == B) is not true. |
!= | Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. | (A != B) is true. |
> | Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. | (A > B) is not true. |
< | Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. | (A < B) is true. |
>= | Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. | (A >= B) is not true. |
⇐ | Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. | (A ⇐ B) is true. |
論理演算子
C ++言語でサポートされている論理演算子は次のとおりです。
変数Aが1を保持し、変数Bが0を保持すると仮定し、その後-
リンク:/cplusplus/cpp_logical_operators [例を表示]
Operator | Description | Example |
---|---|---|
&& | Called Logical AND operator. If both the operands are non-zero, then condition becomes true. | (A && B) is false. |
Called Logical OR Operator. If any of the two operands is non-zero, then condition becomes true. | (A | |
B) is true. | ! | Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true, then Logical NOT operator will make false. |
ビット演算子
ビット演算子はビットに対して機能し、ビットごとの操作を実行します。 &、|、および^の真理値表は次のとおりです-
p | q | p & q | p | q |
---|---|---|---|---|
p ^ q | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
0 | 1 | 0 | 0 | 1 |
A = 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を保持すると仮定します-
リンク:/cplusplus/cpp_bitwise_operators [例を表示]
[cols=",,",options="header",]
|===
|Operator |Description |Example |& |Binary AND Operator copies a bit to the result if it exists in both operands. |(A & B) will give 12 which is 0000 1100 || |Binary OR Operator copies a bit if it exists in either operand. |(A | B) will give 61 which is 0011 1101 |^ |Binary XOR Operator copies the bit if it is set in one operand but not both. |(A ^ B) will give 49 which is 0011 0001 |~ |Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. |(~A ) will give -61 which is 1100 0011 in 2's complement form due to a signed binary number. |<< |Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. |A << 2 will give 240 which is 1111 0000 |>> |Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. |A >> 2 will give 15 which is 0000 1111
|===
=== 割り当て演算子
C ++言語でサポートされている次の代入演算子があります-
リンク:/cplusplus/cpp_assignment_operators [例を表示]
[cols=",,",options="header",]
|===
|Operator |Description |Example |= |Simple assignment operator, Assigns values from right side operands to left side operand. |C = A + B will assign value of A + B into C |+= |Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand. |C += A is equivalent to C = C + A |-= |Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand. |C -= A is equivalent to C = C - A |*= |Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand. |C *= A is equivalent to C = C *A |/= |Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand. |C/= A is equivalent to C = C/A |%= |Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand. |C %= A is equivalent to C = C % A |<<= |Left shift AND assignment operator. |C <<= 2 is same as C = C << 2 |>>= |Right shift AND assignment operator. |C >>= 2 is same as C = C >> 2 |&= |Bitwise AND assignment operator. |C &= 2 is same as C = C & 2 |^= |Bitwise exclusive OR and assignment operator. |C ^= 2 is same as C = C ^ 2 ||= |Bitwise inclusive OR and assignment operator. |C |= 2 is same as C = C | 2
|===
=== その他の演算子
次の表に、C ++がサポートする他の演算子をいくつか示します。
[width="100%",cols="50%,50%",options="header",]
|===
|Sr.No |Operator & Description |1 a|* sizeof*
link:/cplusplus/cpp_sizeof_operator [sizeof operator]は変数のサイズを返します。 たとえば、sizeof(a)、「a」は整数で、4を返します。
|2 a| *Condition ? X : Y*
リンク:/cplusplus/cpp_conditional_operator [条件演算子(?)]。 Conditionがtrueの場合、Xの値を返します。それ以外の場合、Yの値を返します。
|3 a| *,*
link:/cplusplus/cpp_comma_operator [カンマ演算子]を使用すると、一連の操作が実行されます。 コンマ式全体の値は、コンマ区切りリストの最後の式の値です。
|4 a|
. (ドット)および->(矢印) *
link:/cplusplus/cpp_member_operators [メンバー演算子]は、クラス、構造体、および共用体の個々のメンバーを参照するために使用されます。
|5 a|* Cast*
link:/cplusplus/cpp_casting_operators [キャスト演算子]は、1つのデータ型を別のデータ型に変換します。 たとえば、int(2.2000)は2を返します。
|6 a| *&*
link:/cplusplus/cpp_pointer_operators [ポインタ演算子&]は、変数のアドレスを返します。 たとえば、&a;変数の実際のアドレスを提供します。
|7 a| ***
link:/cplusplus/cpp_pointer_operators [ポインタ演算子*]は変数へのポインタです。 たとえば、 *var;変数varへのポインター。
|===
=== C ++での演算子の優先順位
演算子の優先順位は、式内の用語のグループ化を決定します。 これは、式の評価方法に影響します。 特定の演算子は、他の演算子よりも優先順位が高くなっています。たとえば、乗算演算子は加算演算子よりも優先順位が高い-
たとえば、x = 7 + 3* 2;ここでは、演算子*の優先順位が+よりも高いため、xには20ではなく13が割り当てられます。したがって、最初に3 * 2で乗算され、7に加算されます。
ここでは、優先順位が最も高い演算子が表の上部に表示され、優先順位が最も低い演算子が下部に表示されます。 式内では、優先順位の高い演算子が最初に評価されます。
リンク:/cplusplus/cpp_operators_precedence [例を表示]
[cols=",,",options="header",]
|===
|Category |Operator |Associativity |Postfix |() [] -> . ++ - - |Left to right |Unary |+ - ! ~ ++ - - (type)* & sizeof |Right to left |Multiplicative | */% |Left to right |Additive |+ - |Left to right |Shift |<< >> |Left to right |Relational |< <= > >= |Left to right |Equality |== != |Left to right |Bitwise AND |& |Left to right |Bitwise XOR |^ |Left to right |Bitwise OR || |Left to right |Logical AND |&& |Left to right |Logical OR ||| |Left to right |Conditional |?: |Right to left |Assignment |= += -=* =/= %=>>= <<= &= ^= |= |Right to left |Comma |, |Left to right
|===
C ++ループタイプ
コードのブロックを数回実行する必要がある場合があります。 一般に、ステートメントは順番に実行されます。関数の最初のステートメントが最初に実行され、次に2番目のステートメントが実行されます。
プログラミング言語は、より複雑な実行パスを可能にするさまざまな制御構造を提供します。
ループステートメントは、ステートメントまたはステートメントのグループを複数回実行することを可能にし、ほとんどのプログラミング言語のループステートメントの一般的なものは次のとおりです-
C ++プログラミング言語は、ループ要件を処理するために次のタイプのループを提供します。
Sr.No | Loop Type & Description |
---|---|
1 |
特定の条件が真の間、ステートメントまたはステートメントのグループを繰り返します。 ループ本体を実行する前に条件をテストします。 |
2 |
一連のステートメントを複数回実行し、ループ変数を管理するコードを短縮します。 |
3 |
「while」ステートメントに似ていますが、ループ本体の最後で条件をテストします。 |
4 |
別の「while」、「for」、または「do..while」ループ内で1つ以上のループを使用できます。 |
ループ制御ステートメント
ループ制御ステートメントは、通常のシーケンスから実行を変更します。 実行がスコープを離れると、そのスコープで作成されたすべての自動オブジェクトが破棄されます。
C ++は、次の制御ステートメントをサポートしています。
Sr.No | Control Statement & Description |
---|---|
1 |
|
2 |
ループがその本体の残りをスキップし、反復する前にその状態をすぐに再テストします。 |
3 |
ラベル付きステートメントに制御を移します。 プログラムでgotoステートメントを使用することはお勧めしませんが。 |
無限ループ
条件が決して偽にならない場合、ループは無限ループになります。 for ループは伝統的にこの目的に使用されます。 「for」ループを形成する3つの式はいずれも必要ないため、条件式を空のままにして無限ループを作成できます。
#include <iostream>
using namespace std;
int main () {
for( ; ; ) {
printf("This loop will run forever.\n");
}
return 0;
}
条件式が存在しない場合、trueと見なされます。 初期化式と増分式を使用できますが、C ++プログラマーはより一般的に「for(;;)」コンストラクトを使用して無限ループを示します。
注-Ctrl + Cキーを押すと、無限ループを終了できます。
C ++意思決定ステートメント
意思決定構造では、プログラマーが、プログラムによって評価またはテストされる1つ以上の条件を、条件が真であると判断された場合に実行されるステートメント、およびオプションで条件が実行された場合に実行される他のステートメントとともに指定する必要があります偽と判断されます。
以下は、ほとんどのプログラミング言語で見られる典型的な意思決定構造の一般的な形式です-
C ++プログラミング言語は、次のタイプの意思決定ステートメントを提供します。
Sr.No | Statement & Description |
---|---|
1 |
「if」ステートメントは、ブール式とそれに続く1つ以上のステートメントで構成されます。 |
2 |
「if」ステートメントの後にオプションの「else」ステートメントを続けることができます。これはブール式が偽の場合に実行されます。 |
3 |
「switch」ステートメントを使用すると、変数を値のリストと等しいかどうかをテストできます。 |
4 |
1つの「if」または「else if」ステートメントを別の「if」または「else if」ステートメント内で使用できます。 |
5 |
1つの「switch」ステートメントを別の「switch」ステートメント内で使用できます。 |
は? :オペレーター
リンク:/cplusplus/cpp_conditional_operator [条件演算子 "? :”]前の章で if … else ステートメントを置き換えるために使用できます。 それは次の一般的な形式を持っています-
Exp1 ? Exp2 : Exp3;
Exp1、Exp2、およびExp3は式です。 コロンの使用と配置に注意してください。
「?」式の値は次のように決定されます。Exp1が評価されます。 trueの場合、Exp2が評価され、「?」式全体の値になります。 Exp1がfalseの場合、Exp3が評価され、その値が式の値になります。
C ++関数
関数は、一緒にタスクを実行するステートメントのグループです。 すべてのC ++プログラムには少なくとも1つの関数(* main()*)があり、最も単純なプログラムはすべて追加の関数を定義できます。
コードを別々の機能に分割できます。 コードを異なる関数に分割する方法はユーザー次第ですが、論理的には通常、各関数が特定のタスクを実行するように分割されます。
関数*宣言*は、関数の名前、戻り値の型、およびパラメーターについてコンパイラーに通知します。 関数 definition は、関数の実際の本体を提供します。
C ++標準ライブラリは、プログラムが呼び出すことができる多数の組み込み関数を提供します。 たとえば、2つの文字列を連結する関数* strcat()、1つのメモリ位置を別の位置にコピーする関数 memcpy()*、およびさらに多くの関数。
関数は、メソッド、サブルーチン、またはプロシージャなどのさまざまな名前で知られています。
関数を定義する
C ++関数定義の一般的な形式は次のとおりです-
return_type function_name( parameter list ) {
body of the function
}
C ++関数定義は、関数ヘッダーと関数本体で構成されます。 ここに関数のすべての部分があります-
- 戻り値の型-関数は値を返す場合があります。 return_type は、関数が返す値のデータ型です。 一部の関数は、値を返さずに目的の操作を実行します。 この場合、return_typeはキーワード void です。
- 関数名-これは関数の実際の名前です。 関数名とパラメーターリストは一緒に関数シグネチャを構成します。
- パラメータ-パラメータはプレースホルダのようなものです。 関数が呼び出されると、パラメーターに値を渡します。 この値は、実パラメーターまたは引数と呼ばれます。 パラメーターリストは、関数のパラメーターのタイプ、順序、および数を参照します。 パラメーターはオプションです。つまり、関数にパラメーターを含めることはできません。
- 関数本体-関数本体には、関数の動作を定義するステートメントのコレクションが含まれています。
例
以下は、* max()*という関数のソースコードです。 この関数は2つのパラメータ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;
}
main()関数とともにmax()関数を保持し、ソースコードをコンパイルしました。 最終的な実行可能ファイルを実行している間、それは次の結果を生成します-
Max value is : 200
関数の引数
関数が引数を使用する場合、引数の値を受け入れる変数を宣言する必要があります。 これらの変数は、関数の*仮パラメータ*と呼ばれます。
仮パラメータは、関数内の他のローカル変数のように動作し、関数に入ると作成され、終了すると破棄されます。
関数を呼び出している間、引数を関数に渡すことができる2つの方法があります-
Sr.No | Call Type & Description |
---|---|
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などのプリミティブデータ型を使用します。 数値データ型、その可能な値、および数値範囲については、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 | Function & Purpose |
---|---|
1 |
double cos(double); この関数は、角度(double)を取り、コサインを返します。 |
2 |
double sin(double); この関数は、角度(二重)を取り、サインを返します。 |
3 |
double tan(double); この関数は、角度(二重)を取り、タンジェントを返します。 |
4 |
double log(double); この関数は数値を受け取り、その数値の自然対数を返します。 |
5 |
double pow(double, double); 最初の数字は上げたい数字で、2番目の数字はそれを上げたい力です。 |
6 |
double hypot(double, double); この関数に直角三角形の2辺の長さを渡すと、斜辺の長さが返されます。 |
7 |
double sqrt(double); この関数に数値を渡すと、平方根が得られます。 |
8 |
int abs(int); この関数は、渡される整数の絶対値を返します。 |
9 |
double fabs(double); この関数は、渡された10進数の絶対値を返します。 |
10 |
double floor(double); 渡された引数以下の整数を見つけます。 |
以下は、数学的な操作のいくつかを示すための簡単な例です-
#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 ++の乱数
乱数を生成したい場合が多くあります。 実際には、乱数生成について知っておく必要がある関数が2つあります。 最初は* 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などの個々の変数を宣言する代わりに、numbersなどの1つの配列変数を宣言し、numbers [0]、numbers [1]、…、numbers [99]を使用して表現します個々の変数。 配列内の特定の要素は、インデックスによってアクセスされます。
すべての配列は、連続したメモリ位置で構成されています。 最下位アドレスは最初の要素に対応し、最上位アドレスは最後の要素に対応します。
配列の宣言
C ++で配列を宣言するために、プログラマは次のように要素の型と配列に必要な要素の数を指定します-
type arrayName [ arraySize ];
これは、単一次元配列と呼ばれます。 arraySize はゼロより大きい整数定数でなければならず、 type は任意の有効なC ++データ型にすることができます。 たとえば、double型のbalanceと呼ばれる10要素の配列を宣言するには、このステートメントを使用します-
double balance[10];
配列の初期化
あなたはC ++配列要素を1つずつ、または次のように単一のステートメントを使用して初期化できます-
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 ^ th ^に値50.0を割り当てます。 4 ^ th ^インデックスの配列は5 ^ th ^、つまり最後の要素になります。これは、すべての配列がベースインデックスとも呼ばれる最初の要素のインデックスとして0を持っているためです。 以下は、私たちが上で議論したのと同じ配列の絵の表現です-
配列要素へのアクセス
配列名にインデックスを付けることにより、要素にアクセスします。 これは、配列の名前の後に角かっこ内に要素のインデックスを配置することによって行われます。 たとえば-
double salary = balance[9];
上記のステートメントは、配列から10番目の要素を取得し、その値を給与変数に割り当てます。 以下は、上記の3つの概念すべてを使用する例です。 配列の宣言、割り当て、アクセス-
#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 | Concept & Description |
---|---|
1 |
C ++は多次元配列をサポートしています。 多次元配列の最も単純な形式は、2次元配列です。 |
2 |
インデックスなしで配列名を指定するだけで、配列の最初の要素へのポインタを生成できます。 |
3 |
インデックスなしで配列の名前を指定することで、関数に配列へのポインタを渡すことができます。 |
4 |
C ++では、関数が配列を返すことができます。 |
C ++文字列
C ++は、次の2種類の文字列表現を提供します-
- Cスタイルの文字列。
- 標準C ++で導入された文字列クラスタイプ。
Cスタイルの文字列
Cスタイルの文字列は、C言語内で作成され、C ++内で引き続きサポートされます。 この文字列は、実際には null 文字「\ 0」で終了する文字の1次元配列です。 したがって、nullで終わる文字列には、 null が後に続く文字列を構成する文字が含まれます。
次の宣言と初期化により、「Hello」という単語で構成される文字列が作成されます。 配列の末尾にヌル文字を保持するために、ストリングを含む文字配列のサイズは、「Hello」という単語の文字数よりも1つ多くなります。
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
あなたが配列の初期化のルールに従う場合は、次のように上記のステートメントを書くことができます-
char greeting[] = "Hello";
以下は、C/C ++で上記で定義された文字列のメモリ表示です-
実際には、文字列定数の末尾にヌル文字を配置しません。 C ++コンパイラは、配列を初期化するときに、文字列の末尾に「\ 0」を自動的に配置します。 上記の文字列を印刷してみましょう-
#include <iostream>
using namespace std;
int main () {
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << "Greeting message: ";
cout << greeting << endl;
return 0;
}
上記のコードをコンパイルして実行すると、次の結果が生成されます-
Greeting message: Hello
C ++は、nullで終わる文字列を操作する幅広い機能をサポートしています-
Sr.No | Function & Purpose |
---|---|
1 |
strcpy(s1, s2); 文字列s2を文字列s1にコピーします。 |
2 |
strcat(s1, s2); 文字列s2を文字列s1の末尾に連結します。 |
3 |
strlen(s1); 文字列s1の長さを返します。 |
4 |
strcmp(s1, s2); s1とs2が同じ場合は0を返します。 s1 <s2の場合、0未満。 s1> s2の場合、0より大きい。 |
5 |
strchr(s1, ch); 文字列s1に最初に現れる文字chへのポインターを返します。 |
6 |
strstr(s1, s2); 文字列s1内で文字列s2が最初に現れる場所へのポインタを返します。 |
次の例では、上記の機能のいくつかを利用しています-
#include <iostream>
#include <cstring>
using namespace std;
int main () {
char str1[10] = "Hello";
char str2[10] = "World";
char str3[10];
int len ;
//copy str1 into str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
//concatenates str1 and str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
//total lenghth of str1 after concatenation
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
return 0;
}
上記のコードをコンパイルして実行すると、次のような結果が生成されます-
strcpy( str3, str1) : Hello
strcat( str1, str2): HelloWorld
strlen(str1) : 10
C ++の文字列クラス
標準C ++ライブラリは、上記のすべての操作をサポートする string クラスタイプを提供し、さらに多くの機能を提供します。 私たちは次の例をチェックしましょう-
#include <iostream>
#include <string>
using namespace std;
int main () {
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
//copy str1 into str3
str3 = str1;
cout << "str3 : " << str3 << endl;
//concatenates str1 and str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
//total length of str3 after concatenation
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
上記のコードをコンパイルして実行すると、次のような結果が生成されます-
str3 : Hello
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;
ここで、 type はポインターの基本型です。有効な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
すべてのポインターの値の実際のデータ型は、整数、浮動小数点、文字、またはその他のいずれであっても同じで、メモリアドレスを表す長い16進数です。 異なるデータ型のポインターの唯一の違いは、ポインターが指す変数または定数のデータ型です。
C ++でのポインターの使用
重要な操作はほとんどなく、非常に頻繁にポインターを使用します。 *(a)*ポインター変数を定義します。 *(b)*変数のアドレスをポインターに割り当てます。 *(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 | Concept & Description |
---|---|
1 |
C ++は、いくつかの標準ライブラリで定義されたゼロの値を持つ定数であるヌルポインターをサポートしています。 |
2 |
ポインターで使用できる4つの算術演算子があります:+、-、、- |
3 |
ポインターと配列の間には密接な関係があります。 |
4 |
配列を定義して、多数のポインターを保持できます。 |
5 |
C ++では、ポインターなどにポインターを置くことができます。 |
6 |
参照またはアドレスの両方で引数を渡すと、呼び出された関数によって、呼び出された関数で渡された引数を変更できます。 |
7 |
C ++では、関数がローカル変数、静的変数、および動的に割り当てられたメモリへのポインターも返すことができます。 |
C ++リファレンス
参照変数はエイリアスです。つまり、既存の変数の別の名前です。 参照が変数で初期化されると、変数を参照するために変数名または参照名のいずれかを使用できます。
参照とポインター
参照はしばしばポインタと混同されますが、参照とポインタの3つの大きな違いは-
- NULL参照はできません。 参照が正当なストレージに接続されていると常に想定できる必要があります。
- 参照がオブジェクトに初期化されると、他のオブジェクトを参照するように変更することはできません。 ポインターはいつでも別のオブジェクトを指すことができます。
- 参照は作成時に初期化する必要があります。 ポインターはいつでも初期化できます。
C ++での参照の作成
変数名は、メモリ内の変数の場所に付けられたラベルと考えてください。 参照は、そのメモリロケーションに添付された2番目のラベルと考えることができます。 したがって、元の変数名または参照を使用して変数の内容にアクセスできます。 たとえば、次の例があるとします-
int i = 17;
次のように、iの参照変数を宣言できます。
int& r = i;
これらの宣言の&を*参照*として読んでください。 したがって、最初の宣言を「rはiに初期化された整数参照」として読み取り、2番目の宣言は「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 参照に関連する2つの重要な主題を次に示します-
Sr.No | Concept & Description |
---|---|
1 |
C ++は、パラメーターよりも安全に関数パラメーターとして参照を渡すことをサポートしています。 |
2 |
他のデータ型と同様に、C ++関数から参照を返すことができます。 |
C ++の日付と時刻
C 標準ライブラリは、適切な日付型を提供しません。 C は、日付と時刻を操作するための構造体と関数をCから継承します。 日付と時刻に関連する関数と構造にアクセスするには、C ++プログラムに<ctime>ヘッダーファイルを含める必要があります。
4つの時間関連タイプがあります: 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 | Function & Purpose |
---|---|
1 |
time_t time(time_t *time); これは、システムの現在のカレンダー時刻を1970年1月1日から経過した秒数で返します。 システムに時間がない場合、.1が返されます。 |
2 |
char *ctime(const time_t *time); これは、_day month year hours:minutes:seconds year \ 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); これは、timeが指す構造体で見つかった時刻に相当するカレンダー時刻を返します。 |
8 |
double difftime ( time_t time2, time_t time1 ); この関数は、time1とtime2の差を秒単位で計算します。 |
9 |
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:" << 1900 + 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:1563027637
Year2019
Month: 7
Day: 13
Time: 15:21:38
C ++基本入出力
C 標準ライブラリは、後続の章で説明する広範な入出力機能のセットを提供します。 この章では、C プログラミングに必要な非常に基本的で最も一般的なI/O操作について説明します。
C ++ I/Oは、バイトシーケンスであるストリームで発生します。 キーボード、ディスクドライブ、ネットワーク接続などのデバイスからバイトが流れる場合 メインメモリに対しては、これは*入力操作*と呼ばれ、バイトがメインメモリからディスプレイ画面、プリンタ、ディスクドライブ、またはネットワーク接続などのデバイスに流れる場合、これは*出力操作*と呼ばれます。
I/Oライブラリヘッダーファイル
C ++プログラムにとって重要な以下のヘッダーファイルがあります-
Sr.No | Header File & Function and Description |
---|---|
1 |
<iostream> このファイルは、 cin、cout、cerr 、および clog オブジェクトを定義します。これらはそれぞれ、標準入力ストリーム、標準出力ストリーム、バッファリングされていない標準エラーストリーム、バッファリングされた標準エラーストリームに対応します。 |
2 |
<iomanip> このファイルは、 setw や setprecision などのいわゆるパラメーター化されたストリームマニピュレーターでフォーマットされたI/Oを実行するのに役立つサービスを宣言します。 |
3 |
<fstream> このファイルは、ユーザー制御のファイル処理用のサービスを宣言します。 これについては、ファイルおよびストリーム関連の章で詳しく説明します。 |
標準出力ストリーム(cout)
事前定義オブジェクト cout は、 ostream クラスのインスタンスです。 coutオブジェクトは、通常は表示画面である標準出力デバイスに「接続」されていると言われています。 cout は、次の例に示すように、2つの小なり記号である<<と書かれたストリーム挿入演算子と組み合わせて使用されます。
#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 ++コンパイラは、出力する変数のデータ型も決定し、適切なストリーム挿入演算子を選択して値を表示します。 <<演算子は、整数、浮動小数点、倍精度、文字列、およびポインター値の組み込み型のデータ項目を出力するためにオーバーロードされます。
挿入演算子<<は、上記のように1つのステートメントで複数回使用でき、 endl を使用して行末に改行を追加します。
標準入力ストリーム(cin)
定義済みオブジェクト cin は、 istream クラスのインスタンスです。 cinオブジェクトは、通常はキーボードである標準入力デバイスに接続されていると言われています。 cin は、次の例に示すように、>>と表記される2つのより大記号であるストリーム抽出演算子とともに使用されます。
#include <iostream>
using namespace std;
int main() {
char name[50];
cout << "Please enter your name: ";
cin >> name;
cout << "Your name is: " << name << endl;
}
上記のコードをコンパイルして実行すると、名前の入力を求めるプロンプトが表示されます。 あなたは値を入力し、次の結果を見るためにEnterキーを押します-
Please enter your name: cplusplus
Your name is: cplusplus
C ++コンパイラは、入力された値のデータ型も判別し、適切なストリーム抽出演算子を選択して値を抽出し、指定された変数に格納します。
ストリーム抽出演算子>>は、1つのステートメントで複数回使用できます。 複数のデータムを要求するには、次を使用することができます-
cin >> name >> age;
これは、次の2つのステートメントに相当します-
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)
定義済みオブジェクト clog は ostream クラスのインスタンスです。 clogオブジェクトは標準エラーデバイスに接続されていると言われます。これは表示画面でもありますが、オブジェクト clog はバッファリングされます。 つまり、clogに挿入するたびに、バッファがいっぱいになるか、バッファがフラッシュされるまで、出力がバッファに保持される可能性があります。
*clog* は、次の例に示すように、ストリーム挿入演算子とともに使用されます。
#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ストリームを使用してエラーメッセージを表示することをお勧めします。他のログメッセージを表示する場合は、clogを使用する必要があります。
C ++データ構造
C/C ++配列を使用すると、同じ種類の複数のデータ項目を結合する変数を定義できますが、 structure は別の種類のデータ項目を結合できるユーザー定義のデータ型です。
構造はレコードを表すために使用されます。図書館で本を追跡したいとします。 あなたは、各本に関する次の属性を追跡することができます-
- タイトル
- 著者
- 件名
- ブックID
構造の定義
構造を定義するには、structステートメントを使用する必要があります。 structステートメントは、プログラムの複数のメンバーを持つ新しいデータ型を定義します。 構造体ステートメントの形式はこれです-
struct [structure tag] {
member definition;
member definition;
...
member definition;
} [one or more structure variables];
- 構造タグ*はオプションであり、各メンバー定義はint iなどの通常の変数定義です。またはfloat f;または他の有効な変数定義。 構造の定義の最後で、最後のセミコロンの前に、1つ以上の構造変数を指定できますが、これはオプションです。 ここにあなたが本の構造を宣言する方法があります-
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
構造体メンバーへのアクセス
構造体のメンバーにアクセスするには、* memberアクセス演算子(。)を使用します。 メンバーアクセス演算子は、構造変数名とアクセスする構造メンバーの間のピリオドとしてコーディングされます。 *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_を直接使用して、structキーワードを使用せずに_Books_タイプの変数を定義できます。 以下は例です-
Books Book1, Book2;
次のように非構造体に typedef キーワードを使用できます-
typedef long int *pint32;
pint32 x, y, z;
x、y、zはすべてlong intへのポインターです。
C ++クラスとオブジェクト
C プログラミングの主な目的は、Cプログラミング言語にオブジェクト指向を追加することです。クラスは、オブジェクト指向プログラミングをサポートし、多くの場合ユーザー定義型と呼ばれるC の中心的な機能です。
クラスはオブジェクトの形式を指定するために使用され、データ表現とそのデータを1つのきれいなパッケージに操作するためのメソッドを組み合わせます。 クラス内のデータと関数は、クラスのメンバーと呼ばれます。
C ++クラス定義
クラスを定義するときには、データ型の設計図を定義します。 これは実際にはデータを定義しませんが、クラス名が何を意味するのか、つまりクラスのオブジェクトが何を構成するのか、そしてそのようなオブジェクトに対して実行できる操作は定義します。
クラス定義は、キーワード class で始まり、その後にクラス名が続きます。クラス本体は、中括弧のペアで囲まれています。 クラス定義の後には、セミコロンまたは宣言のリストを続ける必要があります。 たとえば、次のようにキーワード class を使用してBoxデータ型を定義しました-
class Box {
public:
double length; //Length of a box
double breadth; //Breadth of a box
double height; //Height of a box
};
キーワード public は、それに続くクラスのメンバーのアクセス属性を決定します。 パブリックメンバーは、クラスオブジェクトの範囲内であればどこからでもクラスの外部からアクセスできます。 また、サブセクションで説明する private または protected としてクラスのメンバーを指定することもできます。
C ++オブジェクトを定義する
クラスはオブジェクトの設計図を提供するため、基本的にオブジェクトはクラスから作成されます。 基本型の変数を宣言するのとまったく同じ種類の宣言でクラスのオブジェクトを宣言します。 次のステートメントは、クラスBoxの2つのオブジェクトを宣言します-
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 | Concept & Description |
---|---|
1 |
クラスのメンバー関数は、他の変数と同様に、クラス定義内にその定義またはプロトタイプを持つ関数です。 |
2 |
クラスメンバーは、public、private、またはprotectedとして定義できます。 デフォルトでは、メンバーはプライベートと見なされます。 |
3 |
クラスコンストラクターは、クラスの新しいオブジェクトが作成されたときに呼び出されるクラス内の特別な関数です。 デストラクタも、作成されたオブジェクトが削除されるときに呼び出される特別な関数です。 |
4 |
コピーコンストラクターは、以前に作成された同じクラスのオブジェクトで初期化することによりオブジェクトを作成するコンストラクターです。 |
5 |
|
6 |
インライン関数を使用すると、コンパイラーは、関数の呼び出しの代わりに関数の本体のコードを展開しようとします。 |
7 |
すべてのオブジェクトには、オブジェクト自体を指す特別なポインター this があります。 |
8 |
クラスへのポインターは、構造体へのポインターとまったく同じ方法で実行されます。 実際、クラスは実際には機能を備えた単なる構造体です。 |
9 |
クラスのデータメンバーと関数メンバーの両方を静的として宣言できます。 |
C ++の継承
オブジェクト指向プログラミングで最も重要な概念の1つは、継承の概念です。 継承を使用すると、クラスを別のクラスの観点から定義でき、アプリケーションの作成と保守が簡単になります。 これにより、コード機能を再利用して実装時間を短縮することもできます。
クラスを作成するとき、プログラマは完全に新しいデータメンバーとメンバー関数を記述する代わりに、新しいクラスが既存のクラスのメンバーを継承するように指定できます。 この既存のクラスは base クラスと呼ばれ、新しいクラスは derived クラスと呼ばれます。
継承の概念は、 is a 関係を実装します。 たとえば、哺乳類IS-A動物、犬IS-A哺乳類、したがって犬IS-A動物などです。
基本クラスと派生クラス
クラスは複数のクラスから派生できます。つまり、複数の基本クラスからデータと関数を継承できます。 派生クラスを定義するには、クラス派生リストを使用して基本クラスを指定します。 クラス派生リストは、1つまたは複数のベースクラスに名前を付け、形式があります-
class derived-class: access-specifier base-class
ここで、access-specifierは* public、protected、または *private のいずれかであり、base-classは以前に定義されたクラスの名前です。 access-specifierが使用されていない場合、デフォルトではprivateです。
次のように基本クラス*形状*とその派生クラス*長方形*を考えてください-
#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
アクセス制御と継承
派生クラスは、その基本クラスのすべての非プライベートメンバーにアクセスできます。 したがって、派生クラスのメンバー関数にアクセスできないはずの基本クラスメンバーは、基本クラスでprivateとして宣言する必要があります。
に応じてさまざまなアクセスタイプを要約できます-誰が次の方法でアクセスできるか-
Access | public | protected | private |
---|---|---|---|
Same class | yes | yes | yes |
Derived classes | yes | yes | no |
Outside classes | yes | no | no |
派生クラスは、次の例外を除いてすべての基本クラスのメソッドを継承します-
- 基本クラスのコンストラクタ、デストラクタ、およびコピーコンストラクタ。
- 基本クラスのオーバーロードされた演算子。
- 基本クラスのフレンド関数。
継承のタイプ
基本クラスからクラスを派生させる場合、基本クラスは public、protected 、または private 継承を介して継承される場合があります。 継承のタイプは、上記で説明したようにaccess-specifierによって指定されます。
*protected* または *private* 継承はほとんど使用しませんが、 *public* 継承が一般的に使用されます。 異なるタイプの継承を使用している間、次のルールが適用されます-
- パブリック継承-パブリック*基本クラスからクラスを派生させると、ベースクラスの*パブリック*メンバーは派生クラスの*パブリック*メンバーになり、ベースクラスの*保護*メンバーは*保護*メンバーになります派生クラス。 基本クラスの *private メンバーは、派生クラスから直接アクセスすることはできませんが、基本クラスの public および protected メンバーの呼び出しを介してアクセスできます。
- Protected Inheritance - protected 基本クラスから派生した場合、基本クラスの public および protected メンバーは、派生クラスの protected メンバーになります。
- Private Inheritance - private 基本クラスから派生する場合、基本クラスの public および protected メンバーは派生クラスの private メンバーになります。
多重継承
C ++クラスは、複数のクラスからメンバーを継承できます。ここに拡張構文があります-
class derived-class: access baseA, access baseB....
アクセスは* public、protected、、または *private のいずれかであり、すべての基本クラスに与えられ、上記のようにコンマで区切られます。 私たちは次の例を試してみましょう-
#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 ++では、同じスコープ内の*関数*名または*演算子*に対して複数の定義を指定できます。これらは、それぞれ*関数のオーバーロード*および*演算子のオーバーロード*と呼ばれます。
オーバーロードされた宣言は、同じスコープ内で以前に宣言された宣言と同じ名前で宣言された宣言です。ただし、両方の宣言に異なる引数と明らかに異なる定義(実装)があります。
オーバーロードされた function または operator を呼び出すと、コンパイラは、関数または演算子の呼び出しに使用した引数の型を定義で指定されたパラメーターの型と比較することにより、使用する最も適切な定義を決定します。 最も適切なオーバーロード関数または演算子を選択するプロセスは、*オーバーロード解決*と呼ばれます。
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&);
2つのBoxオブジェクトを*追加*するために使用できる加算演算子を宣言し、最終的なBoxオブジェクトを返します。 ほとんどのオーバーロード演算子は、通常の非メンバー関数またはクラスメンバー関数として定義できます。 上記の関数をクラスの非メンバー関数として定義する場合、次のように各オペランドに2つの引数を渡す必要があります-
Box operator+(const Box&, const Box&);
以下は、メンバー関数を使用してオーバーロードする演算子の概念を示す例です。 ここでは、オブジェクトが引数として渡され、そのプロパティはこのオブジェクトを使用してアクセスされます。この演算子を呼び出すオブジェクトは、以下で説明するように this 演算子を使用してアクセスできます-
#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
オーバーロード可能/非オーバーロード可能演算子
以下は、オーバーロードできる演算子のリストです-
+ | - | * | / | % | ^ |
& | ~ | ! | , | ||
= | < | > | ⇐ | >= | ++ |
— | << | >> | == | != | && |
+= | -= | /= | |||
%= | ^= | &= | = | *= | |
<⇐ | >>= | [] | () | → | →* |
以下は、オーバーロードすることはできません演算子のリストです-
:: | .* | . | ?: |
演算子のオーバーロードの例
ここに、概念を理解するのに役立つさまざまな演算子オーバーロードの例を示します。
Sr.No | Operators & Example |
---|---|
1 | Unary Operators Overloading |
2 | Binary Operators Overloading |
3 | Relational Operators Overloading |
4 | Input/Output Operators Overloading |
5 | ++ and — Operators Overloading |
6 | Assignment Operators Overloading |
7 | Function call () Operator Overloading |
8 | Subscripting [ Operator Overloading] |
9 | Class Member Access Operator → Overloading |
C ++の多態性
「多態性」という言葉は、多くの形式を持つことを意味します。 通常、ポリモーフィズムは、クラスの階層があり、それらが継承によって関連付けられている場合に発生します。
C ++ポリモーフィズムとは、メンバー関数を呼び出すと、その関数を呼び出すオブジェクトのタイプに応じて異なる関数が実行されることを意味します。
基本クラスが他の2つのクラスによって導出された次の例を考えてください-
#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()関数はプログラムのコンパイル中に設定されるため、これは「初期バインディング」とも呼ばれます。
しかし、今、私たちのプログラムに少し変更を加えて、Shapeクラスのarea()の宣言の前にキーワード 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クラスのオブジェクトのアドレスは* shapeに格納されるため、それぞれのarea()関数が呼び出されます。
ご覧のとおり、各子クラスには、関数area()の個別の実装があります。 これが、*多態性*の一般的な使用方法です。 同じ名前の関数、さらには同じパラメーターを持つ異なるクラスがありますが、実装は異なります。
仮想機能
*virtual* 関数は、キーワード *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は、関数にボディがなく、上記の仮想関数が pure virtual function と呼ばれることをコンパイラーに伝えます。
C ++のデータ抽象化
データの抽象化とは、重要な情報のみを外部に提供し、その背景の詳細を隠すこと、つまり、詳細を提示せずにプログラムで必要な情報を表すことです。
データ抽象化は、インターフェイスと実装の分離に依存するプログラミング(および設計)手法です。
テレビの実際の例を1つ見てみましょう。テレビのオン/オフ、チャンネルの変更、音量の調整、スピーカー、VCR、DVDプレーヤーなどの外部コンポーネントの追加が可能ですが、内部の詳細はわかりません。つまり、空中またはケーブル経由で信号を受信する方法、信号を変換し、最終的に画面に表示する方法がわかりません。
したがって、テレビは内部実装を外部インターフェイスから明確に分離していると言えます。電源ボタン、チャンネルチェンジャー、ボリュームコントロールなどのインターフェイスは、内部の知識がなくても再生できます。
C ++では、クラスは優れたレベルの*データ抽象化*を提供します。 これらは、オブジェクトの機能を操作したり、オブジェクトデータ(つまり、クラスが内部的にどのように実装されているかを実際に知らない状態)を操作するのに十分なパブリックメソッドを外部に提供します。
たとえば、プログラムは、関数が実際に使用して特定の値をソートするアルゴリズムを知らなくても、* sort()*関数を呼び出すことができます。 実際、ソート機能の基礎となる実装はライブラリのリリース間で変更される可能性があり、インターフェースが同じである限り、関数呼び出しは引き続き機能します。
C ++では、 classes を使用して独自の抽象データ型(ADT)を定義します。 クラス ostream の cout オブジェクトを使用して、次のようにデータを標準出力にストリーミングできます-
#include <iostream>
using namespace std;
int main() {
cout << "Hello C++" <<endl;
return 0;
}
ここでは、 cout がユーザーの画面にテキストを表示する方法を理解する必要はありません。 パブリックインターフェイスのみを知っていればよく、「cout」の基礎となる実装は自由に変更できます。
アクセスラベルが抽象化を強制する
C ++では、アクセスラベルを使用して、クラスへの抽象インターフェイスを定義します。 クラスには、0個以上のアクセスラベルを含めることができます-
- 公開ラベルで定義されたメンバーは、プログラムのすべての部分からアクセスできます。 型のデータ抽象化ビューは、そのパブリックメンバーによって定義されます。
- プライベートラベルで定義されたメンバーは、クラスを使用するコードからアクセスできません。 プライベートセクションは、そのタイプを使用するコードから実装を隠します。
アクセスラベルが表示される頻度に制限はありません。 各アクセスラベルは、後続のメンバー定義のアクセスレベルを指定します。 指定されたアクセスレベルは、次のアクセスラベルが検出されるか、クラス本体の右中括弧が表示されるまで有効です。
データ抽象化の利点
データの抽象化には2つの重要な利点があります-
- クラス内部は、オブジェクトの状態を破壊する可能性のある不注意なユーザーレベルのエラーから保護されています。
- クラスの実装は、ユーザーレベルのコードを変更することなく、要件の変更やバグレポートに応じて時間とともに進化する場合があります。
クラスのprivateセクションでのみデータメンバーを定義することにより、クラスの作成者はデータを自由に変更できます。 実装が変更された場合は、クラスコードのみを調べて、変更の影響を確認する必要があります。 データが公開されている場合、古い表現のデータメンバーに直接アクセスする関数は破損する可能性があります。
データ抽象化の例
パブリックメンバーとプライベートメンバーを持つクラスを実装する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 は外界へのインターフェースであり、ユーザーはクラスを使用するためにそれらを知る必要があります。 プライベートメンバー total は、ユーザーが知る必要はありませんが、クラスが適切に動作するために必要です。
戦略の設計
抽象化は、コードをインターフェースと実装に分離します。 したがって、コンポーネントの設計中は、基礎となる実装を変更してもインターフェースが損なわれないように、インターフェースを実装に依存しないようにする必要があります。
この場合、これらのインターフェースを使用しているプログラムが何であれ、それらは影響を受けず、最新の実装で再コンパイルする必要があります。
C ++でのデータのカプセル化
すべてのC ++プログラムは、次の2つの基本的な要素で構成されています-
- プログラム文(コード)-これは、アクションを実行するプログラムの一部であり、関数と呼ばれます。
- プログラムデータ-データは、プログラム機能の影響を受けるプログラムの情報です。
カプセル化は、オブジェクト指向プログラミングの概念であり、データとデータを操作する機能を結び付け、外部の干渉や誤用から安全に保ちます。 データのカプセル化により、*データ隠蔽*という重要なOOPコンセプトが生まれました。
- データのカプセル化*はデータをバンドルするメカニズムであり、それらを使用する機能と*データの抽象化*はインターフェースのみを公開し、実装の詳細をユーザーから隠すメカニズムです。
C ++は、 classes と呼ばれるユーザー定義型の作成を通じて、カプセル化とデータ隠蔽のプロパティをサポートします。 クラスには、 private、protected 、および public メンバーを含めることができることを既に検討しました。 デフォルトでは、クラスで定義されているすべてのアイテムはプライベートです。 たとえば-
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
};
変数の長さ、幅、高さは private です。 つまり、それらはBoxクラスの他のメンバーのみがアクセスでき、プログラムの他の部分はアクセスできません。 これは、カプセル化を実現する1つの方法です。
クラスの一部を public (つまり、プログラムの他の部分からアクセス可能)にするには、 public キーワードの後に宣言する必要があります。 public指定子の後に定義されたすべての変数または関数は、プログラム内の他のすべての関数からアクセスできます。
あるクラスを別のクラスのフレンドにすると、実装の詳細が明らかになり、カプセル化が減少します。 理想は、各クラスの詳細をできるだけ他のすべてのクラスから隠しておくことです。
データのカプセル化の例
パブリックメンバーとプライベートメンバーを持つクラスを実装する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 は外部世界へのインターフェイスであり、ユーザーはクラスを使用するためにそれらを知る必要があります。 プライベートメンバー total は、外部からは隠されていますが、クラスが適切に動作するために必要です。
戦略の設計
私たちのほとんどは、クラスメンバーを公開する必要がない限り、デフォルトでクラスメンバーをプライベートにすることを学びました。 それはちょうど良い*カプセル化*です。
これはデータメンバーに最も頻繁に適用されますが、仮想関数を含むすべてのメンバーに等しく適用されます。
C ++のインターフェイス(抽象クラス)
インターフェイスは、C ++クラスの特定の実装をコミットせずに、そのクラスの動作または機能を記述します。
C ++インターフェースは* abstractクラス*を使用して実装されます。これらの抽象クラスは、実装の詳細を関連データから分離する概念であるデータ抽象化と混同しないでください。
クラスは、その関数の少なくとも1つを pure virtual 関数として宣言することにより抽象化されます。 純粋な仮想関数は、次のように宣言に「= 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()の観点からインターフェースをどのように定義し、他の2つのクラスが同じ機能を実装したが、形状に固有の面積を計算するアルゴリズムが異なることがわかります。
戦略の設計
オブジェクト指向システムは、抽象基本クラスを使用して、すべての外部アプリケーションに適した共通の標準化されたインターフェースを提供します。 次に、その抽象基本クラスからの継承を通じて、同様に動作する派生クラスが形成されます。
外部アプリケーションによって提供される機能(つまり、パブリック関数)は、抽象基本クラスの純粋な仮想関数として提供されます。 これらの純粋な仮想関数の実装は、アプリケーションの特定のタイプに対応する派生クラスで提供されます。
また、このアーキテクチャにより、システムが定義された後でも、新しいアプリケーションをシステムに簡単に追加できます。
C ++ファイルとストリーム
これまで、 iostream 標準ライブラリを使用してきました。これは、それぞれ標準入力からの読み取りと標準出力への書き込みのための cin および cout メソッドを提供します。
このチュートリアルでは、ファイルの読み取りおよび書き込み方法について説明します。 これには、3つの新しいデータ型を定義する fstream という別の標準C ++ライブラリが必要です-
Sr.No | Data Type & Description |
---|---|
1 |
ofstream このデータ型は出力ファイルストリームを表し、ファイルの作成およびファイルへの情報の書き込みに使用されます。 |
2 |
ifstream このデータ型は入力ファイルストリームを表し、ファイルから情報を読み取るために使用されます。 |
3 |
fstream このデータ型は一般にファイルストリームを表し、ofstreamとifstreamの両方の機能を備えています。つまり、ファイルを作成し、ファイルに情報を書き込み、ファイルから情報を読み取ることができます。 |
C でファイル処理を実行するには、ヘッダーファイル<iostream>および<fstream>をC ソースファイルに含める必要があります。
ファイルを開く
ファイルは、読み取りまたは書き込みを行う前に開く必要があります。 ofstream または fstream オブジェクトを使用して、ファイルを書き込み用に開くことができます。 また、ifstreamオブジェクトは、読み取り専用のファイルを開くために使用されます。
以下は、fstream、ifstream、およびofstreamオブジェクトのメンバーであるopen()関数の標準構文です。
void open(const char *filename, ios::openmode mode);
ここで、最初の引数は開くファイルの名前と場所を指定し、* open()*メンバー関数の2番目の引数はファイルを開くモードを定義します。
Sr.No | Mode Flag & Description |
---|---|
1 |
ios::app 追加モード。 そのファイルへのすべての出力は、末尾に追加されます。 |
2 |
ios::ate 出力用のファイルを開き、読み取り/書き込みコントロールをファイルの最後に移動します。 |
3 |
ios::in 読み取り用にファイルを開きます。 |
4 |
ios::out 書き込み用にファイルを開きます。 |
5 |
ios::trunc ファイルが既に存在する場合、ファイルを開く前にその内容は切り捨てられます。 |
これらの値を2つ以上組み合わせるには、* OR *を組み合わせます。 たとえば、書き込みモードでファイルを開き、既に存在する場合に切り捨てたい場合は、次の構文になります-
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );
同様に、次のように目的の読み取りおよび書き込み用にファイルを開くことができます-
fstream afile;
afile.open("file.dat", ios::out | ios::in );
ファイルを閉じる
C ++プログラムが終了すると、すべてのストリームが自動的にフラッシュされ、割り当てられたすべてのメモリが解放され、開いているすべてのファイルが閉じられます。 ただし、プログラマーは、プログラムを終了する前に、開いているすべてのファイルを閉じることをお勧めします。
以下は、fstream、ifstream、およびofstreamオブジェクトのメンバーであるclose()関数の標準構文です。
void close();
ファイルへの書き込み
C ++プログラミングの実行中に、ストリーム挿入演算子(<<)を使用してプログラムからファイルに情報を書き込みます。その演算子を使用して画面に情報を出力します。 唯一の違いは、 cout オブジェクトの代わりに ofstream または fstream オブジェクトを使用することです。
ファイルからの読み取り
ストリーム抽出演算子(>>)を使用して、キーボードから情報を入力するのと同じように、ファイルから情報をプログラムに読み込みます。 唯一の違いは、 cin オブジェクトの代わりに ifstream または fstream オブジェクトを使用することです。
読み取りおよび書き込みの例
以下は、ファイルを読み取りおよび書き込みモードで開く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
上記の例では、外部から行を読み取るgetline()関数や、前のreadステートメントで残った余分な文字を無視するignore()関数など、cinオブジェクトの追加関数を使用します。
ファイル位置ポインター
*istream* と *ostream* の両方が、ファイル位置ポインターを再配置するためのメンバー関数を提供します。 これらのメンバー関数は、istreamでは *seekg* ( "seek get")、ostreamでは *seekp* ( "seek put")です。
- seekgとseekpの引数は通常、長整数です。 シークの方向を示すために、2番目の引数を指定できます。 シーク方向は、ストリームの先頭を基準とした位置決めの場合は *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 の3つのキーワードに基づいて構築されています。
- throw -問題が発生すると、プログラムは例外をスローします。 これは、 throw キーワードを使用して行われます。
- catch -プログラムは、問題を処理するプログラム内の場所で例外ハンドラーを使用して例外をキャッチします。 catch キーワードは、例外のキャッチを示します。
- try - try ブロックは、特定の例外がアクティブになるコードのブロックを識別します。 その後に、1つ以上のcatchブロックが続きます。
ブロックが例外を発生させると仮定すると、メソッドは 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
}
*try* ブロックが異なる状況で複数の例外を発生させた場合に、複数の *catch* ステートメントをリストして、異なるタイプの例外をキャッチできます。
例外を投げる
*throw* ステートメントを使用して、コードブロック内のどこにでも例外をスローできます。 throwステートメントのオペランドは例外のタイプを決定し、任意の式にすることができ、式の結果のタイプはスローされる例外のタイプを決定します。
以下は、ゼロ条件による除算が発生したときに例外をスローする例です-
double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}
例外をキャッチする
*try* ブロックに続く *catch* ブロックは、例外をキャッチします。 キャッチする例外のタイプを指定できます。これは、キーワードcatchに続く括弧内に表示される例外宣言によって決まります。
try {
//protected code
} catch( ExceptionName e ) {
//code to handle ExceptionName exception
}
上記のコードは、 ExceptionName タイプの例外をキャッチします。 あなたがキャッチブロックが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* *型の例外を発生させているため、この例外をキャッチする際に、catchブロックでconst char *を使用する必要があります。 上記のコードをコンパイルして実行すると、次の結果が生成されます-
Division by zero condition!
C ++標準例外
C ++は、プログラムで使用できる <exception> で定義された標準例外のリストを提供します。 これらは、以下に示す親子クラス階層に配置されています-
ここに、上記の階層で言及された各例外の簡単な説明があります-
Sr.No | Exception & Description |
---|---|
1 |
std::exception すべての標準C ++例外の例外と親クラス。 |
2 |
std::bad_alloc これは new によってスローされます。 |
3 |
std::bad_cast これは dynamic_cast によってスローされます。 |
4 |
std::bad_exception これは、C ++プログラムで予期しない例外を処理するのに便利なデバイスです。 |
5 |
std::bad_typeid これは typeid によってスローされます。 |
6 |
std::logic_error コードを読み取ることで理論的に検出できる例外。 |
7 |
std::domain_error これは、数学的に無効なドメインが使用された場合にスローされる例外です。 |
8 |
std::invalid_argument これは無効な引数のためにスローされます。 |
9 |
std::length_error
|
10 |
std::out_of_range
|
11 |
std::runtime_error コードを読み取っても理論的に検出できない例外。 |
12 |
std::overflow_error これは、数学的なオーバーフローが発生した場合にスローされます。 |
13 |
std::range_error これは、範囲外の値を保存しようとしたときに発生します。 |
14 |
std::underflow_error これは、数学的なアンダーフローが発生した場合にスローされます。 |
新しい例外を定義する
- exception クラスの機能を継承およびオーバーライドすることにより、独自の例外を定義できます。 以下は、標準的な方法で独自の例外を実装するために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 ++プログラムのメモリは2つの部分に分かれています-
- スタック-関数内で宣言されたすべての変数は、スタックからメモリを占有します。
- ヒープ-これはプログラムの未使用メモリであり、プログラムの実行時にメモリを動的に割り当てるために使用できます。
多くの場合、定義済み変数に特定の情報を格納するために必要なメモリの量を事前に認識しておらず、必要なメモリのサイズは実行時に決定できます。
割り当てられたスペースのアドレスを返すC ++の特別な演算子を使用して、特定のタイプの変数のヒープ内で実行時にメモリを割り当てることができます。 この演算子は new 演算子と呼ばれます。
動的に割り当てられたメモリがもう必要ない場合は、 delete 演算子を使用できます。これは、新しい演算子によって以前に割り当てられたメモリの割り当てを解除します。
新規および削除演算子
*new* 演算子を使用して任意のデータ型にメモリを動的に割り当てる一般的な構文は次のとおりです。
new data-type;
ここで、 data-type は、配列を含む組み込みデータ型、またはクラスまたは構造を含むユーザー定義のデータ型です。 組み込みのデータ型から始めましょう。 たとえば、double型へのポインターを定義し、実行時にメモリを割り当てるように要求できます。 私たちは次のステートメントで*新しい*演算子を使用してこれを行うことができます-
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);
}
Cの* malloc()*関数はまだC に存在しますが、malloc()関数の使用を避けることをお勧めします。 malloc()に対するnewの主な利点は、newがメモリを割り当てるだけでなく、C の主要な目的であるオブジェクトを構築することです。
動的に割り当てられた変数が不要になったと感じるときはいつでも、次のように「削除」演算子を使用して、フリーストアで占有しているメモリを解放できます-
delete pvalue; //Release memory pointed to by pvalue
上記の概念を入れて、「新規」と「削除」がどのように機能するかを示すために次の例を形成しましょう-
#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;
}
4つのBoxオブジェクトの配列を割り当てると、Simpleコンストラクターが4回呼び出され、同様にこれらのオブジェクトを削除するときに、デストラクターも同じ回数呼び出されます。
上記のコードをコンパイルして実行すると、次の結果が生成されます-
Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!
C ++の名前空間
同じクラスに同じ名前のZaraという2人の人物がいる場合を考えてみましょう。 彼らを明確に区別する必要があるときはいつでも、彼らが別の地域に住んでいるか、母親や父親の名前など、名前のような追加情報を使用する必要があります。
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
}
入れ子になった名前空間
名前空間は、次のように別の名前空間内の1つの名前空間を定義できるネストすることができます-
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テンプレート
テンプレートは汎用プログラミングの基礎であり、特定のタイプに依存しない方法でコードを記述する必要があります。
テンプレートは、汎用クラスまたは関数を作成するための青写真または式です。 イテレータやアルゴリズムなどのライブラリコンテナは一般的なプログラミングの例であり、テンプレートの概念を使用して開発されています。
*vector* など、各コンテナには単一の定義がありますが、たとえば *vector <int>* または *vector <string>* など、さまざまな種類のベクトルを定義できます。
テンプレートを使用して関数だけでなくクラスを定義することができます、それらがどのように機能するかを見てみましょう-
機能テンプレート
テンプレート関数定義の一般的な形式はここに示されています-
template <class type> ret-type func-name(parameter list) {
//body of function
}
ここで、typeは、関数が使用するデータ型のプレースホルダー名です。 この名前は、関数定義内で使用できます。
以下は、2つの値の最大値を返す関数テンプレートの例です-
#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 *ディレクティブを見ています。 このマクロは、ソースファイルにヘッダーファイルを含めるために使用されます。
#include、#define、#if、#else、#lineなど、C ++でサポートされるプリプロセッサディレクティブが多数あります。 重要な指令を見てみましょう-
#defineプリプロセッサ
- defineプリプロセッサディレクティブは、シンボリック定数を作成します。 記号定数は*マクロ*と呼ばれ、指令の一般的な形式は次のとおりです-
#define macro-name replacement-text
この行がファイルに表示されると、プログラムがコンパイルされる前に、そのファイル内の後続のすべてのマクロが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
条件付きコンパイル
プログラムのソースコードの選択部分をコンパイルするために使用できるディレクティブがいくつかあります。 このプロセスは条件付きコンパイルと呼ばれます。
条件付きプリプロセッサ構造は、「if」選択構造によく似ています。 次のプリプロセッサコードを考慮してください-
#ifndef NULL
#define NULL 0
#endif
デバッグ目的でプログラムをコンパイルできます。 また、次のように単一のマクロを使用してデバッグをオンまたはオフにすることができます-
#ifdef DEBUG
cerr <<"Variable x = " << x << endl;
#endif
これにより、ディレクティブ#ifdef DEBUGの前にシンボリック定数DEBUGが定義されている場合、 cerr ステートメントがプログラムでコンパイルされます。 あなたは次のようにプログラムの一部をコメントアウトするために#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;
- 演算子は、2つのトークンを連結するために使用されます。 ここに例があります-
#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 | Macro & Description |
---|---|
1 |
LINE これには、コンパイル中のプログラムの現在の行番号が含まれます。 |
2 |
FILE これには、コンパイル中のプログラムの現在のファイル名が含まれます。 |
3 |
DATE これには、ソースファイルをオブジェクトコードに変換した日付である月/日/年の形式の文字列が含まれます。 |
4 |
TIME これには、時間:分:秒という形式の文字列が含まれます。これは、プログラムがコンパイルされた時刻です。 |
上記のすべてのマクロの例を見てみましょう-
#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 ++シグナル処理
シグナルとは、プログラムを途中で終了させる可能性のあるオペレーティングシステムによってプロセスに配信される割り込みです。 UNIX、LINUX、Mac OS X、またはWindowsシステムでCtrl + Cを押すと、割り込みを生成できます。
プログラムでキャッチできないシグナルがありますが、プログラムでキャッチできるシグナルの以下のリストがあり、シグナルに基づいて適切なアクションを実行できます。 これらの信号は、C ++ヘッダーファイル<csignal>で定義されています。
Sr.No | Signal & Description |
---|---|
1 |
SIGABRT
|
2 |
SIGFPE ゼロ除算やオーバーフローを引き起こす演算などの誤った算術演算。 |
3 |
SIGILL 違法な命令の検出。 |
4 |
SIGINT インタラクティブな注意信号の受信。 |
5 |
SIGSEGV ストレージへの無効なアクセス。 |
6 |
SIGTERM プログラムに送信された終了要求。 |
signal()関数
C ++シグナル処理ライブラリは、予期しないイベントをトラップする関数 signal を提供します。 以下は、signal()関数の構文です-
void (*signal (int sig, void (*func)(int)))(int);
シンプルに保つと、この関数は2つの引数を受け取ります。最初の引数はシグナル番号を表す整数で、2番目の引数はシグナル処理関数へのポインターです。
signal()関数を使用してSIGINTシグナルをキャッチする簡単なC ++プログラムを作成しましょう。 プログラムでキャッチするシグナルが何であれ、 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.
raise()関数
関数* raise()*でシグナルを生成できます。これは、引数として整数シグナル番号を取り、次の構文を持ちます。
int raise (signal sig);
ここで、 sig は、SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV、SIGTERM、SIGHUPのいずれかのシグナルを送信するシグナル番号です。 以下は、次のようにraise()関数を使用して内部的に信号を上げる例です-
#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 ++マルチスレッド
マルチスレッドはマルチタスクの特殊な形式であり、マルチタスクはコンピューターで複数のプログラムを同時に実行できる機能です。 一般に、マルチタスクには、プロセスベースとスレッドベースの2つのタイプがあります。
プロセスベースのマルチタスクは、プログラムの同時実行を処理します。 スレッドベースのマルチタスクは、同じプログラムの各部分の同時実行を処理します。
マルチスレッドプログラムには、同時に実行できる2つ以上の部分が含まれています。 そのようなプログラムの各部分はスレッドと呼ばれ、各スレッドは実行の個別のパスを定義します。
Cには、マルチスレッドアプリケーションに対する組み込みサポートは含まれていません。 代わりに、この機能を提供するためにオペレーティングシステムに完全に依存しています。
このチュートリアルでは、Linux OSで作業しており、POSIXを使用してマルチスレッドC ++プログラムを作成することを想定しています。 POSIX Threads、またはPthreadsは、FreeBSD、NetBSD、GNU/Linux、Mac OS X、Solarisなどの多くのUnix系POSIXシステムで利用可能なAPIを提供します。
スレッドを作成する
次のルーチンは、POSIXスレッドを作成するために使用されます-
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)
ここで、 pthread_create は新しいスレッドを作成し、実行可能にします。 このルーチンは、コード内のどこからでも何度でも呼び出すことができます。 ここにパラメータの説明があります-
Sr.No | Parameter & Description |
---|---|
1 |
thread サブルーチンによって返される新しいスレッドの不透明な一意の識別子。 |
2 |
attr スレッド属性の設定に使用できる不透明な属性オブジェクト。 スレッド属性オブジェクトを指定するか、デフォルト値にNULLを指定できます。 |
3 |
start_routine スレッドが作成された後に実行されるC ++ルーチン。 |
4 |
arg start_routineに渡すことができる単一の引数。 void型のポインターキャストとして参照渡しする必要があります。 引数を渡さない場合は、NULLを使用できます。 |
プロセスが作成できるスレッドの最大数は実装に依存します。 作成されたスレッドはピアになり、他のスレッドを作成する場合があります。 暗黙的な階層やスレッド間の依存関係はありません。
スレッドの終了
POSIXスレッドを終了するために使用する次のルーチンがあります-
#include <pthread.h>
pthread_exit (status)
ここで、 pthread_exit はスレッドを明示的に終了するために使用されます。 通常、pthread_exit()ルーチンは、スレッドがその作業を完了した後に呼び出され、存在する必要がなくなりました。
main()が作成したスレッドの前に終了し、pthread_exit()で終了した場合、他のスレッドは引き続き実行されます。 それ以外の場合、main()が終了すると自動的に終了します。
- 例 *
この単純なサンプルコードは、pthread_create()ルーチンを使用して5つのスレッドを作成します。 各スレッドは「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
スレッドの結合と分離
スレッドを結合または分離するために使用できる次の2つのルーチンがあります-
pthread_join (threadid, status)
pthread_detach (threadid)
pthread_join()サブルーチンは、指定された「threadid」スレッドが終了するまで呼び出しスレッドをブロックします。 スレッドが作成されると、その属性の1つは、スレッドが結合可能か切り離されるかを定義します。 結合可能として作成されたスレッドのみを結合できます。 切り離されたスレッドが作成された場合、そのスレッドは結合できません。
この例は、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 ++ Webプログラミング
CGIとは何ですか?
- Common Gateway Interface(CGI)は、Webサーバーとカスタムスクリプト間で情報を交換する方法を定義する一連の標準です。
- CGIの仕様は現在NCSAによって維持されており、NCSAは次のようにCGIを定義しています-
- Common Gateway Interface(CGI)は、HTTPサーバーなどの情報サーバーとインターフェイスする外部ゲートウェイプログラムの標準です。
- 現在のバージョンはCGI/1.1で、CGI/1.2は進行中です。
ウェブブラウジング
CGIの概念を理解するために、ハイパーリンクをクリックして特定のWebページまたはURLを参照するとどうなるかを見てみましょう。
- ブラウザはHTTP Webサーバーに接続し、URLを要求します。 ファイル名。
- WebサーバーはURLを解析し、ファイル名を探します。 要求されたファイルが見つかった場合、Webサーバーはそのファイルをブラウザに送信します。それ以外の場合は、間違ったファイルを要求したことを示すエラーメッセージを送信します。
- WebブラウザはWebサーバーからの応答を受け取り、受信した応答に基づいて、受信したファイルまたはエラーメッセージを表示します。
ただし、特定のディレクトリ内のファイルが要求されるたびに、そのファイルが送り返されないようにHTTPサーバーを設定することは可能です。代わりに、プログラムとして実行され、プログラムから生成された出力がブラウザに送り返されて表示されます。
Common Gateway Interface(CGI)は、アプリケーション(CGIプログラムまたはCGIスクリプトと呼ばれる)がWebサーバーおよびクライアントと対話できるようにするための標準プロトコルです。 これらのCGIプログラムは、Python、PERL、シェル、CまたはC ++などで作成できます。
CGIアーキテクチャ図
次の単純なプログラムは、CGIの単純なアーキテクチャを示しています-
Webサーバーの構成
CGIプログラミングを進める前に、WebサーバーがCGIをサポートし、CGIプログラムを処理するように構成されていることを確認してください。 HTTPサーバーによって実行されるすべてのCGIプログラムは、事前に構成されたディレクトリに保持されます。 このディレクトリはCGIディレクトリと呼ばれ、慣例により/var/www/cgi-binと名付けられます。 慣例により、CGIファイルの拡張子は .cgi になりますが、C ++実行可能ファイルです。
デフォルトでは、Apache Webサーバーは/var/www/cgi-binでCGIプログラムを実行するように構成されています。 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>
ここでは、Webサーバーが正常に起動して実行されており、PerlやShellなどの他のCGIプログラムを実行できると想定しています。
最初の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プログラムを実行する前に、 chmod 755 cplusplus.cgi UNIXコマンドを使用してファイルのモードを変更し、ファイルを実行可能にしてください。
私の最初のCGIプログラム
上記のC プログラムは、STDOUTファイルに出力を書き込む単純なプログラムです。 画面。 最初の行の印刷 *Content-type:text/html \ r \ n \ r \ n* という重要で追加の機能が1つあります。 この行はブラウザに送り返され、ブラウザ画面に表示されるコンテンツタイプを指定します。 これで、CGIの基本概念を理解しているはずであり、Pythonを使用して多くの複雑なCGIプログラムを作成できます。 C CGIプログラムは、RDBMSなどの他の外部システムと対話して情報を交換できます。
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
CGIプログラミングで頻繁に使用する他の重要なHTTPヘッダーはほとんどありません。
Sr.No | Header & Description |
---|---|
1 |
Content-type: 返されるファイルの形式を定義するMIME文字列。 例は、Content-type:text/htmlです。 |
2 |
Expires: Date 情報が無効になる日付。 これは、ブラウザがページを更新する必要がある時期を決定するために使用する必要があります。 有効な日付文字列は、1998年1月1日12:00:00 GMTの形式である必要があります。 |
3 |
Location: URL 要求されたURLの代わりに返されるURL。 このフィールドを使用して、要求を任意のファイルにリダイレクトできます。 |
4 |
Last-modified: Date リソースの最終変更日。 |
5 |
Content-length: N 返されるデータの長さ(バイト単位)。 ブラウザはこの値を使用して、ファイルの推定ダウンロード時間を報告します。 |
6 |
Set-Cookie: String _string_を介して渡されるCookieを設定します。 |
CGI環境変数
すべてのCGIプログラムは、次の環境変数にアクセスできます。 これらの変数は、CGIプログラムの作成中に重要な役割を果たします。
Sr.No | Variable Name & Description |
---|---|
1 |
CONTENT_TYPE クライアントが添付コンテンツをサーバーに送信するときに使用されるコンテンツのデータ型。 たとえば、ファイルのアップロードなど。 |
2 |
CONTENT_LENGTH POST要求でのみ使用可能なクエリ情報の長さ。 |
3 |
HTTP_COOKIE 設定されたCookieをキーと値のペアの形式で返します。 |
4 |
HTTP_USER_AGENT User-Agent request-headerフィールドには、リクエストを発信したユーザーエージェントに関する情報が含まれています。 これはWebブラウザーの名前です。 |
5 |
PATH_INFO CGIスクリプトのパス。 |
6 |
QUERY_STRING GETメソッド要求で送信されるURLエンコードされた情報。 |
7 |
REMOTE_ADDR 要求を行っているリモートホストのIPアドレス。 これは、ロギングまたは認証の目的に役立ちます。 |
8 |
REMOTE_HOST 要求を行っているホストの完全修飾名。 この情報が利用できない場合、REMOTE_ADDRを使用してIRアドレスを取得できます。 |
9 |
REQUEST_METHOD 要求を行うために使用されるメソッド。 最も一般的なメソッドはGETおよびPOSTです。 |
10 |
SCRIPT_FILENAME CGIスクリプトへのフルパス。 |
11 |
SCRIPT_NAME CGIスクリプトの名前。 |
12 |
SERVER_NAME サーバーのホスト名またはIPアドレス。 |
13 |
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ライブラリ
実際の例では、CGIプログラムで多くの操作を行う必要があります。 あなたはftp://ftp.gnu.org/gnu/cgicc/からダウンロードすることができ、ライブラリをインストールする手順に従ってくださいC ++プログラム用に書かれたCGIライブラリがあります-
$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メソッド
ブラウザからWebサーバーに、そして最終的にはCGIプログラムに何らかの情報を渡す必要がある場合、多くの状況に遭遇したに違いありません。 ほとんどの場合、ブラウザはこの情報をWebサーバーに渡すために2つの方法を使用します。 これらのメソッドは、GETメソッドとPOSTメソッドです。
GETメソッドを使用して情報を渡す
GETメソッドは、エンコードされたユーザー情報をページリクエストに追加して送信します。 ページとエンコードされた情報は、? 次のような文字-
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
GETメソッドは、ブラウザからWebサーバーに情報を渡すデフォルトのメソッドであり、ブラウザのLocation:boxに表示される長い文字列を生成します。 サーバーに渡すパスワードまたはその他の機密情報がある場合は、GETメソッドを使用しないでください。 GETメソッドにはサイズ制限があり、リクエスト文字列で最大1024文字を渡すことができます。
GETメソッドを使用する場合、情報はQUERY_STRING httpヘッダーを使用して渡され、QUERY_STRING環境変数を介してCGIプログラムでアクセスできます。
キーと値のペアを任意のURLと連結するだけで情報を渡すことができます。または、HTML <FORM>タグを使用して、GETメソッドを使用して情報を渡すことができます。
単純なURLの例:Getメソッド
GETメソッドを使用してhello_get.pyプログラムに2つの値を渡す簡単なURLを次に示します。
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
以下は、Webブラウザからの入力を処理する cpp_get.cgi 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
単純なFORMの例:GETメソッド
次に、HTML FORMと送信ボタンを使用して2つの値を渡す簡単な例を示します。 この入力を処理するために、同じ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メソッドを処理します。 上記と同じ例を見てみましょう。HTMLFORMと送信ボタンを使用して2つの値を渡しますが、今回は次のように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プログラムに渡す
チェックボックスは、複数のオプションを選択する必要がある場合に使用されます。
ここに2つのチェックボックスを持つフォームの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スクリプトを生成し、Webブラウザからチェックボックスボタンを介して与えられた入力を処理します。
#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プログラムに渡す
オプションを1つだけ選択する必要がある場合は、ラジオボタンが使用されます。
これは、2つのラジオボタンがあるフォームの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スクリプトを生成して、Webブラウザからラジオボタンを介して与えられた入力を処理します。
#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プログラムに渡す必要がある場合に使用されます。
以下は、TEXTAREAボックスを持つフォームのHTMLコードの例です-
<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スクリプトを生成して、Webブラウザからテキスト領域を介して与えられた入力を処理します。
#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プログラムに渡す
ドロップダウンボックスは、多くのオプションを使用できますが、選択されるのは1つまたは2つだけの場合です。
これは、1つのドロップダウンボックスがあるフォームの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スクリプトを生成して、Webブラウザからドロップダウンボックスを介して与えられた入力を処理します。
#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;
}
CGIでのCookieの使用
HTTPプロトコルはステートレスプロトコルです。 ただし、商用Webサイトの場合は、異なるページ間でセッション情報を維持する必要があります。 たとえば、多くのページを完了すると、1人のユーザー登録が終了します。 しかし、すべてのWebページにわたってユーザーのセッション情報を維持する方法。
多くの場合、Cookieの使用は、ユーザーの利便性やサイトの統計情報を改善するために必要な設定、購入、手数料、その他の情報を記憶および追跡する最も効率的な方法です。
使い方
サーバーは、Cookieの形式で訪問者のブラウザにデータを送信します。 ブラウザはCookieを受け入れる場合があります。 存在する場合、訪問者のハードドライブにプレーンテキストレコードとして保存されます。 これで、訪問者がサイトの別のページに到達すると、Cookieを取得できます。 取得されると、サーバーは保存された内容を認識/記憶します。
クッキーは5つの可変長フィールドのプレーンテキストデータレコードです-
- 有効期限-これは、Cookieの有効期限が切れる日付を示します。 これが空白の場合、訪問者がブラウザを終了すると、Cookieは期限切れになります。
- ドメイン-これはサイトのドメイン名を示します。
- パス-これは、Cookieを設定するディレクトリまたはWebページへのパスを示します。 任意のディレクトリまたはページからCookieを取得する場合、これは空白になる場合があります。
- 安全-このフィールドに「安全」という単語が含まれている場合、Cookieは安全なサーバーでのみ取得できます。 このフィールドが空白の場合、そのような制限はありません。
- 名前=値-Cookieはキーと値のペアの形式で設定および取得されます。
クッキーを設定する
クッキーをブラウザに送信するのは非常に簡単です。 これらのCookieは、コンテンツタイプが提出される前にHTTPヘッダーとともに送信されます。 ユーザーIDとパスワードを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.finddevguides.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の設定方法を理解している必要があります。 Set-Cookie HTTPヘッダーを使用して、Cookieを設定します。
ここでは、Expires、Domain、PathなどのCookie属性を設定することはオプションです。 マジックライン "Content-type:text/html \ r \ n \ r \ n を送信する前にCookieが設定されていることは注目に値します。
上記のプログラムをコンパイルしてsetcookies.cgiを作成し、次のリンクを使用してCookieを設定してください。 それはあなたのコンピューターで4つのクッキーを設定します-
/cgi-bin/setcookies.cgi
Cookieを取得する
設定されたすべてのCookieを簡単に取得できます。 クッキーはCGI環境変数HTTP_COOKIEに保存され、次の形式になります。
key1 = value1; key2 = value2; key3 = value3....
Cookieを取得する方法の例を次に示します。
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main () {
Cgicc cgi;
const_cookie_iterator cci;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Cookies in CGI</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table border = \"0\" cellspacing = \"2\">";
//get environment variables
const CgiEnvironment& env = cgi.getEnvironment();
for( cci = env.getCookieList().begin();
cci != env.getCookieList().end();
++cci ) {
cout << "<tr><td>" << cci->getName() << "</td><td>";
cout << cci->getValue();
cout << "</td></tr>\n";
}
cout << "</table><\n";
cout << "<br/>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
さて、上記のプログラムをコンパイルしてgetcookies.cgiを作成し、コンピューターで利用可能なすべてのCookieのリストを取得してください-
/cgi-bin/getcookies.cgi
これにより、前のセクションで設定された4つのすべてのCookieとコンピューターに設定された他のすべてのCookieのリストが生成されます-
UserID XYZ
Password XYZ123
Domain www.finddevguides.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 ストリームでコンテンツを書き込むためのものですが、ファイルストリームを開いて、アップロードしたファイルのコンテンツを目的の場所のファイルに保存できます。
このチュートリアルをお楽しみください。 はいの場合は、フィードバックをお送りください。 Cplusplus-cpp-questions-answers
C ++オブジェクト指向
C ++プログラミングの主な目的は、オブジェクト指向をCプログラミング言語に追加することでした。Cプログラミング言語は、それ自体が最も強力なプログラミング言語の1つです。
純粋なオブジェクト指向プログラミングの中核は、特定のプロパティとメソッドを持つオブジェクトをコードで作成することです。 C ++モジュールを設計する際には、オブジェクトの形で全世界を見ようとします。 たとえば、車は色、ドアの数などの特定のプロパティを持つオブジェクトです。 また、加速、ブレーキなどの特定の方法があります。
オブジェクト指向プログラミングの基礎を形成するいくつかの原則的な概念があります-
対象
これは、オブジェクト指向プログラミングの基本単位です。 つまり、データを操作するデータと関数の両方が、オブジェクトと呼ばれる単位としてバンドルされています。
クラス
クラスを定義するとき、オブジェクトの設計図を定義します。 これは実際にはデータを定義しませんが、クラス名が何を意味するのか、つまりクラスのオブジェクトが何を構成するのか、そしてそのようなオブジェクトに対して実行できる操作は定義します。
抽象化
データの抽象化とは、重要な情報のみを外部に提供し、その背景の詳細を隠すこと、つまり、詳細を提示せずにプログラムで必要な情報を表すことを指します。
たとえば、データベースシステムは、データの保存、作成、維持方法の特定の詳細を隠します。 同様に、C ++クラスは、これらのメソッドとデータに関する内部の詳細を提供することなく、さまざまなメソッドを外部に提供します。
カプセル化
カプセル化は、データとそのデータで機能する機能を同じ場所に配置することです。 手続き型言語を使用している間、どの関数がどの変数で機能するかは必ずしも明確ではありませんが、オブジェクト指向プログラミングでは、データと関連する関数を同じオブジェクトに配置するフレームワークが提供されます。
継承
オブジェクト指向プログラミングの最も有用な側面の1つは、コードの再利用性です。 名前が示すように、継承は、基本クラスと呼ばれる既存のクラスからの既存のクラスから新しいクラスを形成するプロセスであり、派生クラスと呼ばれる新しいクラスが形成されます。
この機能はコードサイズの削減に役立つため、これはオブジェクト指向プログラミングの非常に重要な概念です。
多型
他の言葉で演算子または関数を異なる方法で使用する能力は、演算子または関数に異なる意味または機能を与えることをポリモーフィズムと呼びます。 ポリは多くを指します。 それは単一の関数、または使用法によって異なる多くの方法で機能する演算子はポリモーフィズムと呼ばれます。
過負荷
オーバーロードの概念は、ポリモーフィズムの分岐でもあります。 既存の演算子または関数が新しいデータ型で動作するように作られている場合、それはオーバーロードされていると言われます。
C ++ STLチュートリアル
前に説明したC テンプレートの概念を既に理解していることを願っています。 C STL(標準テンプレートライブラリ)は、ベクター、リスト、キュー、スタックなどの一般的で一般的に使用される多くのアルゴリズムとデータ構造を実装するテンプレートを備えた汎用クラスと機能を提供するC ++テンプレートクラスの強力なセットです。
C ++標準テンプレートライブラリの中核には、次の3つの適切に構成されたコンポーネントがあります-
Sr.No | Component & Description |
---|---|
1 |
Containers コンテナは、特定の種類のオブジェクトのコレクションを管理するために使用されます。 deque、list、vector、mapなどのさまざまなタイプのコンテナがあります。 |
2 |
Algorithms アルゴリズムはコンテナに作用します。 これらは、コンテナのコンテンツの初期化、ソート、検索、および変換を実行する手段を提供します。 |
3 |
Iterators イテレータは、オブジェクトのコレクションの要素をステップスルーするために使用されます。 これらのコレクションは、コンテナまたはコンテナのサブセットです。 |
次の章では、C 標準ライブラリについて説明しながら、3つのC STLコンポーネントすべてについて説明します。 今のところ、3つのコンポーネントにはすべて、非常に簡単な方法で複雑なタスクを実行するのに役立つ豊富な定義済み関数のセットがあることに留意してください。
それが成長した場合に自動的に独自のストレージ要件を処理することを除いて、配列に似ているベクトルコンテナ(C ++標準テンプレート)を示す次のプログラムを見てみましょう-
#include <iostream>
#include <vector>
using namespace std;
int main() {
//create a vector to store int
vector<int> vec;
int i;
//display the original size of vec
cout << "vector size = " << vec.size() << endl;
//push 5 values into the vector
for(i = 0; i < 5; i++) {
vec.push_back(i);
}
//display extended size of vec
cout << "extended vector size = " << vec.size() << endl;
//access 5 values from the vector
for(i = 0; i < 5; i++) {
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
//use iterator to access the values
vector<int>::iterator v = vec.begin();
while( v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}
上記のコードをコンパイルして実行すると、次の結果が生成されます-
vector size = 0
extended vector size = 5
value of vec [0] = 0
value of vec [1] = 1
value of vec [2] = 2
value of vec [3] = 3
value of vec [4] = 4
value of v = 0
value of v = 1
value of v = 2
value of v = 3
value of v = 4
ここでは、上記の例で使用したさまざまな機能に関連する次の点に注意してください-
- push_back()メンバー関数は、ベクターの最後に値を挿入し、必要に応じてサイズを拡張します。
- size()関数は、ベクトルのサイズを表示します。
- 関数begin()は、ベクトルの先頭への反復子を返します。
- 関数end()は、ベクトルの末尾への反復子を返します。
C ++標準ライブラリ
C ++標準ライブラリは2つの部分に分類することができます-
- 標準関数ライブラリ-このライブラリは、クラスの一部ではない汎用のスタンドアロン関数で構成されています。 関数ライブラリはCから継承されます。
- オブジェクト指向クラスライブラリ-これはクラスと関連する関数のコレクションです。
標準C ++ライブラリには、すべての標準Cライブラリも組み込まれており、タイプセーフをサポートするための小さな追加と変更が行われています。
標準機能ライブラリ
標準機能ライブラリは、次のカテゴリに分かれています-
- I/O,
- 文字列と文字の処理、
- 数学的、
- 時刻、日付、およびローカライズ、
- ダイナミックアロケーション、
- その他、
- ワイド文字関数、
オブジェクト指向クラスライブラリ
標準C ++オブジェクト指向ライブラリは、I/O、文字列、数値処理など、多くの一般的なアクティビティをサポートする広範なクラスのセットを定義しています。 このライブラリには次のものが含まれます-
- 標準C ++ I/Oクラス
- 文字列クラス
- 数値クラス
- STLコンテナクラス
- STLアルゴリズム
- STL関数オブジェクト
- STLイテレーター
- STLアロケーター
- ローカリゼーションライブラリ
- 例外処理クラス
- その他のサポートライブラリ