char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

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

char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#1

投稿記事 by ares » 14年前

unsigned型が表現できる全ての整数を、2進・8進・10進・16進で表示するプログラム

コード:

#include <stdio.h>
#include <limits.h>

int count_bits(unsigned x)
{
	int count =0;
	while (x){
		if(x & 1U)
			count++;
			x >>= 1;
		}
	return(count);
}

int int_bits(void)
{
	return(count_bits(~0U));
}

void print_bits(unsigned x)
{
	int i;
	for(i = int_bits() - 1; i >= 0;i--)
		putchar(((x >> i) & 1U) ? '1' : '0');
}

int main(void)
{
	char i;

	for(i = 0;i < UNIT_MAX;i++){
		print_bits(i);
		printf(" %6o %5u %4X\n" ,i ,i ,i);
	}
	return(0);
}
これをchar型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換えたいのですが

コード:

#include <stdio.h>
#include <limits.h>

int count_bits(char x)
{
	int count =0;
	while (x){
		if(x & 1)
			count++;
			x >>= 1;
		}
	return(count);
}

int int_bits(void)
{
	return(count_bits(~0));
}

void print_bits(char x)
{
	int i;
	for(i = int_bits() - 1; i >= 0;i--)
		putchar(((x >> i) & 1) ? '1':'0');
}

int main(void)
{
	char i;

	for(i = 0;i < CHAR_MAX;i++){
		print_bits(i);
		printf(" %6o %5u %4X\n" ,i ,i ,i);
	}
	return(0);
}
にしてみたんですがコンパイルは出来るのですがプログラムが停止してしまいます。アドバイスください。

non
記事: 1097
登録日時: 15年前

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#2

投稿記事 by non » 14年前

昔、すでにアドバイスしたはず。(6月16日に)
non

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#3

投稿記事 by bitter_fox » 14年前

http://dixq.net/forum/viewtopic.php?f=3 ... 905#p70905
まず、こちらの続きですよね?極力放置せずに同一の内容は一つのトピックにまとめていただきますようにお願いします。
あと、こちらも放置されています。放置をせずに解決をするなりしてください。
http://dixq.net/forum/viewtopic.php?f=3 ... 903#p70903
ares さんが書きました: これをchar型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換えたいのですがプログラムが停止してしまいます。アドバイスください。
non さんが書きました: >return(count_bits(~0U));

これもまずいかな。
前回の質問の時のnonさんの回答は読まれましたか?これに対して適切に修正すれば動くと思うのですが・・・
ares さんが書きました:

コード:

    while (x){
        if(x & 1)
            count++;
            x >>= 1;
        }
あと蛇足ですが、このインデントはかなり紛らわしいので適切にインデントするべきでしょう。

[hr][追記]
charの範囲というのはCHAR_MIN~CHAR_MAX(両端含む)ですがこのプログラムでは0~(CHAR_MAX - 1)(〃)になってしまっていますよ。(より厳密な表現に修正)
[追記]
ares さんが書きました: unsigned型が表現できる全ての整数を、2進・8進・10進・16進で表示するプログラム
あとunsignedは型ではなく型指定子なので厳密にいえば一つ目のプログラムで出力しているのはunsigned指定されたint型で表現できる整数ですよ。

[修正]
かずま さんが書きました:signed char の範囲は SCHAR_MIN~SCHAR_MAX(両端含む)です。
char の範囲が CHAR_MIN~CHAR_MAX(両端含む)です。
unsigned char の範囲は UCHAR_MIN~UCHAR_MAX(両端含む)です。

unsigned は、型修飾子ではなく、型指定子です。
ご指摘ありがとうございます、修正しました。
最後に編集したユーザー bitter_fox on 2011年7月04日(月) 07:31 [ 編集 2 回目 ]

ares

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#4

投稿記事 by ares » 14年前

non さんが書きました: 昔、すでにアドバイスしたはず。(6月16日に)
bitter_fox さんが書きました: まず、こちらの続きですよね?極力放置せずに同一の内容は一つのトピックにまとめていただきますようにお願いします。
すみませんでした。
bitter_fox さんが書きました: charの範囲というのは-128~127(両端含む)ですがこのプログラムでは0~126(〃)になってしまっていますよ。

コード:

int count =-128;
	while (x){
		if(x & 1)	count++;
		x >>= 1;
		}
これなら-128~127になりますかね?
non さんが書きました: >return(count_bits(~0U));

