C言語の基本|C言語の文字列操作関数の基本

長さを調べ、文字列を正しくコピーしよう。文字列操作関数を知れば、C言語で扱えるデータの幅が大きく広がる

C言語でプログラムを作っていると、文字列を扱う場面がたくさんあります。

例えば、入力された名前を表示する、メッセージの長さを調べる、商品名を別の配列へコピーする、文字列の一部分だけを取り出すといった処理です。

C言語には、ほかの多くのプログラミング言語にあるような組み込みの文字列型がありません。文字列はchar型の配列として表現し、最後に文字列の終わりを示すナル文字を置きます。

例えば、ABCという文字列は、配列の中で次のように格納されます。

'A'  'B'  'C'  '\0'

A、B、Cの後ろに置かれている\0がナル文字です。C言語の文字列操作関数は、このナル文字を見つけることで文字列の終わりを判断します。

文字列がchar型の配列として表現されるため、整数や実数と同じ感覚ですべての処理を行うことはできません。配列同士を代入演算子でコピーしたり、文字列の長さを変数の値として直接取り出したりすることはできないのです。

そこで利用するのが、string.hで宣言されている文字列操作関数です。

代表的な文字列操作関数には、次のようなものがあります。

  • strlenで文字列の長さを調べる
  • strcpyで文字列全体をコピーする
  • strncpyで指定した数の文字をコピーする
  • strcmpで2つの文字列を比較する
  • strcatで文字列を連結する
  • strchrで指定した文字を探す
  • strstrで部分文字列を探す

ここでは、strlen、strcpy、strncpyを中心に、それぞれの役割、使い方、戻り値、ナル文字の扱い、コピー先の配列サイズに関する注意点を確認します。

文字列操作関数を正しく使うには、関数名だけでなく、文字列がメモリ上にどのように並んでいるのかを理解することが大切です。配列とナル文字の関係を思い浮かべながら学んでいきましょう。

文字列操作関数とは

文字列操作関数とは、char型の配列で表された文字列を調べたり、コピーしたり、比較したりするための標準ライブラリ関数です。

文字列操作関数を使うときは、string.hをインクルードします。

#include <string.h>

string.hには、文字列やメモリを扱うさまざまな関数が宣言されています。

主な文字列操作関数を整理すると、次のようになります。

関数名主な役割
strlen文字列の長さを調べる
strcpy文字列全体を別の配列へコピーする
strncpy指定した数の文字を別の配列へコピーする
strcmp2つの文字列を比較する
strcat文字列の末尾へ別の文字列を連結する
strchr文字列の中から指定した文字を探す
strstr文字列の中から指定した部分文字列を探す

今回は、この中から文字列の長さとコピーに関係するstrlen、strcpy、strncpyを詳しく見ていきます。

C言語の文字列はchar型の配列

C言語では、文字列をchar型の配列として表現します。

例えば、Codeという文字列を配列へ格納する場合は、次のように宣言できます。

char text[] = "Code";

配列の中には、次の5つの要素が格納されます。

配列要素格納される内容
text[0]C
text[1]o
text[2]d
text[3]e
text[4]\0

画面に表示される文字は4文字ですが、配列にはナル文字を含めた5文字分の領域が必要です。

文字列操作関数は、配列の先頭から文字を順番に確認し、ナル文字に到達した位置を文字列の終わりとして扱います。

ナル文字が必要な理由

char型の配列には、配列自体の要素数があります。しかし、文字列操作関数へ配列の先頭を渡しただけでは、その配列が何要素あるのかは直接伝わりません。

そのため、文字列の最後にナル文字を置き、文字列の終わりを示します。

例えば、次の配列にはナル文字が含まれています。

char text[] = {'C', 'A', 'T', '\0'};

この配列は、文字列CATとして扱えます。

一方、次の配列にはナル文字がありません。

char text[] = {'C', 'A', 'T'};

この配列を文字列操作関数へ渡すと、関数はどこで文字列が終わるのか判断できません。配列の範囲を越えてナル文字を探し続ける可能性があり、正しい動作は保証されません。

文字列操作関数へ渡すデータは、原則としてナル文字で正しく終わっている必要があります。

文字列操作関数を使うときの基本

文字列操作関数を利用するときは、次の点を確認しましょう。

確認する項目内容
ヘッダファイルstring.hをインクルードする
文字列の表現char型の配列として扱う
文字列の終端末尾にナル文字が必要
配列の大きさ文字列本体とナル文字が入る領域を用意する
関数の仕様ナル文字をコピーするかどうかを確認する
戻り値の型関数に合った型で受け取る

