ページ 11

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

Posted: 2011年7月03日(日) 14:01
by ares
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);
}
にしてみたんですがコンパイルは出来るのですがプログラムが停止してしまいます。アドバイスください。

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

Posted: 2011年7月03日(日) 14:32
by non
昔、すでにアドバイスしたはず。(6月16日に)

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

Posted: 2011年7月03日(日) 14:44
by bitter_fox
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 は、型修飾子ではなく、型指定子です。
ご指摘ありがとうございます、修正しました。

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

Posted: 2011年7月03日(日) 15:37
by ares
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;
        }
こういうことですか?

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

Posted: 2011年7月03日(日) 16:02
by non
まず、unsigned char にしてみると。

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

Posted: 2011年7月03日(日) 16:46
by ares
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);
}
こうですか?

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

Posted: 2011年7月03日(日) 17:59
by 初級者
関数を呼び出しているところとその関数の実装とで、
引数の型の食い違いがたくさんあります。

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

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

Posted: 2011年7月03日(日) 18:32
by non
unsigned だけを書いた場合と、unsigned char は違います。

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

Posted: 2011年7月03日(日) 23:24
by box
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進で表示するように書き換える。

Posted: 2011年7月04日(月) 01:10
by かずま
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進で表示するように書き換える。

Posted: 2011年7月04日(月) 01:32
by かずま
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進で表示するように書き換える。

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

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

Posted: 2011年7月04日(月) 16:45
by ares
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);
}

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

Posted: 2011年7月04日(月) 17:08
by non
確認なのですが、
出力したいのは、10進で、
-128~127 ですか?それとも 0~255 ですか?
私は、0~255だと、思っていましたが、違ったのでしょうか?

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

Posted: 2011年7月04日(月) 17:41
by ares
non さんが書きました:確認なのですが、
出力したいのは、10進で、
-128~127 ですか?それとも 0~255 ですか?
私は、0~255だと、思っていましたが、違ったのでしょうか?
10進で、-128~127のsigned char型でも0~255のunsigned char型でもなく0~255のchar型です。

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

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

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

Posted: 2011年7月04日(月) 18:32
by non
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などの関数を使っているのは
処理系が変わってもうまくいくようにするためです。

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

Posted: 2011年7月04日(月) 20:52
by ares
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);
}
出来ました。