C言語でのfizzbuzz問題の回答を探していたら、以下のようなコードがありました。
#include <stdio.h>
int main(void){
int i;
for(i = 1 ; i <= 100 ; i++){
printf("%d \0Fizz \0FizzBuzz "+(i%5?(i%3?0:4):(i%3?14:10)),i);
}
printf("\n");
return 0;
}
(引用元:http://revilog.com/2010/08/c-fizzbuzz-printf.html)
このコードについての質問です。
printf("%d \0Fizz \0FizzBuzz "+(i%5?(i%3?0:4):(i%3?14:10)),i);
で、以下のことは理解しました。
・\0で区切って文字列の終わりを作っておく
・+演算子でポインタ演算を行なっている
・三項演算子でポインタ演算する量を決めている
・+演算子によって指定したポインタから\0までの文字列を出力する
・Buzzを出力する際は、「FizzBuzz」の途中の「Buzz」を出力している
わかっていないところは、
・特殊文字(\0など)や「%d」は何バイトとして計算するのか
・数字以外を出力する際、%dによって桁数がずれ、変なところから出力されてしまうのではないか(でも実際はならない)
です。
以上2点について回答よろしくお願いします。
No.3ベストアンサー
- 回答日時:
>普通に数えるとは、「\0」を1バイトとして数え、%dは代入後の数字で考えるということでよろしいでしょうか?
"\0"については、そうですが
"%d"の「代入後」ってどういう意味ですか?
例えば
printf("%d", 123);
とした場合、もしかしてprintf()に"123"という文字列が渡っていると思ってませんか?
この場合printf()に引数として渡ってるのは"%d"と123です。
>すみません。いまいちよくわかりません。詳しく解説していただけないでしょうか。
上で説明してるので省略。
もっと詳細を知りたければprintf()関数の実装例などを読んでみてください。
皆さん、たくさんの回答ありがとうございました。
すべての返信を書くのは大変なので、ここでまとめて返信させていただきます。
質問の件ですが、(多分)理解しました。
(1)メモリ上のどこかに"%d \0Fizz \0FizzBuzz "という文字列を作り、その先頭ポインタを
(2)+演算子でずらしてprintf関数に渡し、
(3)printf関数内で、渡されたポインタを起点として%dなどがあったら整形し標準出力に出力
の順序で処理が行われているということでしょうか。
"%d"はprintf関数に渡す前はただの文字列であり、printf関数の中で"%d"を第二引数のものに変えている。
そうすると、%で1バイト、dで1バイトの合計2バイトとしていつも数えられるから、常に+4とか+10としても問題ないというわけですね。納得しました。
ありがとうございます。
No.9
- 回答日時:
>#8さん
>#5 にしても #6 にしても, 「正確ではない」どころか「間違っている」と断ずるべきだと思います>#7.
どうも失礼いたしました。
断じてください。
No.8
- 回答日時:
#5 にしても #6 にしても, 「正確ではない」どころか「間違っている」と断ずるべきだと思います>#7.
特に #5 の「回答」では, 質問者自身が「わかっていない」としている
・数字以外を出力する際、%dによって桁数がずれ、変なところから出力されてしまうのではないか(でも実際はならない)
に対し余計に混乱させてしまうだけです. #6 にしても, あたかも「printf に渡す前に %d を書き換えている」かのような印象を与えてしまいます (これが間違いであることは #1/#3 で既に指摘されている通り).
#1 および #3 の繰り返しになりますが,
printf("%d", 123)
という関数呼び出しにおいて printf に渡される引数は "%d" と 123 の 2つです. そして, 書式文字列にある変換指示 %d に対し「引数として渡されている (はずの) int の値」を出力するのは printf の仕事です. だから,
「数字以外を出力する際、%dによって桁数がずれ、変なところから出力されてしまう」
などということは起こりえません.
No.7
- 回答日時:
A No.6
それも正確ではないですね。
まず、"%d \0Fizz \0FizzBuzz "はこれらの文字列が格納された領域のポインタとして扱われます。
そこに、+(i%5?(i%3?0:4):(i%3?14:10))という式でポインタ操作を行っているので、iの値によってprintfに渡されるポインタの値自体が異なることになります。
printfに渡されたポインタが指す文字列に"%d"が含まれなければ、printfは引数の2番目に渡されたiを無視して処理します。
No.6
- 回答日時:
先ほどの私の回答は、いささか正確さを欠いていましたね。
>printf("%d \0Fizz \0FizzBuzz "+(i%5?(i%3?0:4):(i%3?14:10)),i);
printf()の第1引数は、あくまで
"%d \0Fizz \0FizzBuzz "+(i%5?(i%3?0:4):(i%3?14:10))
ですね。で、第1引数の一部を構成している
"%d \0Fizz \0FizzBuzz "
ここに、
"1 \0Fizz \0FizzBuzz "
"2 \0Fizz \0FizzBuzz "
"3 \0Fizz \0FizzBuzz "
...
"98 \0Fizz \0FizzBuzz "
"99 \0Fizz \0FizzBuzz "
"100 \0Fizz \0FizzBuzz "
が順に入っていく、ということでありましょう。
No.5
- 回答日時:
>printf("%d \0Fizz \0FizzBuzz "+(i%5?(i%3?0:4):(i%3?14:10)),i);
printf()の第1引数には、
"1 \0Fizz \0FizzBuzz "
"2 \0Fizz \0FizzBuzz "
"3 \0Fizz \0FizzBuzz "
...
"98 \0Fizz \0FizzBuzz "
"99 \0Fizz \0FizzBuzz "
"100 \0Fizz \0FizzBuzz "
が、順に渡ります。
で、これらを、「実際にどう出力するか」を、
>+(i%5?(i%3?0:4):(i%3?14:10))
ここでコントロールしています。
No.4
- 回答日時:
#include <stdio.h>
int main(void){
printf("%c\n", "%d \0Fizz \0FizzBuzz "[0]);
return 0;
}
とか試せば、n文字目が何かは分かる。
> %dは代入後の数字で考えるということでよろしいでしょうか?
%dはただの文字列です。
putsに渡してみれば理解できますか?
#include <stdio.h>
int main(void){
int i;
char *format;
for(i = 1 ; i <= 100 ; i++){
format = "%d \0Fizz \0FizzBuzz "+(i%5?(i%3?0:4):(i%3?14:10));
puts(format);
//printf(format,i);
//printf("\n");
}
return 0;
}
No.1
- 回答日時:
>・特殊文字(\0など)や「%d」は何バイトとして計算するのか
特殊文字でもなんでもないのでふつうに数えてください。
>・数字以外を出力する際、%dによって桁数がずれ、変なところから出力されてしまうのではないか(でも実際はならない)
"%d"などの書式を解釈するのはprintf()系の関数です。
Cコンパイラが解釈するわけではありません。
この回答への補足
>特殊文字でもなんでもないのでふつうに数えてください。
普通に数えるとは、「\0」を1バイトとして数え、%dは代入後の数字で考えるということでよろしいでしょうか?
>"%d"などの書式を解釈するのはprintf()系の関数です。
>Cコンパイラが解釈するわけではありません。
すみません。いまいちよくわかりません。詳しく解説していただけないでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
勝率をプログラムに
-
cshの文字列操作(0埋め)
-
コンパイルエラーについて
-
switch分のケースを範囲数?に...
-
4の倍数を論理演算で表す。。
-
printfの出力内の文字をdefine...
-
三角形の判別
-
正の実数Aを求めよまた、関数...
-
インクリメント、デクリメント。
-
10個出力で改行したいのですが...
-
C言語でマウス入力(クリックや...
-
教えてください!!
-
ビットを操作する。
-
円の面積を求めるプログラミン...
-
%P と %X の違い
-
C言語のソースをC++言語に変換...
-
C言語習いはじめです
-
3つの整数が等しいかどうか調...
-
間違いを指摘して頂けませんか...
-
筆算(加法)について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コンパイルエラーについて
-
printf で二進表示を行いたい。
-
c言語でAからZまでを表示する...
-
テキストカーソル位置の取得
-
4の倍数を論理演算で表す。。
-
cshの文字列操作(0埋め)
-
【C言語教えてください】sin波...
-
10個出力で改行したいのですが...
-
wsprintfの書式制御文字列につ...
-
error C2143: 構文エラー : ';'...
-
printfの出力内の文字をdefine...
-
%P と %X の違い
-
C言語
-
strcmp
-
(C言語)めちゃくちゃな値にな...
-
コマンドラインに出力した文字...
-
スレッドとメッセージキューに...
-
printf( " %2d", p * q );
-
Visual Sutdio 2017 でのC言語...
-
defineで定数が置き換えられな...
おすすめ情報