特にコピーを行う関数では、コピー元の文字列だけでなく、コピー先の配列サイズを確認する必要があります。

配列同士は代入できない

int型などの通常の変数では、代入演算子を使って値をコピーできます。

int first = 25;
int second;

second = first;

この代入によって、firstの値25がsecondへコピーされます。

しかし、配列同士を代入演算子でコピーすることはできません。

char source[10] = "ABC";
char destination[10];

destination = source;

destinationとsourceはどちらも配列であるため、この代入はコンパイルエラーになります。

文字列を別の配列へコピーしたい場合は、1文字ずつコピーする処理を書くか、strcpyやstrncpyなどの文字列操作関数を使います。

文字列操作関数が役立つ理由

文字列操作関数を使わずに文字列の長さを求める場合は、ナル文字に到達するまで1文字ずつ調べる必要があります。

size_t length = 0;

while (text[length] != '\0') {
    length++;
}

strlenを使えば、同じ目的を次のように表現できます。

size_t length = strlen(text);

文字列をコピーする場合も、自分で繰り返し処理を書く代わりにstrcpyなどを利用できます。

標準ライブラリ関数を使うことで、処理の目的が関数名から分かりやすくなり、プログラムも簡潔になります。

文字列の長さを調べるstrlen

strlenは、文字列の長さを調べる関数です。

strlenを使うにはstring.hをインクルードします。

#include <string.h>

strlenの関数宣言は次のとおりです。

size_t strlen(const char *s);

strlenは、引数sが指す文字列の先頭からナル文字の直前までを調べ、その長さを返します。

項目内容
関数名strlen
引数長さを調べる文字列の先頭
戻り値ナル文字を除いた文字列の長さ
戻り値の型size_t
必要なヘッダstring.h

strlenはナル文字を数えない

Helloという文字列は、配列の中で次のように格納されています。

'H'  'e'  'l'  'l'  'o'  '\0'

配列内では6要素を使っていますが、strlenが返す長さは5です。

char text[] = "Hello";
size_t length = strlen(text);

この場合、lengthには5が格納されます。

strlenは、文字列の終わりを探すためにナル文字を確認しますが、ナル文字自体は文字列の長さに含めません。

図1:strlenが文字列の長さを数える流れ

この図から分かること

strlenは、文字列の先頭から順番に文字を確認し、ナル文字が見つかる直前までの長さを数えます。

Sensorには6文字があるため、strlenが返す値は6です。配列にはナル文字を含めて7要素が使われていますが、ナル文字は長さに含まれません。

この違いから、配列の要素数と文字列の長さは同じとは限らないことが分かります。

配列の大きさと文字列の長さの違い

配列を大きめに用意しても、実際に格納されている文字列が短いことがあります。

char text[20] = "Hello";

この場合、配列全体の大きさは20バイトですが、文字列の長さは5です。

調べる内容結果
sizeof(text)20
strlen(text)5

sizeofは配列全体の大きさを調べます。strlenはナル文字までの文字列の長さを調べます。

この2つは目的が異なります。

  • sizeofは配列や型が使用するメモリの大きさを調べる
  • strlenは文字列の終端までの長さを調べる
  • sizeofの結果には未使用領域も含まれる
  • strlenの結果にはナル文字を含めない

strlenの引数にconstがある理由

strlenの引数はconst char型へのポインタです。

size_t strlen(const char *s);

constは、strlenが引数から受け取った文字列の内容を変更しないことを表します。

strlenは文字列の先頭からナル文字までを調べるだけであり、配列内の文字を書き換えません。

そのため、書き換え可能な文字配列だけでなく、文字列リテラルが表す文字列の長さも調べられます。

size_t length = strlen("Library");

この場合、lengthには7が格納されます。

strlenの戻り値がsize_t型である理由

strlenの戻り値はsize_t型です。

size_tは、配列の大きさ、オブジェクトの大きさ、文字列の長さなど、メモリ上の大きさを表すために使われる符号なし整数型です。

strlenが返す長さは負の値になりません。そのため、処理系が表現できる大きさを適切に扱えるsize_t型が使われています。

size_t length = strlen(text);

strlenの結果を表示するときは、size_t型に対応する%zuを使用します。

printf("文字列の長さは%zuです。\n", length);
項目内容
strlenの戻り値size_t型
printfの変換指定%zu
値の意味ナル文字を除いた長さ

