文字列連結 関数 strcat

strcat は、string.hをインクルードすれば、利用できます。
しかし正しく利用するには、その関数がどのように作られたものかを理解する必要があります。 以下では、この関数の定義例と利用例を紹介します。

char a[10] = "abc";
strcat( a, "12345");
puts( a );
        実行結果⇒ abc12345    

上記のでstrcatは、配列aに記憶される"abc"の後ろに、 "12345"に結合して、 配列aの記憶内容を"abc12345"の文字列へ変更しています。
関数内部では、第1引数の文字列最後の位置へ、第2引数の文字列をコピーしています。

strlenと、strcpyを利用したstrcat定義例

s1の文字列最後の位置は、s1+=strlen(s1); で求められます。その位置にコピーすればよいので、次のような定義が可能です。 なお、戻り値は第1引数と同じです。

#include <stdio.h>
#include <string.h>
char * strcat(char *s1, char *s2)
{
	char * startp = s1;
	s1 += strlen(s1); //ポインタを、s1の文字列の終端である'\0'が記憶される位置へ変更 */
	strcpy(s1, s2);	//それに、s2の文字列をコピー
	return startp;
}
main()
{
	char a[10] = "abc"; 
	char * p = strcat( a, "12345"); 
	puts( p );  /* puts( a ); でも同じ */
}

その実行例を以下に示します。

abc12345

引数のポインタ変数を変更するstrcat関数定義例

ここでは、添え字用変数を使かわずに、ポインタ引数の変数を変更することで、 コピーする位置を探し、次の文字コピーの繰り返しでも コピー先、コピー元の対象を変更しています。

#include <stdio.h>
#include <string.h>
char * strcat(char *s1, char *s2)
{
	char * startp = s1;
	while( s1 != '\0') {/* コピー先文字列の最後に移動する。*/
		s1++;
	}
	while( ( *s1 = *s2 ) != '\0'){/* コピーする。*/
		s1++;
		s2++;
	}
	return startp;
}
main()
{
	char a[10] = "abc"; 
	char * p = strcat( a, "12345"); 
	puts( p );  /* puts( a ); でも同じ */
}

なおこの例において、aの配列要素は10個です。その中の3文字は記憶済みから始まっています。 残りリが7個ですが、文字列終端の'\0'を記憶することを考慮すると、残りは6個です。 よって、この場合6文字を超える文字列(例えば"1234567")を、 strcatの第2引数で指定すると、正しい実行が得られなくなります。 つまり、それは配列の範囲を超えたアクセスになるからです。
この関数も、関数定義例からもわかるように、 コピー元の文字列が記憶可能範囲を超えるサイズであっても、コピーしようとします。
つまり、 利用する方で正しく使わなければならない関数といえます。

引数のポインタ変数を変更しないstrcat定義例

上記strcatと同じ機能を行なわせる別の定義例を、以下に示します。
■■■■ の記述を正しく直して完成くだささい。
(なお、*のポインタ演算子を使わずに、[]の配列演算子を使ってください。つまり、添え字で位置を指定する形態です。 なお添え字変更は、後置インクリメントを使ってください)

←編集 入力後に クリックください。