質問 |
||
| QNo.3988229 | C言語超初心者・シフト演算の問題で質問です | |
|---|---|---|
| 質問者:panichead |
問題集を読んでいて、突然わからない記号が出てきました。 18行目、25行目の意味がさっぱりわかりません。 自分で調べてみたのですが、左に動くと2倍右に動くと1/2倍というのはどこにも書いてあり、理解できたのですがそれがどうこの問題とつながっていて、回答が1〜3まであるのに、0と1で表現するの?25行目の0x3は、16進数かなぁと思うのですが、それが&と組み合わさると・・・??????とか混乱してました・・・GW中にでもご回答いただけたらと思います。よろしくお願いいたします。 Q.「よい」「ふつう」「悪い」の3択で答えるアンケートが4問ある。アンケートに回答を記録するにあたり、1問の回答を 1つの変数に格納していたのでは効率が悪いので、2ビットに1問ずつ詰め込んで保存する。そうすれば一人分の回答を 保存するのにchar型の変数1つですむ。4つの回答をキーボードから入力して、実行例のように格納しなさい。 ■回答の保存 char型変数 7bit6bit(問4の回答)5bit4bit(問3の回答)3bit2bit(問2の回答)1bit0bit(問1の回答) ■実行例 問1:3 問2:2 問3:1 問4:3 回答一覧 問1問2問3問4 3 2 1 3 1:/************アンケートの回答の記録************/ 2: 3: 4:#include<stdio.h> 5:#define N 4 6: 7:main(){ 8: //ローカル変数の宣言 9: char ans; //回答を記録する 10: int work; //作業用 11: int i; //回数のカウント 12: 13: //入力と回答の記録 14: ans=0; //初期化 15: for(i=0;i<N;i++){ 16: printf("問%d:",i+1); 17: scanf("%d",&work); 18: ans|=(work<<i*2); 19: } 20: 21: //結果の表示 22: printf("\n回答一覧\n"); 23: printf("問1問2問3問4\n"); 24: for(i=0;i<N;i++){ 25: work=(ans>>(i*2))&0x3; 26: printf("%d",work); 27: } 28: printf("\n"); 29:} |
|
困り度:
|
||
| 質問投稿日時: 08/04/30 20:58 |
||
回答良回答20pt |
|
| ANo.4 | それぞれの値を2進数で表示すると( )のようになります。 問1:3 (00 00 00 11) 問2:2 (00 00 00 10) 問3:1 (00 00 00 01) 問4:3 (00 00 00 11) これをそれぞれのビット位置に移動するには 問1:3 (00 00 00 11) 0ビット左シフト 問2:2 (00 00 10 00) 2ビット左シフト 問3:1 (00 01 00 00) 4ビット左シフト 問4:3 (11 00 00 00) 6ビット左シフト のように(問数-1)*2ビットシフトすればいいことになります。 プログラム上では問数は0-3なのでそのまま2倍して大丈夫ですね。 4問を1つにまとめたら 11 01 10 11 になります ここから2問目の答えを取得する場合さっきとは逆に右に(問数-1)*2ビットシフトします 00 11 01 10 このままですと他の問の答えも含んでいるので一番下の2ビットだけにする必要があります。 それには必要な部分だけ1にした数字で & (and)すればOKです。 00 11 01 10 00 00 00 11 (16進数で0x3、10進数でも3なので同じですが) この2個を & すると問2の答えの 00 00 00 10 が求められるわけです。 25行目の0x3はこの数字です |
|---|---|
| 回答者:php504 | |
| 種類:回答 どんな人:一般人 自信:自信あり |
|
| 回答日時: 08/05/01 09:12 |
|
| |
| この回答へのお礼 | へえ〜〜このプログラムにはこんな深い内容が込められているのですね! なるほど、移動させて&で消すあたり、面白いです☆彡 非常に参考になりました。ありがとうございます!! |
回答 |
|
| ANo.3 | 絵を使って理解する方がいいかも.... 以下, ans を 8ビットと仮定します. aa, bb, cc, dd を問1〜問4 の回答としたときに ans = [dd][cc][bb][aa] と入れたいわけです. すると, 例えば問3 の回答である cc が来たときには ans = [00][00][bb][aa] と入っていて, これを ans = [00][cc][bb][aa] としたいわけです. すると, 「cc を 4ビット左にシフトして or をとればいい」ということがわかります. 問3 ということは i = 2 だから「2*iビット左シフトする」ということになります. |
|---|---|
| 回答者:Tacosan | |
| 種類:アドバイス どんな人:一般人 自信:参考意見 |
|
| 回答日時: 08/05/01 00:05 |
|
| |
| この回答へのお礼 | お返事ありがとうございます! 左にシフトしてorをとることで1つの変数に横一列に保存するのですね。 それとは別に、表示は考えるんですね〜〜。 ですよね??・_・; |
回答 |
|
| ANo.2 | >16進数かなぁと >18: ans|=(work<<i*2); >25: work=(ans>>(i*2))&0x3; 数の表現の仕方が複数有るだけ。中身は一緒。 現実世界でも有るでしょ。 1時間=60分=1/24日=3600秒 (単位は違うけど指している値は同一) 空白入れると 判りやすくなるんじゃない? 18: ans |= ( work << i * 2 ) ; 25: work = ( ans >> (i*2) ) & 0x3 ; |
|---|---|
| 回答者:SAYKA | |
| 種類:アドバイス どんな人:一般人 自信:参考意見 |
|
| 回答日時: 08/04/30 21:48 |
|
| |
| この回答への補足 | さっそくのお返事ありがとうございます!! ans=ans|(work<<i*2)だから、問1はans=0|(work<<2)となって、 論理和だから、どちらかが1なら1か、両方0なら0で・・・ workを2ビット左へ移動するということは・・・下位ビットに0が入って・・・ココからが難しいです><; |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |