はじめに
この実験では、C++ 標準テンプレートライブラリ (STL) のさまざまなコンポーネントを使用して、ベクター、リスト、マップ、セットなどのデータ構造を作成および操作する方法を学びます。これらの STL コンテナの基本操作、要素の追加、削除、および反復処理についても検討します。また、これらのコンテナ内のデータのソート、検索、および処理に STL アルゴリズムを活用する方法を学びます。この実験が終了するとき、効率的で堅牢なアプリケーションを構築するために C++ STL の力と柔軟性をどのように活用するかを十分に理解しているでしょう。
ベクターコンテナを作成して操作する
このステップでは、C++ 標準テンプレートライブラリ (STL) のベクターコンテナについて学びます。これは、サイズが増減できる動的配列です。ベクターは、要素のコレクションを格納および操作するのに非常に役立ちます。
まず、WebIDE を開き、~/project ディレクトリに vector_demo.cpp という新しいファイルを作成します。ベクターの基本操作を順を追って検討しましょう。
touch ~/project/vector_demo.cpp
vector_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <vector>
int main() {
// 整数の空のベクターを作成する
std::vector<int> numbers;
// push_back() を使用して要素をベクターに追加する
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// ベクターのサイズを表示する
std::cout << "Vector size: " << numbers.size() << std::endl;
// インデックスを使用して要素にアクセスする
std::cout << "First element: " << numbers[0] << std::endl;
std::cout << "Second element: " << numbers[1] << std::endl;
// 範囲ベースの for ループを使用してベクターを反復処理する
std::cout << "All elements: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 最後の要素を削除する
numbers.pop_back();
// 要素を削除した後の新しいサイズを確認する
std::cout << "Vector size after pop_back(): " << numbers.size() << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ vector_demo.cpp -o vector_demo
./vector_demo
実行結果の例:
Vector size: 3
First element: 10
Second element: 20
All elements: 10 20 30
Vector size after pop_back(): 2
ベクターに関する要点:
#include <vector>を使用してベクターライブラリを含めるstd::vector<type>は特定の型のベクターを作成するpush_back()は要素をベクターの末尾に追加するsize()は要素の数を返す- インデックス
[]を使用して要素にアクセスする pop_back()は最後の要素を削除する- 範囲ベースの for ループはベクターを反復処理する簡単な方法である
リンクリスト操作にリストを使用する
このステップでは、C++ STL のリストコンテナについて学びます。これは、双方向リンクリストを実装しています。リストは、コンテナ内の任意の位置での効率的な挿入および削除操作を提供します。
WebIDE を開き、~/project ディレクトリに list_demo.cpp という新しいファイルを作成します。
touch ~/project/list_demo.cpp
list_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <list>
int main() {
// 整数の空のリストを作成する
std::list<int> numbers;
// 要素をリストに追加する
numbers.push_back(10); // 末尾に追加する
numbers.push_front(5); // 先頭に追加する
numbers.push_back(20);
// リストのサイズを表示する
std::cout << "List size: " << numbers.size() << std::endl;
// リストを反復処理する
std::cout << "List elements: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 要素を削除する
numbers.pop_front(); // 最初の要素を削除する
numbers.pop_back(); // 最後の要素を削除する
// 特定の位置に要素を挿入する
auto it = numbers.begin();
numbers.insert(it, 15);
// 更新されたリストを表示する
std::cout << "Updated list: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// リストが空かどうかを確認する
std::cout << "Is list empty? "
<< (numbers.empty()? "Yes" : "No") << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ list_demo.cpp -o list_demo
./list_demo
実行結果の例:
List size: 3
List elements: 5 10 20
Updated list: 15 10
Is list empty? No
リストに関する要点:
#include <list>を使用してリストライブラリを含めるpush_back()は要素を末尾に追加するpush_front()は要素を先頭に追加するpop_front()とpop_back()は要素を削除するinsert()は特定の位置に要素を追加することができるbegin()は最初の要素へのイテレータを返すempty()はリストが空かどうかを確認する
マップを使ってキーと値のペアを実装する
このステップでは、C++ STL のマップコンテナについて学びます。これは、キーと値のペアをソートされた一意のキー順で格納します。マップは辞書や連想配列を作成するのに便利です。
WebIDE を開き、~/project ディレクトリに map_demo.cpp という新しいファイルを作成します。
touch ~/project/map_demo.cpp
map_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <map>
#include <string>
int main() {
// 生徒の名前と年齢を格納するマップを作成する
std::map<std::string, int> students;
// キーと値のペアを挿入する
students["Alice"] = 20;
students["Bob"] = 22;
students["Charlie"] = 21;
// キーを使って値にアクセスする
std::cout << "Alice's age: " << students["Alice"] << std::endl;
// キーが存在するかどうかを確認する
if (students.count("David") == 0) {
std::cout << "David is not in the map" << std::endl;
}
// マップを反復処理する
std::cout << "All students:" << std::endl;
for (const auto& student : students) {
std::cout << student.first << ": " << student.second << std::endl;
}
// キーと値のペアを削除する
students.erase("Bob");
// マップのサイズを確認する
std::cout << "Number of students: " << students.size() << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ map_demo.cpp -o map_demo
./map_demo
実行結果の例:
Alice's age: 20
David is not in the map
All students:
Alice: 20
Bob: 22
Charlie: 21
Number of students: 2
マップに関する要点:
#include <map>を使ってマップライブラリを含めるmap<KeyType, ValueType>は指定されたキーと値の型でマップを作成する- 角括弧
[]を使って値にアクセスする count()はキーが存在するかどうかを確認する- 範囲ベースの for ループを使ってマップを反復処理する
erase()はキーと値のペアを削除するsize()は要素の数を返す
セットを使って一意の要素を格納する
このステップでは、C++ STL のセットコンテナについて学びます。これは、ソートされた順序で一意の要素を格納します。セットは自動的に重複値を防止し、特定の順序で要素を維持します。
WebIDE を開き、~/project ディレクトリに set_demo.cpp という新しいファイルを作成します。
touch ~/project/set_demo.cpp
set_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <set>
int main() {
// 整数のセットを作成する
std::set<int> numbers;
// 要素を挿入する
numbers.insert(10);
numbers.insert(20);
numbers.insert(30);
numbers.insert(10); // 重複するので追加されない
// セットのサイズを表示する
std::cout << "Set size: " << numbers.size() << std::endl;
// セットを反復処理する
std::cout << "Set elements: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 要素が存在するかどうかを確認する
if (numbers.count(20) > 0) {
std::cout << "20 is in the set" << std::endl;
}
// 要素を削除する
numbers.erase(20);
// 削除後のサイズを確認する
std::cout << "Set size after removal: " << numbers.size() << std::endl;
// セットをクリアする
numbers.clear();
// セットが空かどうかを確認する
std::cout << "Is set empty? "
<< (numbers.empty()? "Yes" : "No") << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ set_demo.cpp -o set_demo
./set_demo
実行結果の例:
Set size: 3
Set elements: 10 20 30
20 is in the set
Set size after removal: 2
Is set empty? Yes
セットに関する要点:
#include <set>を使ってセットライブラリを含めるset<type>は一意の要素のセットを作成するinsert()は要素を追加する(重複は無視される)count()は要素の存在を確認するerase()は要素を削除するclear()はすべての要素を削除するempty()はセットが空かどうかを確認する- 要素は自動的にソートされる
STL の sort アルゴリズムを使って要素をソートする
このステップでは、STL のソートアルゴリズムを使って要素を昇順または降順に並べる方法を学びます。<algorithm> ライブラリは、さまざまなコンテナに対して強力なソート機能を提供します。
WebIDE を開き、~/project ディレクトリに sort_demo.cpp という新しいファイルを作成します。
touch ~/project/sort_demo.cpp
sort_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 整数のベクターを作成する
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
// 元のベクターを表示する
std::cout << "Original vector: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// ベクターを昇順にソートする
std::sort(numbers.begin(), numbers.end());
// ソート済みのベクターを表示する
std::cout << "Sorted vector (ascending): ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// ベクターを降順にソートする
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
// 降順にソートされたベクターを表示する
std::cout << "Sorted vector (descending): ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ sort_demo.cpp -o sort_demo
./sort_demo
実行結果の例:
Original vector: 5 2 8 1 9 3
Sorted vector (ascending): 1 2 3 5 8 9
Sorted vector (descending): 9 8 5 3 2 1
STL のソートに関する要点:
- ソートに
<algorithm>ライブラリを含める std::sort()はさまざまなコンテナで動作する- デフォルトのソートは昇順
std::greater<type>()は降順にソートする- ソートは元のコンテナを変更しながらインプレースで行われる
- さまざまなコンテナ型で効率的に動作する
STL アルゴリズムを使って要素を検索する
このステップでは、STL アルゴリズムを使ってコンテナ内の要素を検索する方法を学びます。<algorithm> ライブラリは、要素の検索と位置特定に強力な関数を提供します。
WebIDE を開き、~/project ディレクトリに find_demo.cpp という新しいファイルを作成します。
touch ~/project/find_demo.cpp
find_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 整数のベクターを作成する
std::vector<int> numbers = {5, 2, 8, 1, 9, 3, 8};
// 特定の要素の最初の出現位置を検索する
auto it = std::find(numbers.begin(), numbers.end(), 8);
if (it!= numbers.end()) {
std::cout << "8 の最初の出現位置はインデックス:"
<< std::distance(numbers.begin(), it) << std::endl;
}
// 要素の出現回数を数える
int count = std::count(numbers.begin(), numbers.end(), 8);
std::cout << "ベクター内の 8 の数:" << count << std::endl;
// 6 より大きい要素があるかどうかを検索する
bool has_large_element = std::any_of(numbers.begin(), numbers.end(),
[](int n) { return n > 6; });
std::cout << "ベクターに 6 より大きい要素がある:"
<< (has_large_element? "Yes" : "No") << std::endl;
// 最小値と最大値の要素を検索する
auto min_it = std::min_element(numbers.begin(), numbers.end());
auto max_it = std::max_element(numbers.begin(), numbers.end());
std::cout << "最小値の要素:" << *min_it << std::endl;
std::cout << "最大値の要素:" << *max_it << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ find_demo.cpp -o find_demo
./find_demo
実行結果の例:
8の最初の出現位置はインデックス: 2
ベクター内の8の数: 2
ベクターに6より大きい要素がある: Yes
最小値の要素: 1
最大値の要素: 9
STL 検索アルゴリズムに関する要点:
std::find()は要素の最初の出現位置を特定するstd::count()は要素の出現回数を数えるstd::any_of()は任意の要素が条件を満たすかどうかをチェックするstd::min_element()とstd::max_element()は極端な値を見つける- ラムダ関数を使ってカスタム検索条件を指定できる
- 返されるイテレータは見つかった要素を指す
コンテナを反復処理する
このステップでは、さまざまな反復処理手法を使って STL コンテナを反復処理するさまざまな方法を学びます。範囲ベースの for ループ、イテレータ、そして従来のインデックスベースの反復処理を検討します。
WebIDE を開き、~/project ディレクトリに iteration_demo.cpp という新しいファイルを作成します。
touch ~/project/iteration_demo.cpp
iteration_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <vector>
#include <list>
#include <map>
int main() {
// ベクターの反復処理
std::vector<int> numbers = {10, 20, 30, 40, 50};
// 方法 1: 範囲ベースの for ループ(最も現代的で読みやすい)
std::cout << "ベクターの反復処理(範囲ベースの for):" << std::endl;
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 方法 2: イテレータベースの反復処理
std::cout << "ベクターの反復処理(イテレータ):" << std::endl;
for (auto it = numbers.begin(); it!= numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 方法 3: インデックスベースの反復処理
std::cout << "ベクターの反復処理(インデックスベース):" << std::endl;
for (size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
// マップの反復処理
std::map<std::string, int> ages = {
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35}
};
std::cout << "マップの反復処理:" << std::endl;
for (const auto& pair : ages) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
プログラムをコンパイルして実行します。
g++ iteration_demo.cpp -o iteration_demo
./iteration_demo
実行結果の例:
ベクターの反復処理(範囲ベースのfor):
10 20 30 40 50
ベクターの反復処理(イテレータ):
10 20 30 40 50
ベクターの反復処理(インデックスベース):
10 20 30 40 50
マップの反復処理:
Alice: 25
Bob: 30
Charlie: 35
コンテナの反復処理に関する要点:
- 範囲ベースの for ループは最も現代的で読みやすい
- イテレータはコンテナの反復処理を細かく制御できる
- インデックスベースの反復処理はランダムアクセスコンテナでうまく機能する
autoキーワードは型推論に役立つ- さまざまなコンテナはさまざまな反復処理方法をサポートする
STL のスタックとキューを使用する
このステップでは、2 つの重要な STL コンテナアダプタであるスタックとキューについて学びます。これらのコンテナは、後入先出し (LIFO: Last In, First Out) および先入先出し (FIFO: First In, First Out) のデータ管理に特化した操作を提供します。
WebIDE を開き、~/project ディレクトリに stack_queue_demo.cpp という新しいファイルを作成します。
touch ~/project/stack_queue_demo.cpp
stack_queue_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <stack>
#include <queue>
int main() {
// スタックのデモ
std::stack<int> myStack;
// 要素をスタックにプッシュする
myStack.push(10);
myStack.push(20);
myStack.push(30);
std::cout << "スタックの操作:" << std::endl;
std::cout << "トップ要素:" << myStack.top() << std::endl;
// トップ要素を削除する
myStack.pop();
std::cout << "ポップ後のトップ要素:" << myStack.top() << std::endl;
std::cout << "スタックのサイズ:" << myStack.size() << std::endl;
// キューのデモ
std::queue<std::string> myQueue;
// 要素をキューに追加する
myQueue.push("Alice");
myQueue.push("Bob");
myQueue.push("Charlie");
std::cout << "\nキューの操作:" << std::endl;
std::cout << "先頭要素:" << myQueue.front() << std::endl;
std::cout << "末尾要素:" << myQueue.back() << std::endl;
// 先頭要素を削除する
myQueue.pop();
std::cout << "ポップ後の先頭要素:" << myQueue.front() << std::endl;
std::cout << "キューのサイズ:" << myQueue.size() << std::endl;
return 0;
}
プログラムをコンパイルして実行します。
g++ stack_queue_demo.cpp -o stack_queue_demo
./stack_queue_demo
実行結果の例:
スタックの操作:
トップ要素: 30
ポップ後のトップ要素: 20
スタックのサイズ: 2
キューの操作:
先頭要素: Alice
末尾要素: Charlie
ポップ後の先頭要素: Bob
キューのサイズ: 2
スタックとキューに関する要点:
- スタック (LIFO - 後入先出し)
push()は要素をトップに追加するpop()はトップ要素を削除するtop()はトップ要素を返す
- キュー (FIFO - 先入先出し)
push()は要素を末尾に追加するpop()は先頭要素を削除するfront()は最初の要素を返すback()は最後の要素を返す
- 両方とも要素数を確認するための
size()メソッドがある <stack>と<queue>ヘッダを含める
コンテナの例外安全性を処理する
このステップでは、例外を処理し、STL コンテナを使った安全な操作を確保する方法を学びます。例外処理は、プログラムのクラッシュを防ぎ、堅牢なエラー管理を提供します。
WebIDE を開き、~/project ディレクトリに exception_safety_demo.cpp という新しいファイルを作成します。
touch ~/project/exception_safety_demo.cpp
exception_safety_demo.cpp ファイルに次のコードを追加します。
#include <iostream>
#include <vector>
#include <stdexcept>
void demonstrateVectorSafety() {
std::vector<int> numbers;
try {
// 空のベクターから要素にアクセスしようとする
std::cout << "空のベクターから要素にアクセスしようとしています:" << std::endl;
numbers.at(0); // これは out_of_range 例外を投げます
}
catch (const std::out_of_range& e) {
std::cout << "範囲外エラー: " << e.what() << std::endl;
}
// 安全な要素追加
try {
numbers.push_back(10);
numbers.push_back(20);
std::cout << "ベクターのサイズ:" << numbers.size() << std::endl;
// 安全な要素アクセス
std::cout << "最初の要素:" << numbers.at(0) << std::endl;
std::cout << "2 番目の要素:" << numbers.at(1) << std::endl;
}
catch (const std::exception& e) {
std::cout << "エラーが発生しました:" << e.what() << std::endl;
}
}
int main() {
// ベクターの例外安全性を示す
demonstrateVectorSafety();
return 0;
}
プログラムをコンパイルして実行します。
g++ exception_safety_demo.cpp -o exception_safety_demo
./exception_safety_demo
実行結果の例:
空のベクターから要素にアクセスしようとしています:
範囲外エラー: vector
ベクターのサイズ: 2
最初の要素: 10
2番目の要素: 20
コンテナの例外安全性に関する要点:
- 潜在的な例外を処理するために
try-catchブロックを使用する - 無効なベクター要素にアクセスするときに
std::out_of_rangeが投げられる at()メソッドは[]演算子とは異なり、境界チェックを行う- 最初に特定の例外をキャッチし、その後より一般的な例外をキャッチする
- 常に潜在的な例外を処理して、プログラムのクラッシュを防ぐ
<stdexcept>からの標準例外クラスを使用する
まとめ
この実験では、C++ 標準テンプレートライブラリ (STL) のさまざまなコンポーネントとそれらを効果的に使用する方法を学びました。まず、サイズが増減できる動的配列であるベクターコンテナを調べました。要素の追加と削除、インデックスを使ったアクセス、範囲ベースの for ループを使ったベクターの反復処理方法を学びました。
次に、双方向リンクリストの実装であるリストコンテナについて掘り下げました。挿入、削除、要素のトラバースなどの一般的なリンクリスト操作を行う方法を学びました。また、キーと値のペアを格納するマップコンテナと、一意の要素を格納するセットコンテナについても調べました。さらに、sort や find などの STL アルゴリズムを使ってこれらのコンテナ内の要素を操作したり検索したりする方法を学びました。最後に、スタックとキューコンテナについて調べ、STL コンポーネントを使用する際の例外安全性の重要性について議論しました。



