2012-04-24 23 views
-1

内部が私は出力がMy name is Tomことを期待し、この書式指定子 - %sの%sの

char string[]="My name is %s"; 

printf("%s",string,"Tom"); 

のようなものを持っているが、私は%文字をエスケープしようとしたMy name is %s

を取得していますが、それdint work。

ここで何が問題になりますか? %s内にはどのように%sがありますか?

+2

printfのはわずか%を解釈します。 – nos

答えて

7

あなたの方法に問題がこれである。この

printf(string,"Tom"); 

のようなものを試してみてください - とすぐprintfがあなたのフォーマット文字列で%s書式指定子を見て、それはリストの次の引数がAであることを前提として

文字ポインタが指す文字列を取り出し、%sの代わりにそれを取り出して出力します。今度はprintfの再帰的なの置き換えを行わないので、stringの中には %sが残っており、 "Tom"は今や特別な引数になりました。

1

printf(string, "Tom")多分?

1

printfの最初のパラメータは、フォーマット文字列です。残りはすべて、フォーマット文字列に従ってフォーマットされるすべてのパラメータです。書式文字列は決して入れ子になりません。言い換えると、フォーマットされる文字列に書式設定命令が含まれていても、それは単純に印刷され、別の書式文字列として解釈されません。

あなたは間接のフォーマットのようなものを持っているしたい場合は、まず新しいフォーマット文字列を生成しなければならない(sprintfはそのために便利です):

char string[] = "My name is %s"; 
char format[100]; 

sprintf(format, "%s", string); 

してから使用して新たに生成したフォーマット文字列:

あなたが使用する必要があります
printf(format, "Tom"); 
1

問題がprintf("%s",string,"Tom"); ラインである

char string[]="My name is %s"; 
printf(string,"Tom"); 
ここ

あなたは

My name is Tom 
3

として出力を取得する唯一の拡大がprintf中にあります。つまり、書式文字列を除いて、printfに渡された文字列はすべてそのままの形で印刷されます。それは実際には良いことです。なぜならそうでなければ、それは巨大なセキュリティホールを残すからです。

セキュリティリスクは、フォーマット文字列とパラメータリストが一致しなければならないという事実に関連しています。不要な%は、フォーマット文字列にそれを行った場合ということは、あなたがトラブルに巻き込まれるだろう:

char ch[50]; 
fgets(ch, 50, stdin); 
printf(ch); 

ユーザー用品などの場合。%p %p %p %p、彼は%s %s %sを供給すれば、スタックに格納されたデータ(返信アドレスなど)を読み込み、プログラムをクラッシュさせる可能性があります。彼が%nを提供した場合、彼はスタック上のいくつかのデータを上書きするでしょう。

前記したい場合は、あなただけのフォーマット文字列を計算することができます:それは最初の引数、フォーマット文字列です内

char ch[50]; 
char format_prototype[]="My name is %s"; 
snprintf(ch, 49, "%s", format_prototype); 
ch[49]=0; 
printf(ch, "Tom"); 
+0

+1のセキュリティ面を議論する –

関連する問題