- ベストアンサー
sprintf()の使用方法
先日から仕事で別の人が作ったソースを見ることになりました。 文字列連結を繰り返す処理でこんなコードが書いてありました。 char str[4096]; for(;;) { /* 具体的な条件などは忘れました */ sprintf(str, "%s%s", str, var1); /* 一応、var1はstrに対して十分小さな文字列。*/ /* 繰り返しが終了するまで溢れることはないのですが */ } strcatなどを知らない人が作ったのでしょう。 一応、目的は達しているし、動いているみたいだからいいと言えばいいのかもしれないですが、なんか気持ち悪い。 こういうコードで何か問題はないのでしょうか?
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
strcatと比べて特に問題は無いと思います。ただ、sprintfの方が複雑な関数なので処理時間は掛かりますが、何万回も実行されるので無い限りあまり違いは無いでしょう。 strcatにしてもsprintfにしても、事前にstrlenを使って長さがstrを超えることが無いことを確認すべきことは確かですが、間接的な手段で超えないことが証明できるなら直接的なチェックは略しても良いと思います。strlcatを使ってチェックを兼用する手もあります。
その他の回答 (5)
- JF1Msf
- ベストアンサー率20% (18/88)
strcatを知らなくて、sprintfを知っているというのは非常に考えにくいので、例えばNo.4,5の回答のように、何か意図があるように思われます。どのようなcontextで、なぜsprintfを使っているかを、もうちょっと考えてみたら、「気持ち悪い」状態から、無性に「気持ちいい」状態になるかもしれませんよ。
お礼
ありがとうございました。
- toysmith
- ベストアンサー率37% (570/1525)
このコードがどのような状況で使用されるか不明ですが… よく使うパターンで言えば do { sprintf(path, "%s/%s", path, filename) ; } while (filenameがディレクトリであるという判定) ; とかですね。 C89以降に準拠したsprintf()ならほぼ動作すると思われます。 C89以前のsprintf()の場合、第1引数のバッファを直接書き換えているモノがあり、その場合最初にバッファクリアしている可能性があります。 あと、気になる点では… /* 繰り返しが終了するまで溢れることはないのですが */の保証は一般的に不可能です。 sprintfが作成するstrは環境依存です。 プログラムは単位(たとえば1文字)が何バイトになるかすら想定できません。 (私が知っている文字コードセットでは1文字最大8オクテットというのがあります) C99であればsnprintf()を使うべきですね。
お礼
ありがとうございました。
- Tacosan
- ベストアンサー率23% (3656/15482)
この程度であれば strcpy + strcat の方が自然に感じますが, もっと複雑に連結しようとするとかえって sprintf の方がわかりやすくなることがあります. たとえばディレクトリ名, パス区切, ファイル名からフルパスを作ることを考えると sprintf(fullpath, "%s%c%s", directory, path_delimiter, filename); の方が str... を駆使するより見易いと思います.
お礼
ありがとうございました。
- Tsukasa0215
- ベストアンサー率22% (280/1257)
確かに目的は達成していますね。これでも問題は無いですが、アセンブラに落ちた場合、strcatの方が処理的に早そうだし…。 /* sprintf(str, "%s%s", str, var1); */ strcat(str,var1); と書き換えておけばどうですか?
お礼
ありがとうございました。
- khurata
- ベストアンサー率40% (54/134)
「var1はstrに対して十分小さな文字列」「繰り返しが終了するまで溢れることはない」という条件であれば、目的通りの動作はするコードだと思います。 ただ、おっしゃる通り、strを sprintfの中でこのように使うのは、めずらしい使い方かも知れません。文字列連結が目的なら strcatの方が適切でしょうし、フォーマット処理をしない分、高速だと思います。
お礼
ありがとうございました。
お礼
ありがとうございました。