とある課題でstrlcpyの再現を行うことになり、cpy系のそれぞれの違いが頭に入りづらかったのでまとめておく。
なお挙動については保証しません。
まずは、とりあえずマニュアルを見よう。
ターミナルを開いて、manコマンドでstrcpyとすると、strcpyとstrncpyそれぞれの概要や定義が表示されるはずだ。
strlcpyに関しては、ここには表示されないので、man strlcpy
としてあげよう。
では、それぞれ実装していく。
strcpyの再現
strcpyは、二つの文字列を受け取って、それをもう片方にコピーする関数だ。
dstはdestination(目的地)の略、srcはsorce(コピー元)の意味で、srcからdstに文字をコピーしていく。英単語を覚えるとわかりやすい。コードの実装例は以下で、srcがnull文字になるまで、dstにコピーしていくだけだ。
char *my_strcpy(char * dst, const char * src)
{
int i;
i = 0;
while (src[i] != '\0')
{
dst[i] = src[i];
i++;
}
return (dst);
}
strncpyの再現
strncpyの再現は以下の通り。strncpyはstrcpyに引数が1つ追加される。size_t len
の部分だ。len回文、srcからdstに文字をコピーしていく。
char *my_strncpy(char * dst, const char * src, size_t len)
{
size_t i;
i = 0;
while (i < len && src[i])
{
dst[i] = src[i];
i++;
}
while (i < len)
dst[i++] = '\0';
return (dst);
}
この関数の注意点は、lenの長さがsrcの長さより短い場合、dstがnull止めされないので、最終的にnull止めされてない文字列になってしまうことがある。
strlcpyの再現
strlcpyは必ずnull止めを保証してくれる関数。ただし、帰り値はunsigned intなので注意。実装コードは以下。
srcからdstにdstsize-1文コピーしてくれる。マイナス1する理由は最後にnull文字を入れる為。
関数のプロトタイプは以下。(restrictはよくわかりません。)
//作成しようとされる文字列の長さを返す。つまり、dstからsrcにコピーされるので期待されるのはsrcの長さ。
//だから返されるのはsrcの長さ
size_t my_strlcpy(char * dst, const char * src, size_t dstsize)
{
size_t i = 0;
while (src[i])
i++;
if (dstsize == 0)
return (i);
size_t j = 0;
while (j < (dstsize - 1) && src[j] != '\0')
{
dst[j] = src[j++];
}
dst[j] = '\0';
return (i);
}
dstsizeにはnullを入れる為の余裕をとっておく必要がある。
srcからdstにうまくコピーされたら、srcの文字数分はいる。しかもヌル止めが保証されたままだ。
strlcpy(dst, array, sizeof(dst))
が一番使い勝手良さそう。
dstsizeが0だった時もsrcの長さ返すっぽい。
まとめ
strlcpyなら必ずnull止めしてくれるみたいなので、安心。dstsizeが0だった場合もsrcの長さ返してくれる。そこは注意して使う必要があるみたい。
結局manual読み込むのが一番。書いてないのは本家と比べて合うように作っていくしかないかな。