C言語には「文字列型」が存在しない。文字列は char 型の配列として扱われ、必ず末尾に終端文字 '¥0'(ヌル文字)が付く。2級ではこの仕組みと string.h の関数、メモリ上の並びが問われる。
'¥0' を説明できる ② strlen/strcpy/strncpy/strcmp の動作と戻り値が分かる ③ 文字列の配列 char s[][N] の各要素にアクセスできる。
配列は、同じ型のデータを連続したメモリ領域に並べて格納するデータ構造である。
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) */
文字列は char 配列として宣言する。文字列リテラルで初期化すると、末尾に終端文字 '¥0' が自動的に付く。
char str[6] = "Hello"; /* H e l l o ¥0 の6文字ぶん */
char str[] = "Hello"; /* 要素数は初期化式から決まる(=6) */
宣言 char str[6] = "Hello"; はメモリ上に次のように並ぶ。
'¥0'(5文字 + 終端で 6 バイト)'¥0')。strlen や strcpy などの文字列関数は '¥0' を見つけるまで処理を続ける。'¥0' が無いと、メモリの不正アクセス(暴走)が起こりうる。
文字列を操作するには標準ライブラリ <string.h> を使う。
| 関数 | 機能 | 使用例 |
|---|---|---|
strlen | 文字列の長さを返す('¥0' は数えない) | size_t len = strlen(str); |
strcpy | 文字列をコピー | strcpy(dest, src); |
strcat | 文字列を末尾に連結 | strcat(dest, src); |
strcmp | 2つの文字列を比較(等しいと 0) | int c = strcmp(s1, s2); |
strncpy | 最大 n 文字だけコピー | strncpy(dest, src, n); |
strchr | 指定文字が最初に現れる位置(アドレス)を返す | char *p = strchr(str, 'e'); |
strcmp の戻り値は「等しい→0/s1が大きい→正/s1が小さい→負」。「等しいと0」がよく問われる(0以外=違う、と覚える)。
複数の文字列をまとめて持つには、文字列の配列(2次元 char 配列)を使う。
char str[][10] = { "Hello", "World", "C" };
str は3つの文字列を保持する。'¥0' を含む)。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"
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;
}
%s は先頭から '¥0' まで表示するので、実行結果は:
Result: XXHello
char 配列。末尾に終端文字 '¥0' が必要。'¥0' のぶん)。strlen は '¥0' を数えない。<string.h>。strcmp は等しいと 0。char s[][N]。s[i] は文字列、s[i][j] は1文字。