勉強中の初心者ですが、ビット演算なるもので詰まりました

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ドシロート

勉強中の初心者ですが、ビット演算なるもので詰まりました

#1

投稿記事 by ドシロート » 6年前

最近C言語の勉強を始めたのですが、ビット演算を使って符号なし10進数xを2進数表示する関数を作るというよくわからない演習問題が出てきました。
入力した10進数を2進数に変えて表示させるということなのですが、
・scanf禁止
・unsignedのビット数は32
・n=sizeof(unsigned)*8
・void print_binary(unsigned x);
という条件を守って作るようです。
参考書は読みましたが、方針も思いつきませんでした。どなたか教えてくださいませんか?

模範解答には、コマンドプロンプトに
255
00000000000000000000000011111111
と表示される。という風に書かれていました。。。

これまではprintfとかif文、プロトタイプ宣言、配列など、本当に初歩のところをやっていました。

ドシロート

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#2

投稿記事 by ドシロート » 6年前

申し訳ありません。いま私が書いているものの状態を載せるのを忘れておりましたので追加致します。

コード:

#include <stdio.h>
#define MAXLINE 1000
#define NMAX	3000 

int suuchi_u(char s[]);
int getline(char s[], int lim);

main()
{
	char line[MAXLINE];
	int i,n,data[NMAX];
	
	while(getline(line, MAXLINE)>0)//入力した数字の数が0以上。
	{
		
		n=suuchi_u(line);
		
		printf("データ数%d\n",n);
	}
}

int suuchi_u(char s[])
{
	    int n,i;
	    char line[MAXLINE];
	    n=0;
		for(i=0; '0'<=line[i]&&line[i]<='9'; i++)
		{
			n=10*n+(line[i]-'0');
		}
		
		return n;
}


int getline(char s[], int lim)//数字の入力。
{
	int c,i;
	lim=NMAX;
	
	for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
	{
		s[i]=c;
	}
	
	if(c=='\n')
	{
		s[i]=c;
		++i;
	}
	s[i]='\0';
	
	return i;
}


アバター
usao
記事: 1574
登録日時: 7年前

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#3

投稿記事 by usao » 6年前

>・n=sizeof(unsigned)*8

これは何を言っているのですか?
(nとは 何を表す値?)
オフトピック
符号なし10進数xを2進数表示する関数
void print_binary(unsigned x)
を作りなさい,という旨の問題なのだと思いますが,
対して,あなたが示したコードというのは
>scanf禁止
とかいう謎ルールに対抗して実装されたと思われる 数値xを入力する部分 のコードであるように思われます.
つまり,主題に関して言えば,「どうでもいい部分」です.
コードを示すのならば,
あなた流の print_binary() は現状どうなっているのか?を示すべきではないでしょうか.
(その他の部分については,「プログラムとして動作するためには」必要でしょうが,
 この場で 主題=print_binary()の中身 の話をする分には不要に思います.)

初級者
記事: 200
登録日時: 9年前

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#4

投稿記事 by 初級者 » 6年前

正しいかどうかは保証の限りにあらず。

コード:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define N (10)      // 32ビット符号なし整数の最大桁
#define BIT (32)

void print_binary(unsigned x)
{
   int n[BIT], i;

   printf("%d\n", x);
   for (i = 0; i < BIT; i++) {
       n[i] = x % 2;
       x >>= 1;
   }
   for (i = BIT - 1; i >= 0; i--) {
       printf("%d", n[i]);
   }
   putchar('\n');
}

int main (void)
{
   char s[N + 1];
   unsigned x;
   int i;

   fgets(s, sizeof(s), stdin);
   s[strlen(s) - 1] = '\0';
   for (x = i = 0; i < N; i++) {
       if(isdigit(s[i])) {
           x = 10 * x + s[i] - '0';
       }
   }
   print_binary(x);
   return 0;
}

ドシロート

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#5

投稿記事 by ドシロート » 6年前

usao様
回答ありがとうございます。n=sizeof(unsigned)*8については申し訳ありませんが私もわかりません。ただ、問題の横に書かれていたので、それをどこかで使うのだろうかと予想しています。

私が書いている部分ですが、scanfが禁止されているので、なんとかして10進数だけでも表示させてみようとしたものでございます。usao様のご指摘の通り、的外れの内容かもしれません。失礼いたしました。

ドシロート

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#6

投稿記事 by ドシロート » 6年前

初心者様
回答ありがとうございます。回答に書いていただいたpgmを見て、どうするべきか考えたいと思います。

アバター
usao
記事: 1574
登録日時: 7年前

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#7

投稿記事 by usao » 6年前

>ビット演算を使って
ということですから,ANDとかORとかを使いましょう,という意味でしょう.
例えばこんな感じで良いのではないでしょうか.

コード:

