プロが教えるわが家の防犯対策術!

初歩的なC言語に関する質問です。
テストに出た問題なのですが、解答が開示されず悩んでいます。
以下問題です。

printf,scanf,if,switch,do,while,for
を用いて10進数を2進数に変換するプログラムを作ります。
(ビット変換などは範囲外です。)

整数の範囲で行います。
使わないものがあっても構いませんが、for文のみは必ず使わなくてはなりません。

よろしくおねがいします。

質問者からの補足コメント

  • 整数値をscanfで取り込みそれを10進数と見なし2進数に変換してprintfで表示させたいです。値はint型ですべて扱います。

    質問文「ビット~~」の一文は無視してください。授業中の発言をうろ覚えで書いたため誤りがあります。
    int b[100];
    のような鍵かっこを用いてはならないという意味のようですが、コレにも誤りがございましたら、無視してください。

    不足、誤りがあり申し訳ありません。よろしくおねがいします。

      補足日時:2016/11/17 14:47
  • 修正です。
    すべての整数ではなく正の整数と0でお願いします。

      補足日時:2016/11/17 16:46
  • 何度も補足すみません
    stdio.hのみinclude可能です。
    配列は用いては行けません。
    intのみ(%dのみ)です。
    各方への返事は後程行います。よろしくおねがいします。

      補足日時:2016/11/18 14:58

A 回答 (14件中1~10件)

i*2 がオーバーフローする可能性がありますな>#13. n/2/i なら問題ないんだけどねぇ.



あるいは もっと処理すると
n/(i*2) > 0 ⇔ n/(i*2) ≧ 1 ⇔ n/2 ≧ i
だから
n/(i*2) > 0

n/2 >= i
に置き換えても OK (n/2 がループ不変量になるのでちょっとだけ速い?)
    • good
    • 1

ビット演算等を使用しない方法で、よりシンプルにしてみました。


(整数の範囲チェックや入出力時の文言等は、質問者様で味付けしていただければと思います)

#include <stdio.h>

int main(void) {
int i, n;
scanf("%d", &n);
for (i = 1; n / (i * 2) > 0; i *= 2);
for (; i > 0; n -= (n / i) * i, i /= 2)
printf("%d", n / i);
return 0;
}
    • good
    • 0

No7です。


No7では、一時的な格納エリアを配列で行っていましたので、それをint型の領域に格納するように
しました。考え方はNo7と同じです。
------------------------------------------------------------------
#include<stdio.h>
//#define BASE (10) //10進数で表示する場合
#define BASE (2) //2進数で表示する場合

int main(void)
{
int num; //入力された数値
int digit = 0; //BASEで割った余りを格納する領域
int digit_ctr = 0; //digitの桁数
int amari; //余り
int i;
printf("0以上の整数を入力してください=>");
scanf("%d",&num);
if (num<0){
printf("負の値又はint型の正の最大値を超えているので終了します\n");
return 0;
}
printf("入力値は[%d]です\n",num);
do {
amari = num % BASE;
num = num / BASE;
digit = digit * BASE + amari;
digit_ctr++;
}while(num != 0);
printf("\n"); //改行
//余りを前から格納しているので、表示する場合は、後ろから順に処理する。
//(前の処理と同じことを入力値の桁数分繰り返す)
for(i = 0; i < digit_ctr; i++){
amari = digit % BASE;
digit = digit / BASE;
printf("%d",amari);
}
printf("\n"); //改行
return 0;
}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
10進数で表示する場合は、
#define BASE (2) //2進数で表示する場合 をコメントアウトして、その後
#define BASE (10) //10進数で表示する場合 を有効にします。
但し、10進数で表示の場合、正しい結果が得られるのは、9桁までです。
10桁の数字を入力するとint型の上限を突き破るので、正しい結果が得られません。
(2進数の場合は10桁でも問題ありません。もっとも、9999999999のような数値を入力すると
、そもそもint型の上限を超えた値なので、正しい結果は得られません。
2147483647がint型の上限なのでその値までは正しく処理できます。)
    • good
    • 0

配列の使用不可


