Cスタイルの弦
C++には[2種類の]stringがあります:
- C [スタイル]文字列([文字]配列)
- C++の文字列([後ほど学習します])
[このレッスンではまず] C [スタイルの] string について学びます――[これは] C++ が [C 言語と] [互換性を保つために受け継いだ] [遺産]であり、[これを理解することは] string [の内部の仕組み] を理解する上で役立ちます。
1. C [スタイル]string とは何ですか?
(1) 1.1 [本質]:[文字]配列 + [終了記号]
C [スタイル]文字列は、[単なる][文字]配列ですが、[1つの特別なルールがあります]:
- [最後の文字は]
\0([空白文字]、ASCII [コードは] 0)でなければならない \0[stringの終了を示すために使用]
"Hello":
+---+---+---+---+---+----+
| H | e | l | l | o | \0 |
+---+---+---+---+---+----+
0 1 2 3 4 5 ←
💡 [要点]: C [スタイル]の文字列[の][長さ][は] 5(Hello)ですが、配列[のサイズ][は少なくとも] 6(\0を格納する必要があるため)です。
2. 宣言と初期化
(1) 2.1 C [スタイル]文字列の宣言
[文法]:
char ;
例:
▶ サンプル 2: [基礎プログラミングの実践] (難易度 ⭐)
#include iostream
int main() {
char name[20]; // 19 + 1 \0
name[0] = 'H';
name[1] = 'e';
name[2] = 'l';
name[3] = 'l';
name[4] = 'o';
name[5] = '\0'; //!
std::cout << ":" << name << std::endl; // Hello
return 0;
}
💡 [ヒント]: [手動で追加] \0 [面倒]ですが、[後でより簡単な方法を学びます]。
(2) 2.2 C [スタイル]文字列の初期化
[方法1]:[文字列リテラルによる]初期化
#include iostream
int main() {
char name = "Hello"; // ✅ compilation \0,array 6
std::cout << ":" << name << std::endl;
return 0;
}
💡 [ポイント]: [文字列リテラルを]初期化する際、[配列のサイズ]を指定する必要はありません——コンパイラが[自動的に計算]します(\0も含む)。
3. [常用]文字列関数
C [スタイル]の文字列[に関する]関数[はすべて] cstring ヘッダーファイル[の中に]あります。
(1) 3.1 strlen:[計算]文字列[の長さ]
#include iostream
#include cstring // ...
int main() {
char name = "Hello";
std::cout << ":" << name << std::endl;
std::cout << ":" << std::strlen(name) << std::endl; // 5( \0)
return 0;
}
💡 [ヒント]: std::strlen [は][有効文字数]を返します(\0は含まれません)。一方、sizeof [は]array[のサイズ]を返します(\0を含みます)。
char name = "Hello";
std::cout << sizeof(name) << std::endl; // 6(array)
std::cout << std::strlen(name) << std::endl; // 5(Yes)
(2) 3.2 strcpy:[コピー]文字列
#include iostream
#include cstring
int main() {
char src = "Hello";
char dest[20];
std::strcpy(dest, src); // src dest
std::cout << "src:" << src << std::endl;
std::cout << "dest:" << dest << std::endl;
return 0;
}
⚠️ 警告: std::strcpy は [ターゲット] の [配列] [のサイズ] を [チェックしない] ため、[もし] dest が [小さすぎる] 場合、バッファオーバーフロー が発生する!
[より安全な]関数(C++11 [以降]):
std::strncpy(dest, src, sizeof(dest) - 1); // sizeof(dest)-1
dest[sizeof(dest) - 1] = '\0'; // ...
(3) 3.3 strcat:[連結]string
#include iostream
#include cstring
int main() {
char greeting[50] = "Hello, ";
char name = "World";
std::strcat(greeting, name); // name greeting
std::cout << greeting << std::endl; // Hello, World
return 0;
}
(4) 3.4 strcmp:[比較]文字列
#include iostream
#include cstring
int main() {
char str1 = "Hello";
char str2 = "Hello";
char str3 = "World";
std::cout << "strcmp(str1, str2) = " << std::strcmp(str1, str2) << std::endl;
std::cout << "strcmp(str1, str3) = " << std::strcmp(str1, str3) << std::endl;
return 0;
}
[戻る]値:
0:[2つの]文字列[が等しい]< 0:[1番目の]文字列[が2番目の文字列より小さい]> 0:[1番目の]文字列[が2番目の]より大きい
💡 [ヒント]: == [C] [スタイル]の文字列を[比較]してはいけません!== [比較するのは]アドレスであり、[内容]ではありません。
char str1 = "Hello";
char str2 = "Hello";
if (str1 == str2) { // ❌:'s,
// ...
}
if (std::strcmp(str1, str2) == 0) { // ✅:Using strcmp
// ...
}
4. [cin] [と] [cout] による C スタイルの文字列の処理
(1) 4.1 [読み取り]string
#include iostream
int main() {
char name[20];
std::cout << ":";
std::cin >> name; // ✅ string(butYes)
std::cout << "," << name << "!" << std::endl;
return 0;
}
💡 [問題]: cin >> [スペースに遭遇すると停止してしまう]![もし]input "John Smith" すると、[読み取れるのは] "John" だけだ。
[解決方法]:[YIJIAN0PHを使用]
#include iostream
int main() {
char name[50];
std::cout << ":";
std::cin.getline(name, 50); // ✅ ()
std::cout << "," << name << "!" << std::endl;
return 0;
}
5. 演習:[簡単な]文字列[処理]
▶ サンプル 1: [統計]文字列[の中母音の個数] (難易度 ⭐⭐)
#include iostream
#include cstring
int main() {
char str[100];
std::cout << ":";
std::cin.getline(str, 100);
int vowels = 0;
for (int i = 0; i < std::strlen(str); i++) {
char c = str[i];
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
vowels++;
}
}
std::cout << ":" << vowels << std::endl;
return 0;
}
[動作結果]:
World:3
6. [よくある]エラー
(1) 6.1 [スペースを確保し忘れた] \0
エラー例:
#include iostream
int main() {
char name[5] = "Hello"; // ❌:"Hello" 6 ( \0),butarrayYes 5
std::cout << name << std::endl;
return 0;
}
[修正]:
char name[6] = "Hello"; // ✅:array 6
(2) 6.2 [用] = [賦]valuestring
エラー例:
#include iostream
int main() {
char str1[20];
char str2 = "Hello";
str1 = str2; // ❌:arrayvalue
str1 = "World"; // ❌:arrayvalue
return 0;
}
[修正]:[使用] strcpy
#include iostream
#include cstring
int main() {
char str1[20];
char str2 = "Hello";
std::strcpy(str1, str2); // ✅:Using strcpy
std::cout << str1 << std::endl;
return 0;
}
❓ よくある質問
📖 まとめ
- C [スタイル]文字列[は文字]配列であり、[は]
\0[で終わる] - [常用]関数:
strlen([長さ])、strcpy([コピー])、strcat([連結])、strcmp([比較]) - [使用しない]
==[比較] C [スタイル]string,[使用]strcmp - [不要用]
=[賦]value C [スタイル]string,[用]strcpy - C [スタイル]string[安全でない]([発生しやすい]バッファ[オーバーフロー])、[優先して] C++のstringを使用
📝 練習問題
-
初心者(難易度 ⭐): [Cスタイルの]文字列
char str = "Hello, World!"を宣言し、[その長さと各文字]を出力せよ。 -
中級(難易度 ⭐⭐): [プログラム]を作成し、[ユーザーに][2つの]文字列を入力させ、[それらが等しいかどうかを比較する](
strcmpを使用)。 -
上級(難易度 ⭐⭐⭐): 「文字列の逆順化」を[実装]する[プログラム]を作成してください:
-
[ユーザーに][1つの]文字列を入力させる
-
[反転させる]([例]
"Hello"を"olleH"に変える) -
[使用言語] C [スタイル] string [実装]([使用不可] C++のstring)
-
C [スタイル]文字列:[文字]配列[は] \0 [で終わる]
-
[常用]関数:strlen/strcpy/strcat/strcmp
-
C文字列[ダブルクォートで初期化]、char配列[確保が必要] \0 [領域]
-
[欠点]:[安全性に問題あり](バッファ[オーバーフロー])、[操作が面倒]
-
[現代] C++ [推奨] std::string [代替] C [スタイル] string
7. 🚀 次は
[習得した] Cの[スタイル]のstring、[次は] C++のstring([第]19[回])を学びましょう――[より安全]で[使いやすい]stringクラス!



