質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

2回答

449閲覧

第nビットをリセットする関数

yu_a

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2023/05/21 05:09

編集2023/05/21 10:23

実現したいこと

符号なし整数xの第posビットを、セットした値を返す関数set、リセットした値を返す関数resetを作成する。

※ご指摘ありがとうございます。値を返す、ではなく表示する関数でした。一度値を返す関数として回答してくださった方はそのまま教えていただきたいです。

前提

上の問題で、下のようにコードを作成しましたが、リセットの方で正しい値が返されません。

該当のソースコード

C言語

1#include <stdio.h> 2 3int count_bits(unsigned x) 4{ 5 int bits = 0; 6 while (x){ 7 if (x & 1U) bits++; 8 x >>=1; 9 } 10 return bits; 11} 12 13//--- unsigned型のビット数を返す---// 14int int_bits(void){ 15 return count_bits(~0U); 16} 17 18//---unsigned型のビット内容を表示---// 19void print_bits(unsigned x) 20{ 21 for (int i = int_bits() - 1; i >= 0; i--) 22 putchar(((x >> i) & 1U) ? '1' : '0'); 23} 24 25unsigned set(unsigned x, int pos) 26{ 27 for (int i = int_bits() - 1; i >= pos ; i--) 28 putchar(((x >> i) & 1U ) ? '1' : '0'); 29 30 putchar(((x >> (pos - 1)) & ~1U) ? '1' : '0'); 31 32 for (int i = pos - 2; i >= 0; i--) 33 putchar(((x >> i) & 1U) ? '1' : '0'); 34 35 return 0; 36} 37 38unsigned reset(unsigned x, int pos) 39{ 40 for (int i = int_bits() - 1; i >= pos ; i--) 41 putchar(((x >> i) & 1U ) ? '1' : '0'); 42 putchar(((x >> (pos - 1)) & ~1U) ? '1' : '0'); 43 44 for (int i = pos - 2; i >= 0; i--) 45 putchar(((x >> i) & 1U) ? '1' : '0'); 46 47 return 0; 48} 49 50 51int main(void) 52{ 53 unsigned n1, n2; 54 55 printf("非負の整数:"); scanf("%u", &n1); 56 printf("第何ビットを変更しますか?"); scanf("%u", &n2); 57 58 printf("もとの数 = "); print_bits(n1); putchar('\n'); 59 printf("第%uビットをセットした値 ",n2); set(n1,n2); putchar('\n'); 60 printf("第%uビットをリセットした値 ",n2); reset(n1,n2); putchar('\n'); 61 62 return 0; 63 64}

試したこと

set関数は合っていると思います。
reset関数に関して、例えば実行結果が以下のようになり、リセットされません。

非負の整数:127
第何ビットを変更しますか?3
もとの数 = 00000000000000000000000001111111
第3ビットをセットした値 00000000000000000000000001111111
第3ビットをリセットした値 00000000000000000000000001111111

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2023/05/21 05:25

そもそもとして > セットした「値を返す」関数 > リセットした「値を返す」関数 でないのでNGだと思います。 「表示する関数」としても、試してみると 非負の整数:0 第何ビットを変更しますか?1 もとの数 = 00000000000000000000000000000000 第1ビットをセットした値 00000000000000000000000000000001 第1ビットをリセットした値 00000000000000000000000000000000 となるのでセットも間違っていますね。 そんな難しいことをせずに セット: x|(1<<pos) リセット: x&~(1<<pos) として、必要なら2進数表示する話だと思いますが。
yu_a

2023/05/21 07:53

ありがとうございます。セット→数字を1に変更、リセット→0に変更という認識だったのですが、セット関数が間違っているということはそれも間違っているという事でしょうか?
thkana

2023/05/21 10:58

あぁ、第何bitって1~を期待してたのか... 非負の整数:0 第何ビットを変更しますか?0 もとの数 = 00000000000000000000000000000000 第0ビットをセットした値 000000000000000000000000000000001 第0ビットをリセットした値 000000000000000000000000000000000 非負の整数:0 第何ビットを変更しますか?1 もとの数 = 00000000000000000000000000000000 第1ビットをセットした値 00000000000000000000000000000001 第1ビットをリセットした値 00000000000000000000000000000000 で同じになっちゃだめじゃん...って思ったのだけれど。第何ビットに0は入力されない前提、ですね? そこは勘違いでした。失礼しました。
guest

回答2

0

指摘のあるとおり、

符号なし整数xの第posビットを、セットした値を返す関数set、リセットした値を返す関数resetを作成する。

になっていません。

「~~~という値を返す関数」という概念が理解できてないのですかね。
例えば、「引数の値を2倍して返す関数two_times」は、下記です。

C

1int two_times(int x){ 2 return x*2; 3} 4// 間違いの例 5// int two_times(int x){ 6// printf("%d",x*2); 7// return 0; 8//}

・関数set、関数reset内で 表示しない
・main関数の後半はこのように書く
でやってみて下さい。

C

1 printf("もとの数 = "); 2 print_bits(n1); putchar('\n'); 3 printf("第%uビットをセットした値 ",n2); 4 print_bits(set(n1,n2)); putchar('\n'); 5 printf("第%uビットをリセットした値 ",n2); 6 print_bits(reset(n1,n2)); putchar('\n');

投稿2023/05/21 09:08

otn

総合スコア84559

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

set関数は合っていると思います。

ってなんでしょうか、確認作業(テスト)はちゃんとあってるかがわかる形でやるべきです。

それはともかく、C言語では引数として渡した値を変更したいのならば
scanfみたいに&をつけてアドレスを渡す必要があります。
なので、setもresetも間違っていると思います。
別のやり方だとnew_n1 = set(n1,n2)で変更された値をreturnして新しく格納する方法でもあります

投稿2023/05/21 05:47

red_snow

総合スコア19

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu_a

2023/05/21 07:57

独学で進めている初心者ゆえ、よろしければもう少し詳しく教えて頂きたいです。 [アドレスを渡す]とはどういう意味でしょうか?
episteme

2023/05/22 00:31

> [アドレスを渡す]とはどういう意味でしょうか? たとえばこんなの。 void plus_one(int* pn) { *pn = *pn + 1; } // アドレスpnが差す先に1を加える int main() { int n = 10; plus_one(&n); return 0; } // plus_one に nの[アドレスを渡す]
red_snow

2023/05/22 04:31

独学はいいけど、そのくらい書いてないんですか? アドレス渡しがわからないなら、 とりあえず、ググったりChatGPTに聞いてみるのが先だと思います。 正直、図とか付きで解説があったりするので、そちらの方が分かりやすいと思います。 独学で進めるなら人に聞く前にそういうワンステップを踏む習慣を付けましょう。 値渡し、参照渡しを調べてみるといいでしょう。 プログラムを実行すると、メモリ上に変数の値を格納する領域が確保されます。 関数を実行すると新しくその関数用の変数の領域が確保されるのですが、 普通は、値がコピーされて新しい関数用の変数に設定されます。setのxにはn1と同じ127が入ってます これは元々のn1とは別物、コピペされてきた新しいファイルみたいなもので好きに変更しても 元のn1には変化はありません。 アドレス渡しはコピペではなく、n1という変数の値が格納されている場所(メモリ上の番地)を関数に 渡します。これによってset関数はn1の値を直接見たり、変更することができるようになります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問