ビットシフト演算子の使用不可
ビット論理積の使用不可
となると
基本的にはNo3の方の方法しかありません。
No3の方のソースをそのままコンパイルするとエラーになりますが、
エラーをとった後で、
INT_MAX を 2147483647
EXIT_SUCCESS を 0
に置き換えれば、
#include <stdlib.h>
#include <limits.h>
は不要になります。
(int型が32ビットの整数であることが前提ですが)
    • good
    • 0

>何度も補足すみません


>stdio.hのみinclude可能です。
>配列は用いては行けません。
>intのみ(%dのみ)です。

①ビットシフト演算子 >>とか<<は使用可能ですか。
②ビットの論理和、論理積の&とか|は使用可能ですか。
    • good
    • 0
この回答へのお礼

①、②ともに使用不可です。
確認していただきありがとうございます。

学習と共に確認しているので他の方々への返事は今しばらくかかります。ご了承ください。

お礼日時:2016/11/19 01:22

なんで左に動かすかねぇ>#8. 右に動かせばいいだけなのに....



ちなみに #8 も動作保証がされていないことに注意.
    • good
    • 0

No.5に改良を加えて見ました。

(0からintの上限値まで対応)

#include <stdio.h>

int main(void) {
int i, n, m;
scanf("%d", &n);
for (i = 4, m = 0xf; (m < n) && (m != -1); i += 4, m <<= 4, m |= 0xf);
for (--i; i >= 0; i--)
printf("%d%s", (1 << i) & n ? 1 : 0, ((i % 4) == 0 ? " " : ""));
return 0;
}
    • good
    • 0

12345を10進数で表示する場合を考えてみます。


上記の値から "1","2","3","4","5"と文字が作れれば、
それを順に表示すると"12345"が表示できます。
では、 "1","2","3","4","5"をどうやって作るかですが、
与えられた数値を10で割り続け、その余りを格納していきます。これをその数値が0になるまで行います。
1回目 12345/10 --> 商 1234 余り5(この5を配列[0]へ格納)
2回目 1234/10 -->  商 123 余り4(この4を配列[1]へ格納)
3回目 123/10 -->  商 12 余り3(この3を配列[2]へ格納)
4回目 12/10 -->  商 1 余り2(この2を配列[3]へ格納)
5回目 1/10 -->  商0 余り1(この1を配列[4]へ格納)
商が0になったので、これで打ち切り。
配列を前から順に表示すると"54321"になってしまうので、後ろから順に表示し"12345"を表示します。
これが、10進数で表示する場合の考え方です。
2進数で表示する場合は、割る数を2にすれば良いだけです。
以下のソースを実行してください。
-------------------------------------------------
#include<stdio.h>
#define BASE (10) //10進数で表示する場合
//#define BASE (2) //2進数で表示する場合

int main(void)
{
int num; //入力された数値
int digit[32]; //BASEで割った余りを格納する領域
int digit_ctr = 0; //digitの桁数
int amari; //余り
int i;
printf("0以上の整数を入力してください=>");
scanf("%d",&num);
do {
amari = num % BASE;
num = num / BASE;
digit[digit_ctr] = amari;
digit_ctr++;
}while(num != 0);
printf("\n"); //改行
//余りを前から格納しているので、表示する場合は、後ろから順に処理する。
for(i = digit_ctr-1; i >= 0; i--){
printf("%d",digit[i]);
}
printf("\n"); //改行
return 0;
}
---------------------------------------------------
これは、10進数の場合です。まずこれで、処理結果を確認してください。
次に、
#define BASE (10) をコメントアウトし
#define BASE (2)を有効にしてください。
そうすると、2進数で表示する場合の処理になります。
    • good
    • 0

一瞬そういう系統のプログラムも考えたんだけど明らかに不具合を生じることがわかったので捨てたのでした>#5.



あ, ついでだけど「負の値も許す」場合に符号付絶対値で表現する (つまり -19 を -10011 とする) なら #3 に機能をちょっと追加するだけでできると思います... がさすがに処理系が準備できないのでうまく動くとは保証できない.
    • good
    • 0

No.4を一部訂正します。

(うっかり%luを使っていたので、%dに変更)

#include <stdio.h>

int main(void) {
int i, n, c = 4;
scanf("%d", &n);
for (i = 16; n >= i; i *= 16)
c += 4;
for (i = c - 1; i >= 0; i--)
printf("%d%s", (1 << i) & n ? 1 : 0, ((i % 4) == 0 ? " " : ""));
return 0;
}
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!