void print_binary( unsigned int x )
{
    const size_t nBit = sizeof(unsigned int)*8; //==32
    unsigned Mask = ( 0x01 << (nBit - 1) );

    for( size_t i=0; i<nBit; i++ )
    {
        printf( "%c", ( (x&Mask)!=0 ? '1' : '0' ) );
        Mask >>= 1;
    }
    printf( "\n" );
}

ドシロート

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#8

投稿記事 by ドシロート » 6年前

先ほどのアドバイスにあった
#include <string.h>
#include <ctype.h>
はまだ授業でやっていないため、使い方がよくわかりませんでした。。。

アバター
みけCAT
記事: 6252
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#9

投稿記事 by みけCAT » 6年前

自分が書いた入力ルーチンも貼っておきます。

コード:

#include <stdio.h>

/* 文字をそれが表す数値に変換する */
int get_number_from_char(char c) {
	char number_list[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
	int i;
	for (i = 0; i < 10; i++) {
		if (number_list[i] == c) return i;
	}
	return -1;
}

/* 標準入力から非負整数を1個読み込む */
unsigned int read_non_negative_integer(void) {
	while (1) {
		unsigned int ret = 0; /* 読み込んだ整数 */
		int current_char = '\0'; /* 読み込んだ文字 */
		int nonempty = 0; /* 入力が空ではなかったというフラグ */
		int invalid = 0; /* 不正な文字があったことを表すフラグ */
		int overflow = 0; /* 入力がオーバーフローしたことを表すフラグ */
		while (1) {
			int current_number; /* 読み込んだ文字に対応する数値 */

			/* 次の文字を読み込む */
			if ((current_char=getchar()) == EOF) {
				printf("Unexpected end of input!\n");
				return -1;
			}
			/* 改行なら、今回の入力の終わりとみなす */
			if (current_char == '\n') break;
			/* 入力の文字を数値に変換する */
			current_number = get_number_from_char(current_char);
			if (current_number < 0) {
				/* 入力が数値ではなかったので、不正 */
				invalid = 1;
			} else {
				unsigned int new_ret;
				/* 入力が空ではなかったという情報を保存する */
				nonempty = 1;
				/* オーバーフローをチェックしながら、入力を反映させる */
				new_ret = ret * 10;
				if (new_ret / 10 != ret) {
					overflow = 1;
				} else {
					if(new_ret + current_number < new_ret) {
						overflow = 1;
					} else {
						/* オーバーフローしなかったので、retを更新する */
						ret = new_ret + current_number;
					}
				}
			}
		}
		if (invalid) {
			/* 不正な文字があった */
			printf("The input contains invalid char(s).\n");
		} else if (overflow) {
			/* 入力がオーバーフローした */
			printf("The input is too large.\n");
		} else if (!nonempty) {
			/* 入力が空だった */
			printf("Please input a non-negative integer.\n");
		} else {
			/* 正しい入力が得られた */
			return ret;
		}
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ドシロート

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#10

投稿記事 by ドシロート » 6年前

みけCAT様
回答ありがとうございます。コンパイルしてみましたが、未解決の外部シンボル~などのエラーがでてしまいました。。。

入力した10進数を2進数表示するこの課題は、私のようなC言語に振れはじめて2か月弱の人間には難しいものなのでしょうかね・・・

かずま

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#11

投稿記事 by かずま » 6年前

>ビット演算を使って
ということですから、ANDとかORとかを使いましょう、という意味でしょう。
例えばこんな感じで良いのではないでしょうか。

コード:

void print_binary(unsigned x)
{
    unsigned n = 32;
    while (n--) putchar(x>>n & 1 | '0');   // AND も OR も使っています
    putchar('\n');
}

int main(void)
{
    unsigned x;
    if (fscanf(stdin, "%u", &x) == 1) print_binary(x);
    return 0;
}
なお、print_binary は、
「符号なし10進数 x を 2進数表示する関数」ではありません。
x は、10進数ではないからです。
x の値は、コンピュータの内部表現になっていて、あえて言えば
「表示形式ではない 2進数」です。
print_binary は、それを「表示可能な 2進数文字列」に変換しているだけです。

アバター
みけCAT
記事: 6252
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 勉強中の初心者ですが、ビット演算なるもので詰まりました

#12

投稿記事 by みけCAT » 6年前

ドシロート さんが書きました:みけCAT様
回答ありがとうございます。コンパイルしてみましたが、未解決の外部シンボル~などのエラーがでてしまいました。。。
こちらではhttps://ideone.com/でコンパイルが通ることを確認しているので、詳しいエラーメッセージを教えてください。
なお、入力ルーチンしか載せていないので、これだけで「普通」にコンパイルして実行することはできません。
(これ単体をコンパイルしてオブジェクトファイルを作ることは可能なはずです)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る