• 締切済み

プログラムについて

2進数を文字としてgets()関数を使って入力し,入力された値と宣言している変数(初期値は0)とのビット演算和を取り,2進数に変換し直すという3つの動作を繰り返すプログラムを作成しようとしています。 現在は,現在は最後の出力の部分が前回演算和した値が反映されずに出力してしまうのでこまっています。現在作成しているプログラムを添付します。ここを直したほうがよい,または,このプログラムの方がよいのではと思う方は返信願います。 int main(void) { char a[100],e[100]; int len,k,p,g; int c=0,d; int nisin[16]; int i; printf("2進数を入力:"); gets(a); while(a[1]!=0){ len=strlen(a); for(k=0;k<=len-1;k++){ e[k]=(a[k]-'0')<<(len-(k+1)); } g=0; for(p=0;p<=len-1;p++){ g+=e[p]; } printf("10進数は:%d\n",g); c|=g;/**/ printf("演算和:"); /*変換*/ for(i=0; i<16; i++){ nisin[i] = c % 2; c = c / 2; } /*出力*/ for(i=16-1; i>=0; i--){ printf("%d",nisin[i]); } printf("\n"); printf("2進数を入力:"); gets(a); } return 0; }

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.5

・2進数表記文字列を、gets()関数を使って入力し、それを数値化する。 ・数値化した値と、ある変数(初期値は0)との論理和を求める。 ・これを2進数表記する。 これが「3つの動作」で、  ・「ある変数」は入力以降は初期化せず、1桁の2進数表記文字列が入力されるまで「3つの動作」を繰り返す。 ではないですか。 この解釈が間違っている場合は、以降無視して下さい。 --------------------------------------------------- 過去の質問しかり、今回の質問でも、なにか大きな勘違いされていませんか?。 ★パソコンは、文字にしろ数値にしろ、0か1でしか扱えませんよ。  ここを押さえておけば、「2進数に変換し直す」という記述はしないかと・・。 --------------------------------------------------- 《プログラム構造》 >3つの動作を繰り返すプログラムを作成しようとしています。  「繰り返す」ためと思われる、while( a[1] != 0 ){ は、「2進数1桁の入力でない間」を表すかと思います。  printf( "2進数を入力:" ); と gets( a ); が2組有る無駄を考えると、    while( 1 ){       printf( "2進数を入力:" );       gets( a ); 1つ目の動作の前半(入力)       if( '\0' == a[ 0 ] ) break; // ENTER のみの入力で終了(おまけ)       if( '\0' == a[ 1 ] ) break; // 1桁の入力で終了       ・・(1つ目の動作の後半(数値化))       ・・(2つ目の動作)       ・・(3つ目の動作)    }   がよろしいかと。 《1つ目の動作の後半》  int Str2Value( char a[] ) のような関数を作り、  呼び出し元では、g = Str2Value( a ); とすればよいのでは・・。  具体的には、    for(k=0;k<=len-1;k++){    e[k]=(a[k]-'0')<<(len-(k+1));    }    g=0;    for(p=0;p<=len-1;p++){    g+=e[p];    }  の部分を、一体化すればよいかと( e[], p が不要となります)・・。    g = 0;    for( k = 0; k <= ( len - 1 ); k++ ){      g += ( ( a[k] - '0' ) << ( len - ( k + 1 ) ) );    }    return( g ); 《2つ目の動作》  これは、c |= g; ですよね。 《3つ目の動作》  これも関数にすれば、「値を壊すようなこと」を気にする必要がありません。  void Value2str( int c )  で、呼び出し元は、Value2str( c ); です。  関数の中で、c をどのように料理しようが、呼び出し元の c には影響有りません。  具体的なソースは、質問者様の /*変換*/ と /*出力*/ 部分を、Value2str() に入れるだけ・・。

  • xi_fjw_ix
  • ベストアンサー率100% (2/2)
回答No.4

「質問者:02031988」さんのプログラムの作成意図とか、目的は考慮していません。あくまでも「c = c / 2; で値を壊すようなこと」をしない事だけを考えた提案です。 for(i = 0; i < 16; i++){ nisin[i] = c % 2; c = c / 2; } の個所を以下のように変更してください。 mask = 1; for(i = 0; i < 16; i++){ if((c & mask) != 0){ nisin[i] = 1; }else{ nisin[i] = 0; } mask <<= 1; } それから、変数の定義を1行追加してください。 unsigned int mask;

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.3

論理和を求めた結果について - 2進数化するために変数の値を壊す必要がある - 次の論理和で使うために変数の値を保持する必要がある の両方を満たすには、変数を2つ用意して、片方は2進数化のときに、もう片方は値を保持するために使えばいいだけです。

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.2

括弧が不足していました。正しくは g = (g<<1) + (a[i] - '0'); です。

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

「演算和」って珍しい表現ですね。「(ビットごとの)論理和」というのが普通だと思います。 e[k]=(a[k]-'0')<<(len-(k+1)); lenが大きいときに右辺の値がchar型の範囲を超えてしまいます。 ついでに書くと、e[]に各ビットの値を入れてからgに足し込むのは、他の用途でe[]を使うのでなければ無駄です。 試してはいませんが、e[]は使わずこんなのでどうでしょう。 g=0; for (i=0; i<len; i++) { g = g<<1 + (a[i] - '0'); } 本当は、a[i]が'0'または'1'であることのチェックが必要ですが。 「前回演算和した値」がcに残っていることを期待しているのでしょうが、/*変換*/のループの中で c = c / 2; を実行して値を壊してしまっています。 あと、a[]やe[]は2進数100桁 (99桁) 分用意しているのに、nisin[]はなぜ16桁分だけなのでしょうか。

02031988
質問者

補足

salsberryさんへ for(k=0;k<=len-1;k++){ e[k]=(a[k]-'0')<<(len-(k+1)); } 上記の部分を提案された部分と書き直せばよいのでしょうか?? それとも、 for(k=0;k<=len-1;k++){ e[k]=(a[k]-'0')<<(len-(k+1)); } g=0; for(p=0;p<=len-1;p++){ g+=e[p]; } の部分を上記に書き直せばよいのでしょうか? 後、/*変換*/と/*出力*/の部分で10進数から2進数に直そうとしています。このプログラムではc = c / 2;で値を壊すようなことをせずに値を保持したままループさせたいと考えています。お手数ですが、どのようにすればよいかいい案はございませんか?

関連するQ&A