- 締切済み
10進数の2進数文字列変換
10進数の2進数文字列変換 ◆開発環境 OS:Linux(Ubuntu9.10) コンパイラ:gcc4.4 言語:C ◆質問内容 ポインタ*Aに格納されている10進数を2進数の文字列に変換し、 文字配列Bに格納したい。 バッファとして*fpを準備。 webで調査した結果を以下のソースのようにアレンジしましたが、 fputc関数の処理で、プログラムが強制終了してしまいます。 何か、良い方法ございませんでしょうか。 ◆サンプルソース void Dec_conv_bit(long *A,char *B){ unsigned int bit,n; //ビット比較用 unsigned int *fp = &n; n = (unsigned int)A; for(bit = 1 << sizeof(int)*8-1; bit > 0; bit >>= 1){ fputc((n & bit)?'1':'0',fp); } sprintf(B,"%s",fp); //putchar('\n'); }
- みんなの回答 (10)
- 専門家の回答
みんなの回答
- Tacosan
- ベストアンサー率23% (3656/15482)
いや, 「ビット『列』の逆転」を勝手に「ビットの逆転」と勘違いしただけではないかと>#9. まあ, どんな値で試したのかには, 私も興味がありますが.
- D-Matsu
- ベストアンサー率45% (1080/2394)
> ’1’:’0’ → ’0’:’1’ 外れ。 三項演算子・ビット演算・Cにおける真偽値あたりも理解できてなさそうな感じですね。 というかどんな値で試したんですか?
- LongSecret
- ベストアンサー率68% (22/32)
ん?まてよ 宣言を途中に書けない規格だったらまずいですね。 その場合一行にこだわるとこういうことになりましたか int i=32; for ( ; i--; A>>=1 ) B[i]=(A&1)+'0'; …微妙w あと手癖で書いてしまいましたが、int i(32);の表記はたしかC++からでしたね すみません その辺直せばC90あたりでも大丈夫だったかな?
- LongSecret
- ベストアンサー率68% (22/32)
// #6 char c[33]; c[32]=0; → char a[33]; a[32]=0;
- LongSecret
- ベストアンサー率68% (22/32)
面白そうなので私も考えてみました。 もしポインタでなくてもいいならこう書くことも可能です。 void Dec_conv_bit(long A, char *B){ for (int i=32 ; i--; A>>=1 ) B[i]=(A&1)+'0'; } ザ、無意味に一行コーディング♪ B[i]→ B[31-i]にしてみると…(略 おそらくアセンブリレベルで得してる要因があるため n2201makitaさんのコードの方が私のPCでは若干速いです。 速度を求めたいなら、小さい数字だった場合途中以降手抜き出来る機能があってもいいですね void Dec_conv_bit(long A, char *B){ int i(32); for ( ; A; A>>=1 ) { B[--i]=(A&1)+'0'; if (!i) return; } memset(B,'0',i); } 今度は保証付きでmemsetが日の目を見られるかな。 実はどっか未定義動作になってたらどなたか指摘してください(笑) 限界まで大きい数字だとif(!i) というのが逆に無意味になりますがw 改良はできると思いますw D-Matsuさんやn2201makitaさんのように、質問内容の表記に忠実に、ポインタを使用しつつ 手抜き機能を組み合わせるということも可能でしょう。 その辺はお好きなようにカスタマイズしてください。 >バッファとして*fpを準備。 ポインタとしてバッファを用意するということは char* fp=(char*)malloc(サイズ); しといて後で free(fp); みたいな感じの意味にとれる文ですが これだけ単純な場合はn2201makitaさんのように普通の配列で良いと思いますし、むしろそっちのがいいと思います。 もし32桁全部表示じゃなくて、それより上は全部0になる場合は表示しない (例: 15→1111 )とかだったら、返り値替えてもち~と面白くすることも出来ます。 #include <stdio.h> char * Dec_conv_bit(long A, char *B){ if (!A) return "0"; int i(32); for ( ; A; A>>=1 ) { B[--i]=(A&1)+'0'; if (!i) return B; } return B+i; } int main(){ char c[33]; c[32]=0; const char *p=Dec_conv_bit(0xe3e3e3f1, a); puts(p); Sleep(3000); }
- n2201makita
- ベストアンサー率30% (8/26)
// #2 #include <stdio.h> void Dec_conv_bit(long *A, char *B){ ○○int i; ○○unsigned bit = 0x80000000; ○○for(i=0; i<32; i++){ ○○○○B[i] = (*A & bit) ? '1' : '0'; ○○○○bit >>= 1; ○○} } int main(){ ○○char a[32+1] = {0}; ○○long b = 0xe3e3e3f1; ○○Dec_conv_bit(&b, a); ○○puts("21098765432109876543210987654321"); ○○puts(a); }
- D-Matsu
- ベストアンサー率45% (1080/2394)
あー、#2そのままだとビット列が逆転しますね。 まぁそこは修正しないでおきます。理解できれば直すのは簡単ですから。
お礼
回答ありがとうございました。 ビットの逆転、理解しました。 ’1’:’0’ → ’0’:’1’ であってますよね?(’0’:’1’にしたら希望通りのビット配列になりました)
- Tacosan
- ベストアンサー率23% (3656/15482)
うう~ん....「普通」と思える行が 1つもない.... なんでこんな謎を作れてしまうんだろう!? #1 の通りなんだけど, それとは別にアドバイス: このプログラムをコンパイルするときに警告は出ませんでしたか? 絶対に出てると思うんだけど, もし万が一にでも出てなかったらこれからはコンパイルするときに「全ての警告を報告する」オプション (gcc なら -Wall) を必ず付けてください. そして, 1つでも警告が出たら「警告はエラーの根本原因」あるいは「親の敵」とばかりにつぶしていってください. なお, 「型が合わない」という警告に対して「キャストする」というのは (どうにもならないこともあるけど) 邪道です. 変数の型を直すとかロジックを見直すかしてください. 「警告が全く出なくなって, ようやく意味のあるプログラムができるんだ」くらいに思うといいかもしれません.
- D-Matsu
- ベストアンサー率45% (1080/2394)
「型」に対する理解が根本的に足りていないか間違っています。 そもそも目的を達成するにはこれで充分のはず。 int bit; for(bit = 0; bit < sizeof(long) * 8; bit ++) { B[bit] = ((*A) & (1 << bit)) & '1' : '0'; } 「どこかで見つけたソースを理解もしようとせずにつぎはぎ」するからそのような変なコードになるんです。 ちゃんと理解して使いましょう。
fpって整数型なのにファイルポインタとしてfputcで使ってるからおかしいんじゃないですか? sprintfの使い方も何か変だし。 全然おかしいですよ。ちゃんと処理内容考えて下さい。
補足
三項演算子 -> ?’真(1)’:’偽(0)’ ですね。 よくわかってませんでした。 試した値は'204'です。 いろいろ考えているのですが、どうも「ビット列の逆転」が実現できません。(いま、’102’という値で検討中) 甘えついでに、何かヒントをご教授いただけませんか?