これもまずいかな。
Uがつくと符号無しになっているからUを外すということですか?
bitter_fox さんが書きました:

コード:

    while (x){
        if(x & 1)
            count++;
            x >>= 1;
        }
あと蛇足ですが、このインデントはかなり紛らわしいので適切にインデントするべきでしょう。

コード:

    while (x){
        if(x & 1)     count++;
        x >>= 1;
        }
こういうことですか?


ares

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#6

投稿記事 by ares » 14年前

non さんが書きました:まず、unsigned char にしてみると。

コード:

#include <stdio.h>
#include <limits.h>

char count_bits(unsigned x)
{
	int count =0;
	while (x){
		if(x & 1U)	count++;
		x >>= 1;
		}
	return(count);
}

char char_bits(void)
{
	return(count_bits(~0U));
}

void print_bits(unsigned x)
{
	int i;
	for(i = char_bits() - 1; i >= 0;i--)
		putchar(((x >> i) & 1U) ? '1' : '0');
}

int main(void)
{
	char i;

	for(i = CHAR_MIN;i < CHAR_MAX;i++){
		print_bits(i);
		printf(" %6o %5u %4X\n" ,i ,i ,i);
	}
	return(0);
}
こうですか?

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

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#7

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

関数を呼び出しているところとその関数の実装とで、
引数の型の食い違いがたくさんあります。

まずは、そのあたりを見直してみてはどうでしょうか。

non
記事: 1097
登録日時: 15年前

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#8

投稿記事 by non » 14年前

unsigned だけを書いた場合と、unsigned char は違います。
non

box
記事: 2002
登録日時: 15年前

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#9

投稿記事 by box » 14年前

char_bits() や count_bits() は、今回の問題を解決するために本当に必要ですか?
ares さんが書きました:

