【サクッと習得】C++ 学習教材

# はじめに
**情報処理安全確保支援士の学習にあたってC++の知識が必要**なので、自己学習しました。
その際に学習した内容をまとめたので、**情報処理安全確保支援士の学習をする方**や**C++を短時間で学習したい方**の参考になれば良いと思い教材を作成しました。
**専門書を買うほどでもなくサクッと言語を学習したい方**におすすめです。


# 目次

[1.概要](#1概要)
[2.基本的な構文](#2基本的な構文)
[2-1.コメント](#2-1コメント)
[2-2.データ型と変数](#2-2データ型と変数)
[2-3.演算子](#2-3演算子)
[2-4.制御文](#2-4制御文)
[2-5.関数](#2-5関数)
[2-6.標準ライブラリ関数](#2-6標準ライブラリ関数)
[3.オブジェクト指向プログラミング](#3オブジェクト指向プログラミング)
[3-1.クラスとオブジェクト](#3-1クラスとオブジェクト)
[3-2.コンストラクタとデストラクタ](#3-2コンストラクタとデストラクタ)
[3-3.アクセス修飾子](#3-3アクセス修飾子)
[3-4.継承](#3-4継承)
[3-5.ポリモーフィズム](#3-5ポリモーフィズム)
[4.高度なC++機能](#4高度なC++機能)
[4-1.テンプレート](#4-1テンプレート)
[4-2.名前空間](#4-2名前空間)
[4-3.標準テンプレートライブラリ](#4-3標準テンプレートライブラリ)
[4-4.例外処理](#4-4例外処理)
[5.練習問題](#5練習問題)
[5-1.基本的な文法の練習問題](#5-1基本的な文法の練習問題)
[5-2.オブジェクト指向の練習問題](#5-2オブジェクト指向の練習問題)
[5-3.高度な機能の練習問題](#5-3高度な機能の練習問題)
[6.まとめ](#6まとめ)

# 1.概要

C++は、システムプログラミングからゲーム開発、リアルタイムシステムなど幅広い用途で利用されるプログラミング言語です。本教材では、特に**他のプログラミング言語の経験はあるが、C++に初めて触れるエンジニアを対象**に、**基本的な文法**から**オブジェクト指向プログラミング**、そしてさらに高度な機能までをカバーします。

# 2.基本的な構文

## 2-1.コメント
コメントはコードの説明やメモとして使われ、コンパイラによって無視されます。
```
// これは一行コメントです

/*
これは
複数行にわたる
コメントです
*/
```

## 2-2.データ型と変数
C++には基本的なデータ型がいくつかあります。変数は特定のデータ型に属し、そのデータ型に合った値を保持します。

#### 基本データ型
- <font color="Red">int</font>：整数型
- <font color="Red">float</font>：単精度浮動小数点型
- <font color="Red">double</font>：倍精度浮動小数点型
- <font color="Red">char</font>：文字型
- <font color="Red">bool</font>：真偽値型

#### 変数の宣言と初期化
```
int a = 10;        // 整数型の変数aを宣言し、10で初期化
float b = 5.5f;    // 単精度浮動小数点型の変数bを宣言し、5.5で初期化
double c = 3.14;   // 倍精度浮動小数点型の変数cを宣言し、3.14で初期化
char d = 'A';      // 文字型の変数dを宣言し、'A'で初期化
bool e = true;     // 真偽値型の変数eを宣言し、trueで初期化
```

#### データ型の範囲

各データ型には取りうる値の範囲が決まっています。

- <font color="Red">int</font>：-2147483648 ～ 2147483647
- <font color="Red">float</font>：約3.4e-38 ～ 3.4e+38
- <font color="Red">double</font>：約1.7e-308 ～ 1.7e+308
- <font color="Red">char</font>：-128 ～ 127（符号付き）
- <font color="Red">bool</font>：true または false

## 2-3.演算子

演算子は変数や値に対して様々な操作を行うために使用されます。

#### 算術演算子

- <font color="Red">+</font>：加算
- <font color="Red">-</font>：減算
- <font color="Red">*</font>：乗算
- <font color="Red">/</font>：除算
- <font color="Red">%</font>：剰余

```
int x = 10;
int y = 3;
int result;

result = x + y;  // resultは13
result = x - y;  // resultは7
result = x * y;  // resultは30
result = x / y;  // resultは3
result = x % y;  // resultは1
```

#### 比較演算子

- <font color="Red">==</font>：等しい
- <font color="Red">!=</font>：等しくない
- <font color="Red"><</font>：小さい
- <font color="Red">></font>：大きい
- <font color="Red"><=</font>：以下
- <font color="Red">>=</font>：以上

```
bool comparisonResult;

comparisonResult = (x == y);  // false
comparisonResult = (x != y);  // true
comparisonResult = (x < y);   // false
comparisonResult = (x > y);   // true
comparisonResult = (x <= y);  // false
comparisonResult = (x >= y);  // true
```

#### 論理演算子

- <font color="Red">&&</font>：論理積（AND）
- <font color="Red">||</font>：論理和（OR）
- <font color="Red">!</font>：論理否定（NOT）

```
bool result;

result = (true && false);  // false
result = (true || false);  // true
result = !true;            // false
```

#### 代入演算子

- <font color="Red">=</font>：代入
- <font color="Red">+=</font>：加算代入
- <font color="Red">-=</font>：減算代入
- <font color="Red">*=</font>：乗算代入
- <font color="Red">/=</font>：除算代入
- <font color="Red">%=</font>：剰余代入

```
int value = 10;

value += 5;  // valueは15
value -= 3;  // valueは12
value *= 2;  // valueは24
value /= 4;  // valueは6
value %= 5;  // valueは1
```

## 2-4.制御文

制御文はプログラムの実行フローを制御するために使用されます

#### <font color="Red">if文</font>

```
if (条件) {
    // 条件が真のとき実行されるコード
} else {
    // 条件が偽のとき実行されるコード
}
```

#### <font color="Red">elseif文</font>

```
if (条件1) {
    // 条件1が真のとき実行されるコード
} else if (条件2) {
    // 条件2が真のとき実行されるコード
} else {
    // どの条件も真でないとき実行されるコード
}
```

#### <font color="Red">switch文</font>

```
switch (変数) {
    case 値1:
        // 変数が値1のとき実行されるコード
        break;
    case 値2:
        // 変数が値2のとき実行されるコード
        break;
    default:
        // どのケースにも一致しないとき実行されるコード
        break;
}
```

#### <font color="Red">for文</font>

```
for (初期化; 条件; 増分) {
    // 繰り返し実行されるコード
}
```

#### <font color="Red">while文</font>

```
while (条件) {
    // 条件が真の間繰り返し実行されるコード
}
```

#### <font color="Red">do-while文</font>

```
do {
    // 繰り返し実行されるコード
} while (条件);
```

## 2-5.関数

関数は特定のタスクを実行するためのコードの集まりです。

#### 関数の宣言と定義

```
// 関数の宣言（プロトタイプ）
戻り値の型 関数名(引数リスト);

// 関数の定義
戻り値の型 関数名(引数リスト) {
    // 関数の本体
    return 戻り値;
}
```

#### 例：

```
int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(5, 3);
    std::cout << "Result: " << result << std::endl;
    return 0;
}
```

#### <font color="Red">関数のオーバーロード</font>
同じ名前の関数を異なる引数リストで定義することが可能です。これを関数のオーバーロードと呼びます。


```
int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

int main() {
    std::cout << add(1, 2) << std::endl;       // 3
    std::cout << add(1.5, 2.5) << std::endl;   // 4.0
    return 0;
}
```

#### <font color="Red">引数のデフォルト値</font>
関数の引数にデフォルト値を設定することができます。

```
int add(int a, int b = 10) {
    return a + b;
}

int main() {
    std::cout << add(5) << std::endl;     // 15
    std::cout << add(5, 5) << std::endl;  // 10
    return 0;
}
```

## 2-6.標準ライブラリ関数
C++には多くの組み込み関数があり、標準ライブラリとして提供されています。これらの関数を使うことで、プログラムを効率的にコーディングできます。ここでは、いくつかの基本的な標準ライブラリ関数を紹介し、その使用方法を解説します。

### 文字列操作
### <font color="Red">strlen</font>
<font color="Red">strlen</font>は、Cスタイルの文字列（ヌル終端文字列）の長さを返します。C++11以降では、標準ライブラリの<font color="Red">std::string</font>クラスを使用する方が一般的ですが、Cスタイルの文字列を操作する場合には依然として重要な関数です。

```
#include <iostream>
#include <cstring>

int main() {
    const char* str = "Hello, World!";
    // 文字列の長さを取得
    std::cout << "Length of the string: " << strlen(str) << std::endl;
    return 0;
}
```

### <font color="Red">strcpy</font>
<font color="Red">strcpy</font>は、Cスタイルの文字列を他の場所にコピーするために使用されます。

```
#include <iostream>
#include <cstring>

int main() {
    char src[] = "Hello, World!";
    char dest[50];
    // 文字列をコピー
    strcpy(dest, src);
    std::cout << "Copied string: " << dest << std::endl;
    return 0;
}
```

### <font color="Red">strcmp</font>
<font color="Red">strcmp</font>は、2つのCスタイルの文字列を比較します。文字列が等しい場合は0、異なる場合は非ゼロを返します。

```
#include <iostream>
#include <cstring>

int main() {
    const char* str1 = "Hello";
    const char* str2 = "Hello";
    const char* str3 = "World";

    // str1とstr2を比較
    if (strcmp(str1, str2) == 0) {
        std::cout << "str1 and str2 are equal" << std::endl;
    } else {
        std::cout << "str1 and str2 are not equal" << std::endl;
    }

    // str1とstr3を比較
    if (strcmp(str1, str3) == 0) {
        std::cout << "str1 and str3 are equal" << std::endl;
    } else {
        std::cout << "str1 and str3 are not equal" << std::endl;
    }
    
    return 0;
}
```

### <font color="Red">tolower</font>と<font color="Red">toupper</font>
<font color="Red">tolower</font>は文字を小文字に変換し、<font color="Red">toupper</font>は文字を大文字に変換します。

```
#include <iostream>
#include <cctype>

int main() {
    char ch = 'A';
    // 文字を小文字に変換
    std::cout << ch << " to lowercase is " << (char)tolower(ch) << std::endl;

    ch = 'b';
    // 文字を大文字に変換
    std::cout << ch << " to uppercase is " << (char)toupper(ch) << std::endl;
    
    return 0;
}
```

### 数学関数
数値計算に関する多くの組み込み関数が<font color="Red">\<cmath></font>ライブラリに含まれています。

### <font color="Red">sqrt</font>
<font color="Red">sqrt</font>は平方根を計算します。

```
#include <iostream>
#include <cmath>

int main() {
    double num = 9.0;
    // 数の平方根を計算
    std::cout << "Square root of " << num << " is " << sqrt(num) << std::endl;
    return 0;
}
```

### <font color="Red">pow</font>
<font color="Red">pow</font>は累乗の計算を行います。

```
#include <iostream>
#include <cmath>

int main() {
    double base = 2.0;
    double exponent = 3.0;
    // 累乗の計算
    std::cout << base << "^" << exponent << " = " << pow(base, exponent) << std::endl;
    return 0;
}
```

### <font color="Red">abs</font>
<font color="Red">abs</font>は整数の絶対値を返します。なお、浮動小数点数の場合は<font color="Red">fabs</font>を使用します。

```
#include <iostream>
#include <cstdlib> // absはstdlibに含まれています

int main() {
    int num = -10;
    // 整数の絶対値を計算
    std::cout << "Absolute value of " << num << " is " << abs(num) << std::endl;
    return 0;
}
```

### 乱数の生成
### <font color="Red">rand</font>と<font color="Red">srand</font>
<font color="Red">rand</font>関数は、0からRAND_MAXまでのランダムな整数を返します。<font color="Red">srand</font>関数を使って乱数のシードを設定することで、生成される乱数を制御できます。

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

int main() {
    // シード設定
    srand(static_cast<unsigned int>(time(0)));  
    // ランダムな整数を5回生成
    for (int i = 0; i < 5; ++i) {
        std::cout << rand() % 100 << std::endl;  // 0から99までのランダムな整数
    }
    return 0;
}
```

### 時刻関数
### <font color="Red">time</font>
<font color="Red">time</font>関数は、エポック（1970年1月1日）からの経過秒数を返します。

```
#include <iostream>
#include <ctime>

int main() {
    // 現在の時刻を取得
    time_t currentTime = time(0);
    std::cout << "Current time is " << currentTime << std::endl;
    return 0;
}
```

### <font color="Red">localtime</font>と<font color="Red">strftime</font>
これらの関数を使って、現在時刻を人間が読める形式にフォーマットします。

```
#include <iostream>
#include <ctime>

int main() {
    // 現在の時刻を取得
    time_t currentTime = time(0);
    // tm構造体にローカル時間を格納
    tm* localTime = localtime(&currentTime);

    char buffer[80];
    // 時刻を指定されたフォーマットに変換
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localTime);
    
    std::cout << "Formatted time: " << buffer << std::endl;
    return 0;
}
```

### メモリ操作
### <font color="Red">memcpy</font>
<font color="Red">memcpy</font>はメモリブロックを別の場所にコピーします。

```
#include <iostream>
#include <cstring>

int main() {
    char src[50] = "Hello, World!";
    char dest[50];
    // メモリをコピー
    memcpy(dest, src, strlen(src) + 1);
    std::cout << "Copied string: " << dest << std::endl;
    return 0;
}
```

### <font color="Red">memset</font>
<font color="Red">memset</font>はメモリブロックを特定の値で埋めます。

```
#include <iostream>
#include <cstring>

int main() {
    char str[50] = "Hello, World!";
    // メモリを特定の値で埋める
    memset(str, '*', 5);  // 初めの5バイトを'*'で埋める
    std::cout << "Modified string: " << str << std::endl;
    return 0;
}
```

### ファイル操作
### <font color="Red">fopen</font>と<font color="Red">fclose</font>
<font color="Red">fopen</font>はファイルを開き、<font color="Red">fclose</font>は開いたファイルを閉じます。

```
#include <iostream>
#include <cstdio>

int main() {
    // ファイルを読み取り専用で開く
    FILE *file = fopen("example.txt", "r");
    if (file == nullptr) {
        std::cerr << "File could not be opened." << std::endl;
        return 1;
    } else {
        std::cout << "File opened successfully." << std::endl;
    }
    
    // ファイルを閉じる
    fclose(file);
    return 0;
}
```

### <font color="Red">fgets</font>と<font color="Red">fputs</font>
<font color="Red">fgets</font>はファイルから文字列を読み取り、<font color="Red">fputs</font>は文字列をファイルに書き込みます。

```
#include <iostream>
#include <cstdio>

int main() {
    // ファイルを読み取り専用で開く
    FILE *file = fopen("example.txt", "r");
    if (file == nullptr) {
        std::cerr << "File could not be opened." << std::endl;
        return 1;
    }

    char buffer[100];
    // ファイルから文字列を読み取る
    while (fgets(buffer, sizeof(buffer), file) != nullptr) {
        std::cout << buffer;
    }
    
    // ファイルを閉じる
    fclose(file);
    return 0;
}
```

### 入出力操作
### <font color="Red">printf</font>と<font color="Red">scanf</font>
<font color="Red">printf</font>はフォーマット付きの出力を行い、<font color="Red">scanf</font>はフォーマット付きの入力を行います。

```
#include <iostream>
#include <cstdio>

int main() {
    int num;
    // フォーマット付きで入力を求める
    std::printf("Enter a number: ");
    std::scanf("%d", &num);
    // フォーマット付きで出力
    std::printf("You entered: %d\n", num);
    return 0;
}
```

### <font color="Red">sprintf</font>と<font color="Red">sscanf</font>
<font color="Red">sprintf</font>はフォーマット付きの出力を文字列に格納し、<font color="Red">sscanf</font>は文字列からフォーマット付きの入力を行います。

```
#include <iostream>
#include <cstdio>

int main() {
    char buffer[50];
    int a = 10, b = 20;
    // フォーマット付きで文字列に出力
    sprintf(buffer, "a = %d, b = %d", a, b);
    std::cout << buffer << std::endl;  // "a = 10, b = 20"

    int x, y;
    // フォーマット付きで文字列から入力
    sscanf(buffer, "a = %d, b = %d", &x, &y);
    std::cout << "x = " << x << ", y = " << y << std::endl;  // "x = 10, y = 20"
    return 0;
}
```

### データ変換
### <font color="Red">atoi</font>と<font color="Red">atof</font>
<font color="Red">atoi</font>は文字列を整数に変換し、<font color="Red">atof</font>は文字列を浮動小数点数に変換します。

```
#include <iostream>
#include <cstdlib>

int main() {
    const char* intStr = "123";
    const char* floatStr = "123.456";
    
    // 文字列を整数に変換
    int intValue = atoi(intStr);
    // 文字列を浮動小数点数に変換
    double doubleValue = atof(floatStr);

    std::cout << "Integer value: " << intValue << std::endl;
    std::cout << "Double value: " << doubleValue << std::endl;

    return 0;
}
```

### <font color="Red">strtol</font>, <font color="Red">strtoll</font>, <font color="Red">strtof</font>, <font color="Red">strtod</font>, および <font color="Red">strtold</font>
これらの関数は、文字列をそれぞれ<font color="Red">long</font>, <font color="Red">long long</font>, <font color="Red">float</font>, <font color="Red">double</font>, および <font color="Red">long double</font>に変換します。

```
#include <iostream>
#include <cstdlib>

int main() {
    const char* longStr = "1234567890";
    const char* doubleStr = "123.456789";

    // 文字列をlong型に変換
    long longValue = strtol(longStr, nullptr, 10);
    // 文字列をdouble型に変換
    double doubleValue = strtod(doubleStr, nullptr);

    std::cout << "Long value: " << longValue << std::endl;
    std::cout << "Double value: " << doubleValue << std::endl;

    return 0;
}
```

### メモリブロック操作
### <font color="Red">malloc</font>と<font color="Red">free</font>
Cスタイルのメモリ管理には<font color="Red">malloc</font>と<font color="Red">free</font>が使用されます。通常はC++の<font color="Red">new</font>および<font color="Red">delete</font>を使用することが推奨されますが、Cスタイルのコードとの互換性のために知っておくと役立ちます。

```
#include <iostream>
#include <cstdlib>  // mallocとfreeはstdlibに含まれています

int main() {
    // 5つの整数用のメモリを割り当て
    int* arr = (int*)malloc(5 * sizeof(int));  

    if (arr != nullptr) {  // メモリ割り当ての成功を確認
        for (int i = 0; i < 5; ++i) {
            arr[i] = i * 2;
            std::cout << arr[i] << " ";
        }
        std::cout << std::endl;
        // メモリを解放
        free(arr);  
    }
    return 0;
}
```

# 3.オブジェクト指向プログラミング

## 3-1.クラスとオブジェクト

クラスはオブジェクトの設計図であり、オブジェクトはクラスのインスタンスです。

#### クラスの定義

```
class クラス名 {
public:
    // パブリックメンバ関数と変数
    型 メンバ関数();
    型 メンバ変数;

private:
    // プライベートメンバ関数と変数
    型 メンバ関数();
    型 メンバ変数;
};
```

#### 例：
```
class Person {
public:
    std::string name;
    int age;

    void introduce() {
        std::cout << "Hello, my name is " << name << " and I am " << age << " years old." << std::endl;
    }
};

int main() {
    Person person;
    person.name = "John";
    person.age = 30;
    person.introduce();
    return 0;
}
```

## 3-2.コンストラクタとデストラクタ
コンストラクタはオブジェクトが生成されるときに呼ばれる特別なメンバ関数であり、デストラクタはオブジェクトが破棄されるときに呼ばれる特別なメンバ関数です。

#### <font color="Red">コンストラクタ</font>

```
class クラス名 {
public:
    クラス名();  // デフォルトコンストラクタ
    クラス名(引数リスト);  // パラメータ付きコンストラクタ
};
```

#### <font color="Red">デストラクタ<font>

```
class クラス名 {
public:
    ~クラス名();  // デストラクタ
};
```

#### 例：
```
class Person {
public:
    std::string name;
    int age;

    // コンストラクタ
    Person(std::string n, int a) : name(n), age(a) {}

    // デストラクタ
    ~Person() {
        std::cout << "Person object is being destroyed" << std::endl;
    }

    void introduce() {
        std::cout << "Hello, my name is " << name << " and I am " << age << " years old." << std::endl;
    }
};

int main() {
    Person person("John", 30);
    person.introduce();
    return 0;
}
```

## 3-3.アクセス修飾子
アクセス修飾子はクラスメンバのアクセス範囲を制御します。

- <font color="Red">public</font>：どこからでもアクセス可能
- <font color="Red">private</font>：クラス内からのみアクセス可能
- <font color="Red">protected</font>：クラス内および派生クラスからアクセス可能

#### <font color="Red">アクセス修飾子の例</font>

```
class MyClass {
public:
    int publicVar;
    void publicMethod() {
        std::cout << "Public method" << std::endl;
    }

private:
    int privateVar;
    void privateMethod() {
        std::cout << "Private method" << std::endl;
    }

protected:
    int protectedVar;
    void protectedMethod() {
        std::cout << "Protected method" << std::endl;
    }
};

int main() {
    MyClass obj;
    obj.publicVar = 10;  // OK
    obj.publicMethod();  // OK

    // obj.privateVar = 20;  // エラー
    // obj.privateMethod();  // エラー

    // obj.protectedVar = 30;  // エラー
    // obj.protectedMethod();  // エラー

    return 0;
}
```

## 3-4.継承

継承は既存のクラスを基に新しいクラスを定義する機能です。

#### <font color="Red">基本クラス（親クラス）</font>

```
class Base {
public:
    void baseFunction() {
        std::cout << "Base function" << std::endl;
    }
};
```

#### <font color="Red">派生クラス（子クラス）</font>

```
class Derived : public Base {
public:
    void derivedFunction() {
        std::cout << "Derived function" << std::endl;
    }
};
```

#### 例：

```
int main() {
    Derived derived;
    derived.baseFunction();
    derived.derivedFunction();
    return 0;
}
```

## 3-5.ポリモーフィズム

ポリモーフィズム（多態性）は、同じインターフェースを通じて異なる実装を利用できるようにする機能です。特に、仮想関数を使用します。

#### <font color="Red">仮想関数</font>

```
class Base {
public:
    virtual void show() {
        std::cout << "Base class" << std::endl;
    }
};

class Derived : public Base {
public:
    void show() override {
        std::cout << "Derived class" << std::endl;
    }
};
```

#### 例：

```
int main() {
    Base* b;
    Derived d;
    b = &d;
    b->show();  // "Derived class"が出力される
    return 0;
}
```

# 4.高度なC++機能

## 4-1.テンプレート
テンプレートはデータ型に依存しない汎用的なコードを作成するための機能です。

## 関数テンプレート

```
template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << add<int>(2, 3) << std::endl;    // 5
    std::cout << add<double>(2.5, 3.5) << std::endl;  // 6.0
    return 0;
}
```

## クラステンプレート

```
template <typename T>
class Container {
private:
    T element;
public:
    Container(T e) : element(e) {}
    T getElement() {
        return element;
    }
};

int main() {
    Container<int> intContainer(42);
    Container<std::string> stringContainer("Hello");

    std::cout << intContainer.getElement() << std::endl;  // 42
    std::cout << stringContainer.getElement() << std::endl;  // Hello
    return 0;
}
```

## 4-2.名前空間

名前空間（namespace）は識別子のスコープを指定するために使用されます。

```
namespace MyNamespace {
    void myFunction() {
        std::cout << "Hello from MyNamespace" << std::endl;
    }
}

int main() {
    MyNamespace::myFunction();  // Hello from MyNamespace
    return 0;
}
```

# 4-3.標準テンプレートライブラリ
標準テンプレートライブラリ(<font color="Red">STL</font>)は、効率的なデータ操作を可能にするテンプレートクラスとテンプレート関数の集合です

<font color="Red">std::sort</font>
<font color="Red">std::sort</font>は<font color="Red">STL</font>（標準テンプレートライブラリ）の一部であり、配列またはコンテナ内の要素をソートするために使用されます。

```
#include <iostream>
#include <algorithm>
#include <vector>

int main() {
    // ベクター（動的配列）の初期化
    std::vector<int> vec = {5, 3, 1, 4, 2};
    // 要素をソート
    std::sort(vec.begin(), vec.end());

    std::cout << "Sorted vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}
```

### <font color="Red">std::vector</font>
<font color="Red">std::vector</font>は動的配列を表し、要素の追加や削除、アクセスが効率的に行えます。

```
#include <iostream>
#include <vector>

int main() {
    // ベクターの初期化
    std::vector<int> vec = {1, 2, 3, 4, 5};
    // 要素を追加
    vec.push_back(6);  

    std::cout << "Vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // 最後の要素を削除
    vec.pop_back();  

    std::cout << "After pop_back, vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}
```

### <font color="Red">std::map</font>
<font color="Red">std::map</font>はキーと値のペアを格納し、キーで検索できる連想コンテナです。

```
#include <iostream>
#include <map>

int main() {
    // マップの初期化
    std::map<std::string, int> myMap;
    myMap["one"] = 1;
    myMap["two"] = 2;

    std::cout << "Map elements:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // キー"one"を削除
    myMap.erase("one");  

    std::cout << "After erase, map elements:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}
```

### <font color="Red">std::set</font>の操作
<font color="Red">std::set</font>は重複を許さない、順序付けられた要素のコレクションです。

```
#include <iostream>
#include <set>

int main() {
    // セットの初期化
    std::set<std::string> mySet;
    mySet.insert("apple");
    mySet.insert("banana");
    mySet.insert("apple");  // 重複するため追加されない

    std::cout << "Set elements: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 要素"banana"を削除
    mySet.erase("banana");  

    std::cout << "After erase, set elements: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}
```

### <font color="Red">イテレータ</font>
イテレータはSTLコンテナを巡回するためのオブジェクトです。

```
#include <vector>
#include <iostream>

int main() {
    // ベクターの初期化
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // イテレータを使用してベクターの要素を巡回
    for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    return 0;
}
```

### <font color="Red">std::deque</font>
<font color="Red">std::deque（デック）</font>は両端からの高速な追加と削除を提供するシーケンスコンテナです。

```
#include <iostream>
#include <deque>

int main() {
    // デックの初期化
    std::deque<int> deq = {1, 2, 3, 4, 5};
    
    // 先頭に要素を追加
    deq.push_front(0);
    
    // 末尾に要素を追加
    deq.push_back(6);
    
    std::cout << "Deque elements: ";
    for (int i : deq) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // 先頭の要素を削除
    deq.pop_front();
    
    // 末尾の要素を削除
    deq.pop_back();

    std::cout << "After pop operations, deque elements: ";
    for (int i : deq) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}
```

### <font color="Red">std::stack</font>
<font color="Red">std::stack</font>は<font color="Red">LIFO（Last In First Out）</font>データ構造を提供するコンテナアダプタです。

```
#include <iostream>
#include <stack>

int main() {
    // スタックの初期化
    std::stack<int> stk;
    
    // 要素をスタックにプッシュ
    stk.push(1);
    stk.push(2);
    stk.push(3);

    std::cout << "Stack top element: " << stk.top() << std::endl;

    // 要素をポップ
    stk.pop();

    std::cout << "After pop, stack top element: " << stk.top() << std::endl;

    return 0;
}
```

### <font color="Red">std::queue</font>の操作
<font color="Red">std::queue</font>は<font color="Red">FIFO（First In First Out）</font>データ構造を提供するコンテナアダプタです。

```
#include <iostream>
#include <queue>

int main() {
    // キューの初期化
    std::queue<int> que;
    
    // 要素をキューにプッシュ
    que.push(1);
    que.push(2);
    que.push(3);

    std::cout << "Queue front element: " << que.front() << std::endl;
    std::cout << "Queue back element: " << que.back() << std::endl;

    // 要素をポップ
    que.pop();

    std::cout << "After pop, queue front element: " << que.front() << std::endl;

    return 0;
}
```

### <font color="Red">std::priority_queue</font>
<font color="Red">std::priority_queue</font>は優先度に基づいて要素を管理するヒープデータ構造です。

```
#include <iostream>
#include <queue>
#include <vector>

int main() {
    // 優先度キューの初期化（デフォルトは最大ヒープ）
    std::priority_queue<int> pq;
    
    // 要素をプッシュ
    pq.push(3);
    pq.push(5);
    pq.push(2);
    pq.push(4);

    std::cout << "Priority queue top element: " << pq.top() << std::endl;

    // 要素をポップ
    pq.pop();

    std::cout << "After pop, priority queue top element: " << pq.top() << std::endl;

    return 0;
}
```

### <font color="Red">std::list</font>の操作
<font color="Red">std::list</font>は双方向リストを表し、リスト中の任意の位置での効率的な挿入と削除を提供します。

```
#include <iostream>
#include <list>

int main() {
    // リストの初期化
    std::list<int> lst = {1, 2, 3, 4, 5};
    
    // 先頭に要素を追加
    lst.push_front(0);
    
    // 末尾に要素を追加
    lst.push_back(6);
    
    std::cout << "List elements: ";
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // 先頭の要素を削除
    lst.pop_front();
    
    // 末尾の要素を削除
    lst.pop_back();

    std::cout << "After pop operations, list elements: ";
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}
```

### <font color="Red">std::algorithm</font>の便利な関数
### <font color="Red">std::find</font>
<font color="Red">std::find</font>は範囲内での要素の検索を行います。見つからなかった場合は範囲の終わりを指すイテレータを返します。

```
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // ベクターの初期化
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 要素の検索
    auto it = std::find(vec.begin(), vec.end(), 3);

    if (it != vec.end()) {
        std::cout << "Element found: " << *it << std::endl;
    } else {
        std::cout << "Element not found" << std::endl;
    }

    return 0;
}
```

### <font color="Red">std::reverse</font>
<font color="Red">std::reverse</font>は範囲内の要素を反転させます。

```
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // ベクターの初期化
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 要素を反転
    std::reverse(vec.begin(), vec.end());

    std::cout << "Reversed vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}
```

### <font color="Red">std::accumulate</font>
<font color="Red">std::accumulate</font>は範囲内の要素の累積を計算します。\<numeric>ヘッダに含まれています。

```
#include <iostream>
#include <vector>
#include <numeric>

int main() {
    // ベクターの初期化
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 要素の累積を計算
    int sum = std::accumulate(vec.begin(), vec.end(), 0);

    std::cout << "Sum of vector elements: " << sum << std::endl;

    return 0;
}
```

## 4-4.例外処理
例外処理は、エラーが発生したときにプログラムの実行を中断し、適切な処理を行うための機能です。

#### <font color="Red">try-catchブロック</font>
例外が発生する可能性のあるコードをtryブロックに書き、例外が発生した場合の処理をcatchブロックに書きます。

```
#include <iostream>
#include <stdexcept>

int main() {
    try {
        // 例外が発生する可能性のあるコード
        throw std::runtime_error("An error occurred");
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
}
```

#### 複数のcatchブロック
異なる型の例外をキャッチするために複数のcatchブロックを使用できます。

```
#include <iostream>
#include <stdexcept>

int main() {
    try {
        // 例外が発生する可能性のあるコード
        throw std::out_of_range("Out of range error");
    } catch (const std::out_of_range& e) {
        std::cerr << "Out of range exception: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Other exception: " << e.what() << std::endl;
    }
    return 0;
}
```

#### 独自の例外クラスの作成
独自の例外クラスを作成することもできます。

```
#include <iostream>
#include <exception>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "My custom exception";
    }
};

int main() {
    try {
        throw MyException();
    } catch (const MyException& e) {
        std::cerr << "Caught: " << e.what() << std::endl;
    }
    return 0;
}
```

## 4-5.<font color="Red">スマートポインタ</font>
スマートポインタはメモリ管理を簡素化するためのクラスです。C++11以降では、標準ライブラリが提供するスマートポインタを使用することが推奨されます。

#### <font color="Red">std::unique_ptr</font>
<font color="Red">colerstd::unique_ptr</font>は所有権を唯一保持するスマートポインタです。所有権は移動できますが、コピーはできません。

```
#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    std::cout << *ptr << std::endl;  // 10
    return 0;
}
```

#### <font color="Red">std::shared_ptr</font>
<font color="Red">std::shared_ptr</font>は複数の所有者を持つことができるスマートポインタです。所有者の数がゼロになると、リソースは自動的に解放されます。

```
#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
    std::shared_ptr<int> ptr2 = ptr1;

    std::cout << *ptr1 << std::endl;  // 20
    std::cout << ptr1.use_count() << std::endl;  // 2 (ptr1 と ptr2 が同じメモリを共有している)
    return 0;
}
```

#### <font color="Red">std::weak_ptr</font>
<font color="Red">std::weak_ptr</font>は<font color="Red">std::shared_ptr</font>の循環参照を防ぐために使用されます。所有権は持ちませんが、std::shared_ptrの有効性を確認するために使用されます。

```
#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> sp = std::make_shared<int>(30);
    std::weak_ptr<int> wp = sp;

    if (auto spt = wp.lock()) { // std::shared_ptr に変換
        std::cout << *spt << std::endl;  // 30
    } else {
        std::cout << "Pointer is expired" << std::endl;
    }
    return 0;
}
```

# 5.練習問題

## 5-1.基本的な文法の練習問題

#### 問題1
2つの整数を引数として受け取り、その和を返す関数を作成してください。

```
int add(int a, int b) {
    // ここにコードを記述
}

int main() {
    std::cout << add(2, 3) << std::endl;  // 5
    return 0;
}
```

#### <font color="Red">解答例：</font>

```
#include <iostream>

int add(int a, int b) {
    return a + b;
}

int main() {
    std::cout << add(2, 3) << std::endl;  // 5
    return 0;
}
```

#### 問題2
if文を使って、入力された整数が正の数、負の数、またはゼロであるかを判定するプログラムを作成してください。

```
int main() {
    int num;
    std::cout << "Enter a number: ";
    std::cin >> num;

    // ここにコードを記述

    return 0;
}
```

#### <font color="Red">解答例：</font>

```
#include <iostream>

int main() {
    int num;
    std::cout << "Enter a number: ";
    std::cin >> num;

    if (num > 0) {
        std::cout << "The number is positive." << std::endl;
    } else if (num < 0) {
        std::cout << "The number is negative." << std::endl;
    } else {
        std::cout << "The number is zero." << std::endl;
    }

    return 0;
}
```

#### 問題3
Cスタイルの文字列を使用し、以下の操作を行ってください。

- 文字列の長さを計算する
- 文字列を別の場所にコピーする
- 2つの文字列を比較する

```
#include <iostream>
#include <cstring>

int main() {
    const char* str1 = "Hello, World!";
    const char* str2 = "Hello, C++!";
    char strCopy[50];

    // TODO: 1. str1の長さを計算
    // TODO: 2. str1をstrCopyにコピー
    // TODO: 3. str1とstr2を比較

    return 0;
}
```

#### <font color="Red">解答例：</font>
```

#include <iostream>
#include <cstring>

int main() {
    // 初めに文字列を宣言
    const char* str1 = "Hello, World!";
    const char* str2 = "Hello, C++!";
    char strCopy[50];

    // 1. str1の長さを計算
    size_t length = strlen(str1);
    std::cout << "Length of str1: " << length << std::endl;

    // 2. str1をstrCopyにコピー
    strcpy(strCopy, str1);
    std::cout << "Copied string: " << strCopy << std::endl;

    // 3. str1とstr2を比較
    int result = strcmp(str1, str2);
    if (result == 0) {
        std::cout << "str1 and str2 are equal" << std::endl;
    } else {
        std::cout << "str1 and str2 are not equal" << std::endl;
    }

    return 0;
}
```

## 5-2.オブジェクト指向の練習問題

#### 問題3
クラスを使ってシンプルな銀行口座システムを作成してください。口座には残高を持ち、入金と出金のメソッドを持つようにしてください。

```
class BankAccount {
public:
    // コンストラクタ
    BankAccount(double initial_balance);

    // メソッド
    void deposit(double amount);
    void withdraw(double amount);
    double getBalance() const;

private:
    double balance;
};

int main() {
    BankAccount account(1000.0);
    account.deposit(500.0);
    account.withdraw(200.0);
    std::cout << "Balance: " << account.getBalance() << std::endl;
    return 0;
}
```

#### <font color="Red">解答例：</font>
```
#include <iostream>

class BankAccount {
private:
    double balance;

public:
    // コンストラクタ
    BankAccount(double initial_balance) : balance(initial_balance) {}

    // メソッド
    void deposit(double amount) {
        balance += amount;
    }

    void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        } else {
            std::cout << "Insufficient balance" << std::endl;
        }
    }

    double getBalance() const {
        return balance;
    }
};

int main() {
    BankAccount account(1000.0);
    account.deposit(500.0);
    account.withdraw(200.0);
    std::cout << "Balance: " << account.getBalance() << std::endl;
    return 0;
}
```


#### 問題4
継承を使って動物のクラスを作成し、犬と猫のクラスをそれぞれ派生させてください。それぞれのクラスに特有のメソッドを追加してください。

#### <font color="Red">解答例：</font>
```
class Animal {
public:
    virtual void makeSound() const {
        std::cout << "Some generic animal sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() const override {
        std::cout << "Woof!" << std::endl;
    }
};

class Cat : public Animal {
public:
    void makeSound() const override {
        std::cout << "Meow!" << std::endl;
    }
};

int main() {
    Dog dog;
    Cat cat;

    dog.makeSound();  // Woof!
    cat.makeSound();  // Meow!

    return 0;
}
```

## 5-3.高度な機能の練習問題

#### 問題5
テンプレートを使って、任意のデータ型の配列をソートする関数を作成してください。

#### <font color="Red">解答例：</font>

```
template <typename T>
void sortArray(T arr[], int size) {
    // バブルソートの実装
    for (int i = 0; i < size - 1; ++i) {
        for (int j = 0; j < size - 1 - i; ++j) {
            if (arr[j] > arr[j + 1]) {
                std::swap(arr[j], arr[j + 1]);
            }
        }
    }
}

int main() {
    int intArray[] = {5, 2, 9, 1, 5, 6};
    double doubleArray[] = {3.1, 2.4, 1.8, 4.1};

    sortArray(intArray, 6);
    sortArray(doubleArray, 4);

    for (int i : intArray) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (double d : doubleArray) {
        std::cout << d << " ";
    }
    std::cout << std::endl;

    return 0;
}
```

#### 問題6
例外処理を使って、0で除算した場合に例外を投げる関数を作成してください。

#### <font color="Red">解答例：</font>
```
double divide(double a, double b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero");
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 2) << std::endl;  // 5
        std::cout << divide(10, 0) << std::endl;  // 例外が投げられる
    } catch (const std::runtime_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return 0;
}
```

# 6.まとめ
本教材では、Cの基本的な文法からオブジェクト指向プログラミング、さらに高度な機能までを紹介しました。Cは強力で柔軟な言語ですが、その分学ぶべきことも多くあります。ここで紹介した内容をしっかりと理解し、実際にコードを書いてみることが上達の近道です。個人的には次に何か成果物を作ってみることをおすすめします。