strlenの戻り値をint型で受け取ると、大きな文字列を扱う環境で値を正しく表現できない可能性があります。戻り値の型に合わせてsize_tを使うことが基本です。

strlenは画面上の文字数とは限らない

strlenが返すのは、ナル文字までに使用されているバイト数です。必ずしも、人が画面上で数える文字数ではありません。

半角英数字を1バイトで表す一般的な環境では、ABCのstrlenの結果は3です。

一方、UTF-8で表現された日本語は、一般的に1文字が複数バイトになります。そのため、日本語文字列にstrlenを使うと、見た目の文字数より大きな値が返ることがあります。

文字列の種類strlenの考え方
半角英数字見た目の文字数と一致しやすい
UTF-8の日本語見た目の文字数と一致しないことがある
ナル文字長さに含まれない

strlenは文字数を数える関数というより、C言語の文字列がナル文字までに使用しているバイト数を調べる関数と理解すると正確です。

strlenで入力文字列の長さを調べるプログラム

fgetsで英単語を読み込み、末尾の改行文字を取り除いてからstrlenで長さを調べます。

入力した英単語の長さを表示するプログラム

ファイル名:12_5_1.c

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

int main(void)
{
    char keyword[100];

    printf("英単語を入力してください > ");

    /* 文字列を読み込む */
    if (fgets(keyword, sizeof(keyword), stdin) != NULL) {
        size_t length = strlen(keyword);

        /* 末尾の改行文字を取り除く */
        if (length > 0 && keyword[length - 1] == '\n') {
            keyword[length - 1] = '\0';
            length--;
        }

        printf("入力した英単語: %s\n", keyword);
        printf("文字列の長さ: %zu\n", length);
    } else {
        puts("文字列を読み取れませんでした。");
    }

    return 0;
}
実行結果の例

Networkと入力した場合の例です。

英単語を入力してください > Network
入力した英単語: Network
文字列の長さ: 7

入力した英単語の長さを表示するプログラムの解説

必要なヘッダをインクルードする部分

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

stdio.hはprintf、fgets、puts、stdinを使うために必要です。

string.hはstrlenを使うために必要です。

文字列を格納する配列

char keyword[100];

キーボードから入力した文字列を格納するため、100要素のchar型配列keywordを用意しています。

fgetsは最大99文字を読み込み、最後にナル文字を格納できます。

fgetsで文字列を読み込む部分