コード:

	for(i = CHAR_MIN;i < CHAR_MAX;i++){
i が CHAR_MAX(たぶん127)の場合は考慮しなくていいんでしょうか?
ares さんが書きました:

コード:

		printf(" %6o %5u %4X\n" ,i ,i ,i);
10進数で出力するときの書式文字列が"%5u"である理由は何でしょうか?
特に"u"のところがよくわかりません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

かずま

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#10

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

ares さんが書きました:

コード:

int count_bits(char x)
{
    int count =0;
    while (x){
        if(x & 1)
            count++;
            x >>= 1;
        }
    return(count);
}
にしてみたんですがコンパイルは出来るのですがプログラムが停止してしまいます。アドバイスください。
停止しているのではありません。逆に激しく動き続けているのです。
while が無限ループになっています。
元のプログラムでは unsigned x でしたよね。
x >>= 1 で右シフトすると、左からはゼロが入ってきて、これを繰り返すと x に入っている 1 のビットはすべてなくなって、x はゼロになり、while ループを抜けます。
ところが、char x だと、多くのコンパイラで、char は符号付きなので、最上位ビットが 1 だと、右シフトしてもそのビットは 1 のままです。
x は全ビットが 1 になり、いつまでたってもゼロにならず、このループを回り続けます。
この関数は count_bits(~0) で呼び出されています。
~0 というのは int の 0 の全ビットを反転するので全ビットが 1です。
この説明で理解できますか?

かずま

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#11

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

bitter_fox さんが書きました: signed修飾されたcharの範囲というのはCHAR_MIN~CHAR_MAX(両端含む)ですが
signed char の範囲は SCHAR_MIN~SCHAR_MAX(両端含む)です。
char の範囲が CHAR_MIN~CHAR_MAX(両端含む)です。
unsigned char の範囲は UCHAR_MIN~UCHAR_MAX(両端含む)です。
bitter_fox さんが書きました: あとunsignedは型ではなく型修飾子なので厳密にいえば一つ目のプログラムで出力しているのはunsigned修飾されたint型で表現できる整数ですよ。
unsigned は、型修飾子ではなく、型指定子です。
JIS X2010:2003(ISO/IEC 9899:1999) の 6.7.2 型指定子に記述されています。
6.7.3 型修飾子にあるのは、const, restrict, volatile だけです。

かずま

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#12

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

かずま さんが書きました: unsigned char の範囲は UCHAR_MIN~UCHAR_MAX(両端含む)です。
これは間違いです。次のように訂正します。
unsigned char の範囲は 0~UCHAR_MAXです。

ares

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#13

投稿記事 by ares » 14年前

box さんが書きました: i が CHAR_MAX(たぶん127)の場合は考慮しなくていいんでしょうか?
box さんが書きました: 10進数で出力するときの書式文字列が"%5u"である理由は何でしょうか?
特に"u"のところがよくわかりません。
かずま さんが書きました: 停止しているのではありません。逆に激しく動き続けているのです。
while が無限ループになっています。
元のプログラムでは unsigned x でしたよね。
x >>= 1 で右シフトすると、左からはゼロが入ってきて、これを繰り返すと x に入っている 1 のビットはすべてなくなって、x はゼロになり、while ループを抜けます。
ところが、char x だと、多くのコンパイラで、char は符号付きなので、最上位ビットが 1 だと、右シフトしてもそのビットは 1 のままです。
x は全ビットが 1 になり、いつまでたってもゼロにならず、このループを回り続けます。
この関数は count_bits(~0) で呼び出されています。
~0 というのは int の 0 の全ビットを反転するので全ビットが 1です。
この説明で理解できますか?
説明を基にこのように直してみたんですが2進数が表示されなくなってしまったんですが・・・。

コード:

#include <stdio.h>
#include <limits.h>

int count_bits(char x)
{
	int count =0;
	while (x){
		if(x & 1U)	count++;
		x >>= 1;
		}
	return(count);
}

char char_bits(void)
{
	return(count_bits(~-1));
}

void print_bits(unsigned x)
{
	int i;
	for(i = char_bits() - 1; i >= 0;i--)
		putchar(((x >> i) & 1U) ? '1' : '0');
}

int main(void)
{
	int i;

	for(i = SCHAR_MIN;i <= SCHAR_MAX;i++){
		print_bits(i);
		printf(" %11o %5d %8X\n" ,i ,i ,i);
	}
	return(0);
}

non
記事: 1097
登録日時: 15年前

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#14

投稿記事 by non » 14年前

確認なのですが、
出力したいのは、10進で、
-128~127 ですか?それとも 0~255 ですか?
私は、0~255だと、思っていましたが、違ったのでしょうか?
non

ares

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#15

投稿記事 by ares » 14年前

non さんが書きました:確認なのですが、
出力したいのは、10進で、
-128~127 ですか?それとも 0~255 ですか?
私は、0~255だと、思っていましたが、違ったのでしょうか?
10進で、-128~127のsigned char型でも0~255のunsigned char型でもなく0~255のchar型です。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#16

投稿記事 by ISLe » 14年前

ares さんが書きました:10進で、-128~127のsigned char型でも0~255のunsigned char型でもなく0~255のchar型です。
決め打ちしてはいけないと思いますが。
負数を右シフトした結果は予測できないので、左シフトで1ビットずつ論理積を取るようにしたら良いのでは?
(追記)
int型に昇格してしまうので無理でした。

non
記事: 1097
登録日時: 15年前

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#17

投稿記事 by non » 14年前

ares さんが書きました:10進で、-128~127のsigned char型でも0~255のunsigned char型でもなく0~255のchar型です。
「0~255のchar型です」って言われてもですね・・・・
charとだけ書いた場合は,処理系によって,unsigned char か signed char のどちらかになります。 
VisualC++とBorland C++ Compilerでは共に「signed char」だったと思います。
0~255を出力したいなら,unsigned char で取り扱わなくてはいけません。

また,charが1バイトか2バイトかも処理系によって異なります。
元のプログラムは,柴田望洋さんの本に載っているものだとおもいますが,int_bitsなどの関数を使っているのは
処理系が変わってもうまくいくようにするためです。
non

ares

Re: char型が表現できる全ての整数を、2進・8進・10進・16進で表示するように書き換える。

#18

投稿記事 by ares » 14年前

non さんが書きました:まず、unsigned char にしてみると。

コード:

#include <stdio.h>
#include <limits.h>

int count_bits(unsigned char x)
{
	int count =0;
	while (x){
		if(x & 1U)	count++;
		x >>= 1;
		}
	return(count);
}

int int_bits(void)
{
	return(count_bits(~0U));
}

void print_bits(unsigned x)
{
	int i;
	for(i = int_bits() - 1; i >= 0;i--)
		putchar(((x >> i) & 1U) ? '1' : '0');
}

int main(void)
{
	int i;

	for(i = 0;i <= UCHAR_MAX;i++){
		print_bits(i);
		printf(" %6o %5d %4X\n" ,i ,i ,i);
	}
	return(0);
}
出来ました。

閉鎖

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