文字列の結合
文字列操作3
文字列の末尾に別の文字列を結合するにはstrcat
関数、strncat
関数、またはstrcat_s
関数、strncat_s
関数を使用します。
strcat_s
関数、strncat_s
関数はコンパイラによっては使用できません。
strcat
関数、strncat
関数はVisualStudio既定の設定では使用するとエラーとなります。
詳しくは_s系関数とエラー表示についてを参照してください。
strcat関数、strncat関数
#include <stdio.h>
#include <string.h>
int main()
{
char strDest1[32] = "ABC"; //結合先1
char strDest2[32] = "ABC"; //結合先2
const char strSource[] = "DEF"; //結合元
strcat(strDest1, strSource);
strncat(strDest2, strSource, sizeof(strSource));
printf("%s\n", strDest1);
printf("%s\n", strDest2);
getchar();
}
ABCDEF ABCDEF
-
char *strcat(
char *strDestination,
const char *strSource
); -
文字列strDestinationの末尾に文字列strSourceを結合する。
戻り値は文字列strDestination。
-
char *strncat(
char *strDest,
const char *strSource
size_t count
); -
文字列strDestinationの末尾に文字列strSourceをcount文字分結合する。
終端がNULL文字でない場合はNULL文字に置き換える。
戻り値は文字列strDestination。
これらの関数はいずれも結合される文字列の末尾のNULL文字から文字列の結合が開始されます。
つまり文字列strDestination
の末尾のNULL文字は文字列strSource
の一文字目に置き換えられ、文字列と文字列の間にNULL文字が入ることはありません。
strcpy関数の時と同様、strcat
関数は配列サイズのチェック機能がないため、結合先配列のサイズが足りないとバッファオーバーランが発生します。
strncat
関数は第三引数count
で結合する文字数を制限できます。
結合する文字列の文字数がcount
よりも大きい場合、文字列の切り捨てが発生するわけですが、このとき文字列の末尾にNULL文字が付加されます。
そのため、結合先配列の空き容量ギリギリの値をcount
に指定するとバッファオーバーランが発生してしまいます。
(NULL文字がはみ出る)
なので、count
に指定できる値は最大で「空き容量-1」となります。
char strDest[6] = "ABC";
const char strSource[] = "DEF";
//strDest[6]の位置をNULL文字に置き換えてしまう
//(バッファオーバーラン)
//strncat(strDest, strSource, sizeof(strDest) - strlen(strDest));
//strDest[5]の位置がNULL文字になる
strncat(strDest, strSource, sizeof(strDest) - strlen(strDest) - 1);
printf("%s\n", strDest);
ABCDE
strcat_s関数、strncat_s関数
#include <stdio.h>
#include <string.h>
int main()
{
char strDest1[32] = "ABC"; //結合先1
char strDest2[32] = "ABC"; //結合先2
const char strSource[] = "DEF"; //結合元
strcat_s(strDest1, sizeof(strDest1), strSource);
strncat_s(strDest2, sizeof(strDest2), strSource, sizeof(strSource));
printf("%s\n", strDest1);
printf("%s\n", strDest2);
getchar();
getchar();
}
ABCDEF ABCDEF
-
errno_t strcat_s(
char *strDestination,
size_t numberOfElements,
const char *strSource
); -
サイズnumberOfElementsの文字列strDestinationの末尾に文字列strSourceを結合する。
正常終了すると0を、エラーの場合は0以外を返す。
-
errno_t strncat_s(
char *strDest,
size_t numberOfElements,
const char *strSource
size_t count
); -
サイズnumberOfElementsの文字列strDestの末尾に文字列strSourceをcount文字分結合する。
正常終了すると0を、エラーの場合は0以外を返す。
strcat_s
関数の第二引数numberOfElements
はstrncat
関数の第三引数count
とは意味が異なります。
strncat
関数のcount
は結合される文字列のサイズ指定ですが、strcat_s
関数のnumberOfElements
は「結合される文字列+結合する文字列+NULL文字」の総サイズを指定します。
要するに第一引数strDest
の(空き容量も含めた)配列サイズを指定します。
このサイズ指定よりも実際に生成される文字列のサイズの方が大きいとプログラムが停止します。
strncat_s
関数は第四引数count
で結合する文字列のサイズを制限することができます。
配列の空容量-1を指定すれば安全に結合が可能です。
#include <stdio.h>
#include <string.h>
int main()
{
char strDest1[8] = "ABCDE";
char strDest2[32] = "ABCDE";
const char strSource[] = "FGHIJ";
strncat_s(strDest1, sizeof(strDest1), strSource, sizeof(strDest1) - strlen(strDest1) - 1);
strncat_s(strDest2, sizeof(strDest2), strSource, sizeof(strDest2) - strlen(strDest2) - 1);
printf("%s\n", strDest1);
printf("%s\n", strDest2);
getchar();
}
ABCDEFG ABCDEFGHIJ
第四引数に_TRUNCATE
マクロを指定しても同じ動作となります。
strncat_s(strDest, sizeof(strDest), strSource, sizeof(strDest) - strlen(strDest) - 1);
//↑↓同じ意味
strncat_s(strDest, sizeof(strDest), strSource, _TRUNCATE);