【C言語】
文字列連結にはsprintfを使え!
strcpy,strcatは使わない

strcpy+ strcat👇 sprintf

■sprintfで文字列連結すると見やすい

#include <stdio.h>
//sprintfで簡単に書く
void Sprintf(char *output,char *s1,char *s2){
    sprintf(output,"/%s/%s/%s:%s",
        s1,s2,__FILE__,__func__);
}
int main(void){
    char    string[1024];
    Sprintf(string,"root","home");
    puts(string);
}

編集後のイメージがわかりやすいです。

➡実行結果

./a.out
/root/home/f2.c:Sprintf

strcpy+strcatをダラダラ書くと見にくい

#include <stdio.h>
#include <string.h>
//strcpy+strcatをダラダラ書く
void strcpy_cat(char *output,char *s1,char *s2){
    strcpy(output,"/");
    strcat(output,s1);
    strcat(output,"/");
    strcat(output,s2);
    strcat(output,"/");
    strcat(output,__FILE__);
    strcat(output,":");
    strcat(output,__func__);
}
int main(void){
    char    string[1024];
    strcpy_cat(string,"root","home");
    puts(string);
}

編集後のイメージがわかりにくいです。


■sprintfは入力出力引数を同じにしてはいけない

#include <stdio.h>
int main(void){
    char    dst[16] = "abcd";
    char    src[16] = "1234";

    sprintf(dst,"/%s/%s/",src,dst);
    puts(dst);
}

dstが入力と出力の引数に使われているので
未定義の動作(バグ)となります。

参考:

軽率にも次のようなコードを使っているプログラムがある。

■sprintfの出力バッファは充分大きくする

#include <stdio.h>
int main(void){
    char    dst[32] ;
    char *src = 
    "Jugemu Jugemu," 
    "Gokō no Surikire," 
    "Kaijarisuigyo no Suigyōmatsu," 
    "Ungyōmatsu," 
    "Fūraimatsu," 
    "Kuunerutokoro ni Sumutokoro," 
    "Yaburakōji no Burakōji," 
    "Paipo Paipo," 
    "Paipo no Shūringan," 
    "Shūringan no Gūrindai," 
    "Gūrindai no Ponpokopī no Ponpokona no Chōkyūmei,"
    "Chōkyūmei no Chōsuke";

    sprintf(dst,"%s\n",src);
    puts(dst);
}

出力バッファは充分に大きくとりましょう。
このコードでは
領域破壊で異常終了するかもしれません。


■sNprintfが安全とは限らない

#include <stdio.h>
int main(void){
    char    dst[32] ;
    char *src = 
    "Jugemu Jugemu," 
    "Gokō no Surikire," 
    "Kaijarisuigyo no Suigyōmatsu," 
    "Ungyōmatsu," 
    "Fūraimatsu," 
    "Kuunerutokoro ni Sumutokoro," 
    "Yaburakōji no Burakōji," 
    "Paipo Paipo," 
    "Paipo no Shūringan," 
    "Shūringan no Gūrindai," 
    "Gūrindai no Ponpokopī no Ponpokona no Chōkyūmei,"
    "Chōkyūmei no Chōsuke";

    snprintf(dst,sizeof(dst),"%s",src);
    puts(dst);
}

➡実行結果

./a.out
Jugemu Jugemu,Gokō no Surikire

寿限無落語が途中で終わってしまいました。
お客に怒られないでしょうか?

意味のある文字列を
途中でぶった切っても良い状況って
筆者には余り思いつきません。

例えば
”やっぱり買うのを止めた”を途中で切ると
”やっぱり買う”になり
意味が反対になってしまいます。

それでもsnprintfは安全でしょうか?