if (fgets(keyword, sizeof(keyword), stdin) != NULL) {

fgetsで標準入力から1行を読み込み、keywordへ格納します。

fgetsの戻り値がNULLではない場合は、読み込みに成功したと判断してif文の中を実行します。

strlenで長さを調べる部分

size_t length = strlen(keyword);

strlenでkeywordの先頭からナル文字までの長さを調べ、結果をsize_t型のlengthへ格納します。

fgetsがEnterまで読み取れた場合、keywordには改行文字が含まれています。この時点では、改行文字もstrlenの長さに含まれます。

改行文字を取り除く部分

if (length > 0 && keyword[length - 1] == '\n') {
    keyword[length - 1] = '\0';
    length--;
}

文字列の長さが1以上であり、最後の文字が改行文字である場合、その改行文字をナル文字へ置き換えます。

改行文字を取り除いたため、lengthも1減らします。

この処理によって、Enterによる改行を除いた長さを表示できます。

結果を表示する部分

printf("入力した英単語: %s\n", keyword);
printf("文字列の長さ: %zu\n", length);

%sで文字列を表示し、%zuでsize_t型の長さを表示しています。

Networkは半角英字7文字であるため、結果は7になります。

文字列全体をコピーするstrcpy

strcpyは、文字列全体を別の配列へコピーする関数です。

strcpyを使うにはstring.hをインクルードします。

#include <string.h>

strcpyの関数宣言は次のとおりです。

char *strcpy(char *restrict s1, const char *restrict s2);

第1引数s1はコピー先、第2引数s2はコピー元です。

項目内容
関数名strcpy
第1引数コピー先の配列
第2引数コピー元の文字列
コピー範囲コピー元の先頭からナル文字まで
戻り値コピー先の先頭
必要なヘッダstring.h

strcpyの基本的な使い方

文字列ABCを別の配列へコピーする場合は、次のように書きます。

char source[] = "ABC";
char destination[10];

strcpy(destination, source);

コピー後のdestinationには、次の内容が格納されます。

'A'  'B'  'C'  '\0'

strcpyは、表示される文字だけでなく、文字列の終わりを表すナル文字もコピーします。

そのため、コピー後のdestinationを正しい文字列として扱えます。

strcpyの戻り値

strcpyは、コピー先として指定した配列の先頭を返します。

char *result = strcpy(destination, source);

コピーに成功すると、resultはdestinationの先頭を指します。

簡単なプログラムでは戻り値を使用せず、次のように呼び出すことが多いでしょう。

strcpy(destination, source);

ただし、strcpyにはコピー先の配列サイズを確認する機能がありません。戻り値によってサイズ不足を検出することもできません。

コピー前に、プログラマーがコピー先の大きさを確認する必要があります。

図2:strcpyがナル文字までコピーする流れ

この図から分かること

strcpyは、コピー元の先頭からナル文字までをコピー先へ書き込みます。

Routeは5文字ですが、コピーされる要素はナル文字を含めた6要素です。そのため、コピー先には少なくとも6要素分の領域が必要です。

コピー先が文字数と同じ5要素しかない場合は、ナル文字を格納できません。文字列をコピーするときは、表示される文字だけでなく、最後のナル文字の領域も考える必要があります。

strcpyではコピー先の大きさが重要

strcpyは、コピー先の配列が何要素あるのかを確認しません。コピー元のナル文字までを、そのままコピー先へ書き込みます。

例えば、次のコピー先は小さすぎます。

char source[] = "Computer";
char destination[5];

strcpy(destination, source);

Computerは8文字あり、ナル文字を含めると9要素が必要です。しかし、destinationには5要素しかありません。

この状態でstrcpyを実行すると、destinationの範囲を越えて書き込むため、動作は保証されません。

必要な配列サイズは、次のように考えます。

コピー元の文字列長 + ナル文字の1要素

strlenを使うと、コピーに必要な最小サイズを次のように求められます。

strlen(source) + 1

コピー先に十分な大きさがあるか確認する例は次のとおりです。

if (sizeof(destination) >= strlen(source) + 1) {
    strcpy(destination, source);
}

この方法は、destinationが現在の場所で実体の分かる配列である場合に利用できます。

バッファオーバーフローとは

配列として用意した領域を越えてデータを書き込むことを、バッファオーバーフローといいます。

文字列コピーでは、コピー元より小さな配列へstrcpyでコピーすると、バッファオーバーフローが発生する可能性があります。

バッファオーバーフローによって、次のような問題が起こります。

  • 近くにある別の変数の値が壊れる
  • 表示結果が不正になる
  • プログラムが異常終了する
  • 実行するたびに異なる動作になる
  • セキュリティ上の問題につながる

C言語では、strcpyがコピー先のサイズを自動的に確認してくれるわけではありません。プログラマー自身が配列サイズを管理する必要があります。

strcpyを使う前の確認事項

strcpyを使う前に、次の点を確認しましょう。

  • コピー元がナル文字で正しく終わっているか
  • コピー元の文字列長を確認したか
  • コピー先に文字列本体が入るか
  • コピー先にナル文字の領域があるか
  • コピー先が書き換え可能な配列か
  • コピー先の大きさを超えないか

文字列の長さが分からないままstrcpyを使うのは危険です。コピー元の長さとコピー先の大きさを確認してから実行しましょう。

指定した数をコピーするstrncpy

strncpyは、コピーする文字数を指定できる文字列操作関数です。

strncpyを使うにはstring.hをインクルードします。

#include <string.h>

strncpyの関数宣言は次のとおりです。

char *strncpy(char *restrict s1,
              const char *restrict s2,
              size_t n);

strncpyは、第2引数s2から第1引数s1へ、nで指定した数の文字をコピーします。

項目内容
関数名strncpy
第1引数コピー先の配列
第2引数コピー元の文字列
第3引数コピーする要素数
戻り値コピー先の先頭
必要なヘッダstring.h

strncpyの基本的な使い方

Programmingの先頭から5文字分をコピーする場合は、次のように書けます。

char source[] = "Programming";
char destination[6];

strncpy(destination, source, 5);
destination[5] = '\0';

destinationには、次の文字列が格納されます。

'P'  'r'  'o'  'g'  'r'  '\0'

先頭5文字を格納するために5要素、ナル文字を格納するために1要素を使用しています。

strncpyは安全版strcpyとは限らない

strncpyはコピーする数を指定できるため、strcpyより安全な関数に見えるかもしれません。

しかし、strncpyには重要な注意点があります。

コピー元の長さがn以上の場合、コピー先へナル文字が自動的に付かないことがあります。

例えば、次の処理を考えます。

char source[] = "ABCDE";
char destination[5];

strncpy(destination, source, 4);

destinationの先頭4要素にはABCDがコピーされます。しかし、strncpyがコピーする範囲は4要素なので、コピー元のナル文字には到達しません。

'A'  'B'  'C'  'D'  ?

最後の要素にどのような値が入っているかは、この処理だけでは決まりません。

destinationを文字列として使うには、ナル文字を自分で格納します。

destination[4] = '\0';

これでdestinationはABCDという正しい文字列になります。

コピー元がnより短い場合

コピー元の文字列がnより短い場合、strncpyはコピー元のナル文字をコピーし、残りの範囲もナル文字で埋めます。

char source[] = "AB";
char destination[6];

strncpy(destination, source, 5);

コピー後の先頭5要素は次のようになります。

'A'  'B'  '\0'  '\0'  '\0'

strncpyは単純に最大n文字までコピーするというより、n要素分を次の規則で処理する関数です。

コピー元の状態strncpyの動作
コピー元の長さがn以上先頭からn要素をコピーし、ナル文字が付かないことがある
コピー元の長さがn未満ナル文字をコピーし、残りもナル文字で埋める

この違いを理解せずに使うと、コピー先が正しい文字列にならない場合があります。

図3:strncpyで一部をコピーするときの注意点

この図から分かること

strncpyでコピーする数を4に指定すると、コピー元の先頭から4要素だけがコピーされます。

コピー元ABCDEのナル文字は4要素の範囲より後ろにあるため、コピー先へは入りません。そのままではコピー先が正しい文字列として終端されていない可能性があります。

コピー先を文字列として使うには、配列内の適切な位置へナル文字を格納する必要があります。コピーする数だけでなく、文字列終端のための領域も確保しましょう。

strcpyとstrncpyの違い

strcpyとstrncpyはどちらも文字列をコピーしますが、コピー方法とナル文字の扱いが異なります。

比較項目strcpystrncpy
コピー範囲コピー元のナル文字までnで指定した範囲
ナル文字コピー元のナル文字をコピーするコピー元がn文字以上の場合は付かないことがある
コピー先サイズ関数内では確認しない関数内では確認しない
主な用途文字列全体をコピーする指定した要素数でコピーする
主な注意点コピー先の領域不足コピー先が終端されない可能性

strncpyもコピー先の実際の配列サイズを確認しません。第3引数へ大きすぎる値を指定すれば、strcpyと同じように配列の範囲を越えて書き込む可能性があります。

そのため、strncpyを単純な安全版strcpyと考えるのは適切ではありません。

strncpyで終端を確保する基本形

コピー先の最後にナル文字を確実に置く場合は、次のような形を使えます。

char destination[10];

strncpy(destination, source, sizeof(destination) - 1);
destination[sizeof(destination) - 1] = '\0';

この処理では、コピーする範囲をコピー先の大きさより1小さくしています。

最後の1要素は、ナル文字を格納するために残します。

配列の範囲用途
先頭から最後の1つ前sourceからコピーする領域
最後の1要素ナル文字を格納する領域

ただし、コピー元が長い場合は途中までしかコピーされません。文字列が切り詰められてもよい処理なのかを確認する必要があります。

strcpyとstrncpyを使うプログラム

次のプログラムでは、strcpyで文字列全体をコピーし、strncpyで先頭部分だけを別の配列へコピーします。

文字列全体と先頭部分を別の配列へコピーするプログラム

ファイル名:12_5_2.c

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

int main(void)
{
    char original[] = "Database";
    char full_copy[20];
    char part_copy[6];

    /* コピー先に十分な領域があるか確認する */
    if (sizeof(full_copy) >= strlen(original) + 1) {
        strcpy(full_copy, original);
        printf("全体コピー: %s\n", full_copy);
    } else {
        puts("全体コピー用の配列が不足しています。");
    }

    /* 配列の最後を空けて先頭5文字をコピーする */
    strncpy(part_copy, original, sizeof(part_copy) - 1);

    /* 末尾にナル文字を格納する */
    part_copy[sizeof(part_copy) - 1] = '\0';

    printf("一部コピー: %s\n", part_copy);

    return 0;
}
実行結果の例
全体コピー: Database
一部コピー: Datab

文字列をコピーするプログラムの解説

必要なヘッダをインクルードする部分

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

stdio.hはprintfとputsを使うために必要です。

string.hはstrlen、strcpy、strncpyを使うために必要です。

コピー元の文字列

char original[] = "Database";

コピー元となる文字列Databaseをchar型の配列originalへ格納しています。

Databaseは8文字なので、配列にはナル文字を含めた9要素が用意されます。

コピー先の配列

char full_copy[20];
char part_copy[6];

full_copyは文字列全体をコピーするための配列です。20要素あるため、Databaseとナル文字を十分に格納できます。

part_copyは、先頭5文字とナル文字を格納するための配列です。

配列要素数用途
full_copy20文字列全体をコピーする
part_copy6先頭5文字とナル文字を格納する

コピー先の大きさを確認する部分

if (sizeof(full_copy) >= strlen(original) + 1) {

sizeof(full_copy)でコピー先配列全体の大きさを調べています。

strlen(original)でコピー元の文字列長を調べ、ナル文字の領域として1を加えています。

コピー先の大きさが必要な大きさ以上であれば、strcpyを実行します。

strcpyで全体をコピーする部分

strcpy(full_copy, original);
printf("全体コピー: %s\n", full_copy);

strcpyによって、originalの先頭からナル文字までをfull_copyへコピーしています。

コピー後のfull_copyは、Databaseという正しい文字列として使えます。

strncpyで先頭部分をコピーする部分

strncpy(part_copy, original, sizeof(part_copy) - 1);

part_copyの大きさは6です。sizeof(part_copy)-1は5になるため、originalの先頭から5要素をコピーします。

Databaseの先頭5文字はDatabです。

このコピーではoriginalのナル文字まで到達しないため、strncpyによってpart_copyへナル文字は追加されません。

ナル文字を追加する部分

part_copy[sizeof(part_copy) - 1] = '\0';

part_copyの最後の要素へナル文字を格納しています。

part_copyの要素数は6なので、最後の添字は5です。先頭5要素にDatabを格納し、最後の要素にナル文字を格納します。

'D'  'a'  't'  'a'  'b'  '\0'

これによって、part_copyを安全に文字列として表示できます。

文字列コピーで意識したい計算

文字列をコピーするときは、次の関係を意識しましょう。

必要な配列サイズ = コピーする文字数 + ナル文字の1要素

例えば、文字列Codeをコピーするには、最低でも5要素が必要です。

格納する内容必要な要素数
C、o、d、e4
ナル文字1
合計5

先頭10文字だけをコピーする場合は、コピー先に最低11要素必要です。

表示される文字数だけで配列を用意すると、ナル文字を格納できません。文字列の終端に使う1要素を忘れないようにしましょう。

文字列操作関数を安全に使うための確認事項

strlen、strcpy、strncpyを使うときは、次の点を確認することが大切です。

確認事項理由
string.hをインクルードする関数の宣言をコンパイラへ知らせるため
文字列がナル文字で終わっているか確認する関数が文字列の終わりを判断するため
strlenの戻り値をsize_tで受け取る戻り値の型に合わせるため
size_tを%zuで表示する適切な変換指定を使うため
コピー元の長さを確認するコピーに必要な領域を知るため
コピー先の大きさを確認するバッファオーバーフローを防ぐため
ナル文字の1要素を確保する正しい文字列として終端するため
strncpy後の終端を確認するナル文字が付かない場合があるため

strlen、strcpy、strncpyから学べること

3つの関数を学ぶことで、C言語の文字列処理に必要な基本が見えてきます。

関数学べること
strlenナル文字までが文字列であり、ナル文字は長さに含まれない
strcpy文字列全体とナル文字をコピーする
strncpyコピーする範囲を指定できるが、終端を自分で確認する必要がある

これらの関数には、C言語の文字列を扱ううえで重要な考え方が詰まっています。

  • 文字列はchar型の配列で表現される
  • 文字列の終わりにはナル文字が必要である
  • 配列の大きさと文字列の長さは異なる
  • コピー先の領域はプログラマーが管理する
  • 関数によってナル文字の扱いが異なる
  • 戻り値の型に合った変数と表示形式を使う

文字列操作関数は便利ですが、関数を呼び出すだけで安全性が自動的に保証されるわけではありません。

特にstrcpyとstrncpyでは、コピー先に十分な領域があるか、コピー後の文字列がナル文字で終わっているかを確認することが大切です。

strlen、strcpy、strncpyの動きを理解すると、今後学ぶstrcmp、strcat、strchr、strstrなどの文字列操作関数も理解しやすくなります。