C++: 練習:ポインタと参照
最終更新:2026-08-31
これまでポインタと参照を学びましたが、実際のプログラムでは組み合わせて使うことが多いです。
このレッスンでは、総合的な実例でポインタと参照を練習します。
1. 実践例:ポインタで文字列を反転
▶ サンプル 1:文字列の反転(難易度 ⭐⭐)
CPP
#include <iostream>
#include <cstring>
void reverseString(char* str) {
int len = std::strlen(str);
char* left = str;
char* right = str + len - 1;
while (left < right) {
// leftとrightの文字を交換
char temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}
int main() {
char str[] = "Hello, World!";
std::cout << "反転前:" << str << std::endl;
reverseString(str);
std::cout << "反転後:" << str << std::endl;
return 0;
}
出力:
TEXT 📖 参照専用反転前:Hello, World! 反転後:!dlroW ,olleH
2. 実践例:動的な構造体配列
▶ サンプル 2:動的配列(難易度 ⭐⭐⭐)
CPP
#include <iostream>
#include <string>
struct Student {
std::string name;
int age;
double score;
};
int main() {
int n;
std::cout << "学生数を入力:";
std::cin >> n;
// 動的にn個のStudentを確保
Student* students = new Student[n];
// データを入力
for (int i = 0; i < n; i++) {
std::cout << "学生" << i + 1 << "の名前:";
std::cin.ignore();
std::getline(std::cin, students[i].name);
std::cout << "年齢:";
std::cin >> students[i].age;
std::cout << "点数:";
std::cin >> students[i].score;
}
// 出力
std::cout << "\n========== 学生一覧 ==========\n";
for (int i = 0; i < n; i++) {
std::cout << i + 1 << ". " << students[i].name
<< "、年齢:" << students[i].age
<< "、点数:" << students[i].score << std::endl;
}
// 解放
delete[] students;
return 0;
}
3. 実践例:連結リスト(LinkedList)
(1) 3.1 連結リストとは?
連結リストは動的なデータ構造 —— 要素(ノード)と次の要素へのポインタで構成。
| 特徴 | プログラムでの意味 |
|---|---|
| 動的なサイズ変更(実行時) | 連結リスト |
▶ サンプル 3:単方向連結リスト(難易度 ⭐⭐⭐)
CPP
#include <iostream>
struct Node {
int data;
Node* next;
};
int main() {
// 3つのノードを作成
Node* head = new Node{1, nullptr};
Node* second = new Node{2, nullptr};
Node* third = new Node{3, nullptr};
// 連結
head->next = second;
second->next = third;
// 先頭から走査
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
// 解放
delete head;
delete second;
delete third;
return 0;
}
出力:
TEXT 📖 参照専用1 2 3
💡 ヒント: 連結リストの操作は、単純なようで実はバグが起きやすい。注意深く実装。
4. 練習:アドレス帳(動的メモリ)
▶ サンプル 4:動的アドレス帳(難易度 ⭐⭐⭐)
CPP
#include <iostream>
#include <string>
#include <cstring>
struct Contact {
char name[50];
char phone[20];
Contact* next; // 次の連絡先
};
Contact* head = nullptr; // 先頭ポインタ
void addContact(const std::string& name, const std::string& phone) {
Contact* newContact = new Contact;
std::strcpy(newContact->name, name.c_str());
std::strcpy(newContact->phone, phone.c_str());
newContact->next = head; // 先頭に追加
head = newContact; // 新しい先頭
}
void printContacts() {
if (head == nullptr) {
std::cout << "連絡先がありません!" << std::endl;
return;
}
std::cout << "\n========== 連絡先一覧 ==========\n";
Contact* current = head;
int index = 1;
while (current != nullptr) {
std::cout << index << ". " << current->name
<< " - " << current->phone << std::endl;
current = current->next;
index++;
}
}
int main() {
addContact("MOTO", "13800138000");
addContact("Alice", "13900139000");
addContact("Bob", "13700137000");
printContacts();
// 解放(演習)
// ...
return 0;
}
❓ よくある質問
Q メモリリークを避けるには?
A
newとdeleteを必ずペアで書く- 解放後は
nullptrを代入 - スマートポインタ
📖 まとめ
- ポインタと参照は組み合わせて使う —— 参照はコードを簡潔に、ポインタは動的メモリに
- ポインタで動的データ構造を実装(連結リスト、ツリー、グラフ)
- 動的メモリは必ず解放(
delete) - 連結リストは動的なサイズのデータ構造
📝 練習問題
-
初級(難易度 ⭐): 関数
void swap(int* a, int* b)を書いてください。ポインタで変数の値を交換。 -
中級(難易度 ⭐⭐): プログラムを書いてください。動的メモリで
int配列を確保し、ユーザー入力で配列に値を入れ、配列を反転して出力。 -
上級(難易度 ⭐⭐⭐): 「動的アドレス帳」プログラムを完成:
- 「削除」機能を追加
- 「検索」機能を追加
- プログラム終了時に動的メモリをすべて解放
5. 🚀 次のステップ
おめでとう!フェーズ4(ポインタと参照)の学習が完了しました。 次は フェーズ5(オブジェクト指向プログラミング) —— C++の中核、クラス、オブジェクト、継承、ポリモーフィズムを学ぼう!