01 文字列操作(char 配列・終端文字・string.h)

C言語には「文字列型」が存在しない。文字列は char 型の配列として扱われ、必ず末尾に終端文字 '¥0'(ヌル文字)が付く。2級ではこの仕組みと string.h の関数、メモリ上の並びが問われる。

✅ この章のゴール:① 文字列=char配列+'¥0' を説明できる ② strlen/strcpy/strncpy/strcmp の動作と戻り値が分かる ③ 文字列の配列 char s[][N] の各要素にアクセスできる。

01-1 配列の宣言と初期化

配列は、同じ型のデータを連続したメモリ領域に並べて格納するデータ構造である。

int  arr[5];    /* 整数型を5要素ぶん確保 */
char str[10];   /* 文字型を10要素ぶん確保 */

宣言と同時に初期値を与えることもできる。

int num[10] = {1,2,3,4,5,6,7,8,9,0};  /* 各要素に値を格納 */
int num[]   = {1,2,3,4,5,6,7,8,9,0};  /* 要素数は初期化式から決まる(=10) */

01-2 文字列の宣言と終端文字

文字列は char 配列として宣言する。文字列リテラルで初期化すると、末尾に終端文字 '¥0' が自動的に付く

char str[6] = "Hello";  /* H e l l o ¥0 の6文字ぶん */
char str[]  = "Hello";  /* 要素数は初期化式から決まる(=6) */

メモリマップ

宣言 char str[6] = "Hello"; はメモリ上に次のように並ぶ。

H
0
e
1
l
2
l
3
o
4
¥0
5
青いマスが終端文字 '¥0'(5文字 + 終端で 6 バイト)
⚠ 「Hello」は5文字だが、確保されるのは 6バイト(5文字 + 終端文字 '¥0')。
strlenstrcpy などの文字列関数は '¥0' を見つけるまで処理を続ける。'¥0' が無いと、メモリの不正アクセス(暴走)が起こりうる。

01-3 string.h の主な関数

文字列を操作するには標準ライブラリ <string.h> を使う。

関数機能使用例
strlen文字列の長さを返す('¥0' は数えない)size_t len = strlen(str);
strcpy文字列をコピーstrcpy(dest, src);
strcat文字列を末尾に連結strcat(dest, src);
strcmp2つの文字列を比較(等しいと 0int c = strcmp(s1, s2);
strncpy最大 n 文字だけコピーstrncpy(dest, src, n);
strchr指定文字が最初に現れる位置(アドレス)を返すchar *p = strchr(str, 'e');
strcmp の戻り値は「等しい→0/s1が大きい→正/s1が小さい→負」。「等しいと0」がよく問われる(0以外=違う、と覚える)。

01-4 文字列の配列

複数の文字列をまとめて持つには、文字列の配列(2次元 char 配列)を使う。

char str[][10] = { "Hello", "World", "C" };

メモリマップ

H
e
l
l
o
¥0
str[0]
W
o
r
l
d
¥0
str[1]
C
¥0
str[2]
0123456789

要素へのアクセス

printf("%s¥n", str[0]);     /* "Hello" を表示(str[0] は文字列の先頭アドレス) */
printf("%s¥n", str[1]);     /* "World" を表示 */
printf("%s¥n", str[2]);     /* "C" を表示 */

printf("%c¥n", str[0][1]);  /* 'e' を表示(str[0] の1番目の "1文字") */
printf("%c¥n", str[1][2]);  /* 'r' を表示 */
よくある間違いstr[0][1]1文字(char'e'であって文字列ではない。
printf("%s", str[0][1]) のように %s に1文字を渡すと暴走する(未定義動作)。
e から後ろ("ello")」を文字列として表示したいなら、アドレスを渡す
printf("%s¥n", str[0] + 1); または printf("%s¥n", &str[0][1]);"ello"

01-5 strncpy の応用(途中にコピー)

strncpy(コピー先, コピー元, 文字数)。コピー先・コピー元はアドレスなので、dest + 2 のように「途中の位置」から始められる。

#include <stdio.h>
#include <string.h>

int main(void)
{
    char src[]     = "Hello, World!";
    char dest[20]  = "XXXXXXXXXXXXXXX";   /* X が15個 */

    strncpy(dest + 2, src, 5);  /* dest の index 2 から "Hello" を5文字コピー */
    dest[7] = '¥0';             /* 終端文字を手動で付ける */

    printf("Result: %s¥n", dest);
    return 0;
}

コピー後のメモリ

X
0
X
1
H
2
e
3
l
4
l
5
o
6
¥0
7
X
8
X
9

%s は先頭から '¥0' まで表示するので、実行結果は:

Result: XXHello

01-6 📝 過去問で確認

過去問(文字列操作・問3)— プログラムの出力 (15)〜(19) を解いてみよう
文字列操作の過去問 問題①
問題 ①
文字列操作の過去問 問題②
問題 ②
解説を表示
文字列操作の過去問 解説①
解説 ①
文字列操作の過去問 解説②
解説 ②

01-7 まとめ