• ベストアンサー

2進数の乗算と除算

先日、桁上がりについて質問させていただいた者です。 加算と減算はなんとか完成したのですが、乗算と除算になって混乱してしまいました。 二進数の乗算、除算はビットシフトと関係がありますが、私の作っているものの場合はどのようなソースコードにすればよいでしょうか? (ちなみに、bの値は2のべき乗に限定しています。) int main(void) { int a,b,i; int x[8],y[8]; puts("二つの符号なし整数を入力してください。(ただしa>bとし、bは2のべき乗の値とする)"); printf("a="); scanf("%d",&a); printf("b="); scanf("%d",&b);  printf("\n"); /*二進数の形に変換*/ for(i=0;i<=7;i++){ x[i]=a%2; a=a/2; y[i]=b%2; b=b/2; } puts("aとbをそれぞれ二進数で表すと"); printf("a="); for(i=7;i>=0;i--){ printf("%d",x[i]); } puts(""); printf("b="); for(i=7;i>=0;i--){ printf("%d",y[i]); } printf("となります。\n\n");     return(0);  }

noname#47478
noname#47478

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★アドバイス >加算と減算はなんとか完成したのですが、乗算と除算になって混乱してしまいました。  ↑  何が混乱したのでしょうか? >二進数の乗算、除算はビットシフトと関係がありますが、 >私の作っているものの場合はどのようなソースコードにすればよいでしょうか?  ↑  まずはビットシフトで乗算を作ってみましょう。  2進数の乗算は次のようになります。(2のべき乗限定)  例えば  a…123  b…32(2の5乗)  この場合は 123 を 2 進数に変換して 01111011 とします。  その後に 01111011 を左に 5 ビットシフトすればよいだけです。  なお、シフトさせた結果の配列サイズは x[8] の倍 16 必要になります。  下にそのサンプルを載せておきます。 サンプル: int x[ 8 ] = { 1, 1, 0, 1, 1, 1, 1, 0 }; ←10進数で 123 を表す int y[ 8 ] = { 0, 0, 0, 0, 0, 1, 0, 0 }; ←10進数で 32 を表す int z[ 16 ]; ←シフトした結果を格納 int shift; ←シフトするビット数 // シフト数を算出 for ( shift = i = 0; i < 8 ; i++ ){  if ( y[i] == 1 ){   shift = i;   break;  } } // 初期化 for ( i = 0 ; i < 16 ; i++ ){ ←z[16]の回数  z[ i ] = 0; } // 左シフト for ( i = 0 ; i < 8 ; i++ ){ ←x[8]の回数  z[ i + shift ] = x[ i ]; } // z = x * y の表示 printf( "z=" ); for ( i = 15 ; i >= 0 ; i-- ){  printf( "%d", z[i] ); } printf( "\n" ); 説明: ・上記のサンプルをつければ b が 2 のべき乗限定で乗算らしきものが出来ます。  前回の加算は 8 ビットでしたよね。すると乗算も除算も 8 ビットという事ですよね。  乗算も除算も演算は倍の 16 ビット分のサイズが必要になります。ここ注意! ・あと上記のサンプルの x, y に直接 2 進値を入れていますが x[0]、y[0] が下位ビット  になります。これは質問者さんの仕様に合わせています。 その他: ・ちゃんとした乗算(2のべき乗限定ではないタイプ)を行いたい場合は次のようになります。  a=123  b=12  の場合は  a=01111011  b=00001100  となるので b の下位ビットから順番にスキャンして 0 ならそのまま、1 なら a を自分の  ビット数だけ左シフトすれば良い。この結果を倍の 16 ビット配列に加算していけばやがて  b のすべてのビットを処理したとき a と b の乗算結果になります。 ・除算は別の機会にアドバイスします。まずは乗算を作ってみて下さい。 ・以上。

noname#47478
質問者

お礼

回答ありがとうございます!私はビットシフトのことが完全に把握できていなかったので混乱してしまっていたんです。 なので、アドバイス通りにまずは乗算からじっくり理解したいと思います。

その他の回答 (6)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.7

★回答者 No.6 です。修正です。 ・最後の部分でキャストすればよいとアドバイスしましたが一部、間違いました。  間違い⇒ #define LONGMASK ((LONGINT1)(~((~0UL) << LONGBITS)))  正しい⇒ #define LONGMASK ((LONGINT2)(~((~0UL) << LONGBITS)))  ※LONGINT1 を LONGINT2 にして下さい。 ・以上です。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.6

★そうでしたか。 >私は自分で学習したところ(まだ初めて2ヶ月くらいですが)までの内容でどこまでできるかという挑戦で >作り始めたので、この形で完成させてみたいと思っています。  ↑  薄々は感じてはいましたけど。  ソース上で二進数の形に変換するとき 2 で割ったあまりを x[i] にセットして a = a/2; を  行っていますね。私ならビット演算で AND、右シフトしてセットします。  つまり、  /*二進数の形に変換*/  for ( i = 0 ; i < 8 ; i++ ){ ←ここは 8 にする(8Bitなので分かりやすく)   x[ i ] = a & 0x1; ←2 で割ったあまり 0、1 がセットされる   y[ i ] = b & 0x1;   a >>= 1; ←2 で割ったのと同じ効果になる   b >>= 1;  }  ↑  こんな感じです。  でも多分、ビット演算はまだ知らないのでしょうね。  下の『参考URL』をどうぞ。 >2のべき乗以外で掛け算できるようにはしようとは思っていません。 >上に書いたように初心者ですので、恥ずかしながら今のところは簡単にしようと思っています。  ↑  やっぱりプログラミングを簡単に行うために限定していたのですね。  でもこれをきっかけに 2 のべき乗以外でも掛け算できるように考えてみてはどう。  もし出来たらスキルアップしますよ。 >一塊を 8 個の配列にセットして扱っているのは、そういう方法しか思いつかなかったので、 >そうしただけであって、特に意図はありません。  ↑  これは質問者さんの仕様という事ですね。  分かりました。  でも、回答者 No.4 さんの言うとおりで変数はコンピュータ上で全部 2 進数で格納されています。  なので x * y とすれば 2 進数の演算を行ったことにもなるのです。  でも 2 進数の演算を理解するという目的では今回の質問はそれなりに意味があります。  理由は今回の方式で四則演算が出来ればその後に『多倍長演算』の考えに繋がりますので。 ●質問者さんとVTClient さんへ。 >で当確する桁数ビットマスクを得る >と言う、解釈でよいのでしょうか?  ↑  そうですね。解釈は正しいです。 ・add() 関数で 8 ビットの最大値 0xFF を定義すればよいのですが、LONGBITS だけを  可変すれば自動的に作成してくれるようにしたためです。これなら 7、15、20 ビットでも  自分で 0x7F、0x7FFF、0xFFFFF としなくても良いからです。 ・あとちょっと修正しますと  #define LONGMASK (~((~0UL) << LONGBITS))  の行は  #define LONGMASK ((LONGINT1)(~((~0UL) << LONGBITS)))  とキャストした方がコンパイルで警告メッセージが出ませんね。  参考にする際はキャストした方がいいです。 ・以上。

参考URL:
http://www9.plala.or.jp/sgwr-t/c/sec14.html
noname#47478
質問者

お礼

回答ありがとうございます!それと、私のわがままをご理解いただきましてありがとうございます。 参考URLのおかげでビット演算が少しずつわかってきました。 これからもっと深くじっくりと理解したいと思います。

noname#50176
noname#50176
回答No.5

ANo.2 です。 >アドバイスいただいたような内容はまだ私にとっては難しすぎるんです。 確かに、Oh-Orangeさんの解説は(私としても)非常に参考になります。 ただ理解できないと残念になってしまうので便乗して Oh-Orangeさんに、ある1行でお聞きしたいのですが…、 #define LONGMASK (~((~0UL) << LONGBITS)) とは、 符号なし(UNSIGNED LONG)のコンパイル上でのnビット (例えば通例32ビット)で →00000000000000000000000000000000 を1補数反転 →11111111111111111111111111111111 のLONGBITS=8ビット上位シフト →11111111111111111111111100000000 の1補数反転 →00000000000000000000000011111111 で当確する桁数ビットマスクを得る と言う、解釈でよいのでしょうか? (すみません、どさくさまぎれで…)

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.4

そもそも,あなたがやってるのは2進数の計算ではありませんが.. scanf(..., &x)...scanf(..., &y) z=x*y; とやれば,これがすでに2進数での計算が行われています.現代のコンピュータは全部二進演算するように作られているのですから. 整数配列の各要素に1か0だけ入れて,2進数の筆算をなぞるような形で演算するというのは,効率が悪いだけで意味がありません. 何がやりたいのでしょうか? 単に頭の体操がしたいだけでしょうか?

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★回答者 No.1 です。 >私はビットシフトのことが完全に把握できていなかったので混乱してしまっていたんです。 >なので、アドバイス通りにまずは乗算からじっくり理解したいと思います。  ↑  それならもう少し演算についてアドバイスします。  まず最初に乗算する b の数はなぜ 2 のべき乗でないといけないのですか?  お聞きしたいです。もし、プログラミングを簡単に行うために限定しているのなら  2 のべき乗以外も掛け算できるように最終的にはするつもりなのでしょうか?  この辺はどう考えているのですか。 ・あとちょっと気になったのですが 8 ビットを1つの塊として加算、減算、乗算、除算を  実装していますよね。この一塊を 8 個の配列にセットして扱っていますが、これには何か  意図があるのでしょうか? ・普通なら unsigned char 型で 8 ビットを管理して演算するときは 2 倍の unsigned short 型  などで処理します。その後、8 ビットの配列× n 個に格納するようにします。  こういうのは俗に『多倍長演算』という考えです。 ・例えば『多倍長演算』という考えでの加算は下のサンプルのようになります。 サンプル: // 記号定数 #define LONGBITS (8) // 一度に扱うビット数 #define LONGMASK (~((~0UL) << LONGBITS)) // 一度に扱うビットマスクデータ(0xFF) // 型の再定義 typedef unsigned char LONGINT1; // 基本のデータ型 typedef unsigned short LONGINT2; // 基本のデータの倍の型 // 8 ビットを一塊とした n 個分の配列加算 int add( LONGINT ans[], LONGINT a[], LONGINT b[], int max ) {  LONGINT2 carry = 0;  int i;    for ( i = 0 ; i < max ; i++ ){   if ( (carry = (carry + a[i] + b[i])) > LONGMASK ){    ans[ i ] = (LONGINT1)(carry & LONGMASK);    carry = 1;   }   else{    carry = 0;   }  }  return (carry ? 1 : 0); // オーバーフローしたら 1 を返す } 説明: ・上記のサンプルは 8 ビットを1つの塊として max 個分の配列を加算する関数です。  8 ビットの加算では LONGINT1 a[1], LONGINT1 b[1], LONGINT1 ans[1]; と宣言して  add( ans, a, b, 1 ); として呼び出します。  64 ビットの加算では LONGINT1 a[8], LONGINT1 b[8], LONGINT1 ans[8]; と宣言して  add( ans, a, b, 8 ); として呼び出します。  800 ビットの加算では LONGINT1 a[100], LONGINT1 b[100], LONGINT1 ans[100]; と宣言して  add( ans, a, b, 100 ); として呼び出します。  ※いずれも戻り値はオーバーフローすれば 1 を返す事になります。  ※800 ビットの場合は 2 の 800 乗(0~6.668e+240)までの計算が行えます。 ・上記のサンプルを参考にすれば『多倍長整数演算』として何桁でも演算可能になります。  また、同じような考えで sub(減算)、mul(乗算)、div(除算)、shl(左シフト)、shr(右シフト)  の関数を作成して『多倍長整数演算ライブラリ』として用意するのも良いでしょう。 最後に: ・上記のサンプルでは 8 ビットを一塊として処理していますが、実際にはもっと多い 16、32 ビット  を一塊の単位として処理した方が計算速度が速くなります。また、i カウンタを用いずにポインタ  を使えばさらに早く演算できるようになります。増やすときは次のようにします。  ●16 ビットの場合  // 記号定数  #define LONGBITS (16) // 一度に扱うビット数  #define LONGMASK (~((~0UL) << LONGBITS)) // 一度に扱うビットマスクデータ(0xFF)    // 型の再定義  typedef unsigned short LONGINT1; // 基本のデータ型  typedef unsigned long LONGINT2; // 基本のデータの倍の型    ●32 ビットの場合  // 記号定数  #define LONGBITS (32) // 一度に扱うビット数  #define LONGMASK (~((~0ULL) << LONGBITS)) // 一度に扱うビットマスクデータ(0xFF)    // 型の再定義  typedef unsigned long    LONGINT1; // 基本のデータ型  typedef unsigned long long LONGINT2; // 基本のデータの倍の型  ↑  C99 規格に対応した long long 型が使えることが前提です。  未対応のコンパイラでは 32 ビットで使います。  ※ビット数を 16、32 に変更しても関数 add() の定義は書き換える必要はありません。  ※そのための記号的数、型の再定義を行っているのですから。 ・以上。

noname#47478
質問者

補足

申し訳ありません。私はほとんど初心者なので、情けないのですが、アドバイスいただいたような内容はまだ私にとっては難しすぎるんです。 私は自分で学習したところ(まだ初めて2ヶ月くらいですが)までの内容でどこまでできるかという挑戦で作り始めたので、この形で完成させてみたいと思っています。 >2 のべき乗以外も掛け算できるように最終的にはするつもりなのでしょうか? >この一塊を 8 個の配列にセットして扱っていますが、これには何か  意図があるのでしょうか? ↑ 2のべき乗以外で掛け算できるようにはしようとは思っていません。 上に書いたように初心者ですので、恥ずかしながら今のところは簡単にしようと思っています。一塊を 8 個の配列にセットして扱っているのは、そういう方法しか思いつかなかったので、そうしただけであって、特に意図はありません。 せっかく回答をいただいたのに自分勝手のことを言って申し訳ないです。

noname#50176
noname#50176
回答No.2

実際の処理はこんな感じかと思います。 #include <stdio.h> int nishin(int h[],int size,int a) { /*二進数の形に変換*/ for(int i=0;i<size;i++){ h[i]=a%2; a=a/2; } return 0; } int main(void) { int x[16],y[16],a,b,i,j,m,n,p,w,z; unsigned int size_8=8,size_16=16; puts("二つの符号なし整数を入力してください。(ただしa>bとし、bは2のべき乗の値とする)"); do{ printf("a=");scanf("%d",&a); printf("b=");scanf("%d",&b); printf("\n"); if (!(a&&b)) return 0; for(i=0x80,j=0;i;i>>=1) j+=b&i?1:0; }while(a<=b||(a|b)>0x100||a<0||b<0||j-1); // 入力条件を満たせば続きます puts("aとbをそれぞれ二進数で表すと"); printf("a="); nishin(x,size_8,a); for(i=size_8-1;i>=0;i--){ printf("%d",x[i]); } puts(""); printf("b="); nishin(y,size_8,b); for(i=size_8-1;i>=0;i--){ printf("%d",y[i]); } printf("\r\n"); for(j=0,m=a,n=b;j<8;j++,n>>=1) m=n&1?m<<j:m; printf("a*b=");//掛け算 nishin(x,size_16,m); for(i=size_16-1;i>=0;i--){ printf("%d",x[i]); } printf("\r\n"); for(j=0,p=m=a,n=b,z=0,w=0;j<8;j++,n>>=1,p>>=1) { m=n&1?m>>j:m; if (!(n&1) && !w) z|=(p&1)<<j,w=n>>1&1; } printf("a/b=");//割り算 nishin(x,size_16,m); for(i=size_16-1;i>=0;i--){ printf("%d",x[i]); } printf("\r\n"); printf("a mod b=");//余り nishin(y,size_16,z); for(i=size_16-1;i>=0;i--){ printf("%d",y[i]); } printf("\r\n"); printf("\r\nとなります。\n\n"); return(0); }

noname#47478
質問者

お礼

回答ありがとうございます!とても参考になりました。

関連するQ&A

  • 2進数の加算の繰り上がり

    2進数の四則演算のプログラムを作りたいと思い、2進数を表示するところまではできたのですが、加算になると繰り上がりという壁にぶつかってしまいました。繰り上がりや桁上げなどがよく分からないので、お教えください。(下のソースコードが繰り上がりのない加算をするまでのものです) #include <stdio.h> int main(void) { int a,b,i,j,x[8],y[8],z[8]; do{ puts("二つの符号なし整数を入力してください。(ただしa>bとし、bはのべき乗の値とする)"); printf("a="); scanf("%d",&a); printf("b="); scanf("%d",&b); if(a < = b) puts("入力した値がa>bになっていません。\a"); }while(a < = b); for( i = 0; i < = 7; i + +){ x[i] = a % 2; a = a / 2; y[i] = b % 2; b = b / 2; } puts("aとbをそれぞれ二進数で表すと"); printf("a="); for( i = 7; i > = 0; i - -){ printf("%d",x[i]); } puts(""); printf("b="); for( i = 7; i > = 0; i - -){ printf("%d",y[i]); } printf("となります。\n\n"); printf("<加算>\n"); printf("c=a+b="); for( j = 7; j > = 0; j - -){ z[j]=x[j]^y[j]; printf("%d",z[j]); } return(0); }

  • cプログラム

    #include<stdio.h> /*Calc MAX of (a,b)*/ int max(int x,int y) { if(x>y) return x; else return y; } /*Calc n!*/ void fact(int n) { int i,ans; ans=1; for(i=n;i>=1;i--){ ans*=i; } printf("ans=%d\n",ans); } /*END*/ void end() { printf("Thanks\n"); exit(0); } /*Main*/ int main() { int key; int a,b,saidai; int n; while(1){ puts("\n=====Main MENU ====="); puts("1.......max(a,b)"); puts("2.......n!"); puts("9.......END\n"); printf("Input No(1,2,9)=?"); scanf("%d",&key); switch(key){ case 1: printf("Inputs:a,b?"); scanf("%d,%d",&a,&b); saidai=max(a,b); //Call max(a,b) printf("max(%d,%d)=%d\n",a,b,saidai); break; case 2: printf("Input:n?"); scanf("%d",&n); fact(n); break; case 9: end(); break; default: printf("!!!!!Miss Input_No!!!!!\n"); break; } } のプログラムなのですが、1の処理を行った場合max(a,b)の値が正しく表示されません どこを直せばいいでしょうか? return(0);

  • 行列の積を関数を使って求める・・?

    2つの行列の行と列を入力し、積を計算するプログラムを関数を使って書きたいのですが、上手く行きません。どこをどのように直したらよいか教えてください!お願いします!! 以下が私が書いたプログラムです。 #include<stdio.h> #define NUMBER 10 int first(int x1,int x2,int y1,int y2,int i,int j,int k) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; do{ printf("2つの行列の行と列を入力してください\n"); scanf("%d", &x1); scanf("%d", &x2); scanf("%d", &y1); scanf("%d", &y2); if(x1 != y2){ printf("行列の積は計算できません\n"); } }while(x1 != y2); printf("行列Aの要素を入力してください\n"); for(i=0; i<x1; i++){ for(j=0; j<x2; j++) scanf("%d", &a[i][j]); } printf("行列Bの要素を入力してください\n"); for(j=0; j<y1; j++){ for(k=0; k<y2; k++) scanf("%d", &b[j][k]); } } int second(int x1,int x2,int y1,int y2,int i,int j,int k) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; for(i=0; i<x1; i++){ for(k=0; k<y2; k++){ for(j=0; j<x2; j++) c[i][k] = c[i][k] + a[i][j]*b[j][k]; } } for(i=0; i<x2; i++){ for(k=0; k<y2; k++) printf("%3d", c[i][k]); printf("\n"); } } int main(void) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; printf("行列の積を計算します\n %d\n", first(x1,x2,y1,y2,i,j,k)); printf("行列Aと行Bの積は\n %3d",second(x1,x2,y1,y2,i,j,k)); }

  • 10進数から2進数へ・・・

    10進数から2進数に変換するプログラムを作っています。a[i]=(x/2)%2という式をforでまわせば、できると思うんですが、a[i]の配列をどうやって表示させるのかわかりません、 main以下をのせときます。 int x; int i; float a[i]; printf("10進数を入力してください>"); scanf("%d",&x); a[i]=(x/2)%2; printf("2進数は%d\n",a[i]); }

  • c言語のプログラムで行列の積を計算する

    指定された行・列数(それぞれ10以下とする)の行列 X, Y の積 Z = X × Y を求めるプログラムを作成せよ.行列の要素はすべて整数とする. このプログラムで行と列の成分を入力するときに、1列になってしまうのですがどうしたらちゃんと入力できますか? int main(void) { double A[10][10]; double B[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } }

  • このプログラムの間違いを指摘していただけませんか?

    まだ、初めて一ヶ月も経たない者です。それでも、勉強しつつ、組んでみたのですが、うまくいきません。数字の足し算をして、結果を表示させたいのですが、四回足しても四回目の数字が、足されずに結果がでてしまいます。1と2と3と4と入力すると、6と出てきます。一体どのようにしたらよいのでしょうか?教えて頂けませんか?(下に書いてあります。) #include <stdio.h> int sub(int x, int y, int z){ return x + y + z; } int main() { int i; int a[i]; for (i=1; i<=1; ++i){ printf("数字は?\n"); scanf ("%d\n", &a[i]); scanf ("%d\n", &a[i+1]); scanf ("%d\n", &a[i+2]); scanf ("%d\n", &a[i+3]); int result,x,y,z; result = sub(a[i],a[i+1],a[i+2]); printf("結果は%d\n",result); } return 0; }

  • c言語で行列の積の値を求める

    行列の成分を入力した後に、 入力された行列は X = 1 2 3 4 5 6 7 8 9 10 11 12 Y = 1 5 2 6 3 7 4 8 のように表示して、(上の数字は適当です。) 行列 X と行列 Y の積を求めて結果を表示するプログラムが作りたいのですが、上手く表示できなくて困っています。 #include <stdio.h> int main(void) { double A[10][10]; double B[10][10]; double C[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } } この後にどうすればいいのか教えてください。 よろしくお願いします。

  • C言語 プログラミングで行詰まりました…

    標準入力(キーボード)からi,jk,nの値を入力し、次の漸化式を計算し、X_0からX_nまで求めるプログラムを作成したいのですが、うまく表示されません。どかがおかしいのかご指摘お願いします。 <漸化式> X_n=(a+b)/X_(n-1) , X_0=c(n=0) ================================================================== #include<stdio.h> float f_X(int a,int b,float c) { float y; y=(a+b)/c; return y; } int main (void) { int number,i,j; float k,l,n,X; printf("i:"); scanf("%d", &i); printf("j:"); scanf("%d", &j); printf("k:"); scanf("%f", &k); printf("n:"); scanf("%f", &n); X=k; printf("X_0= %.6f\n",X); for(number=1;number<=n;number++) { l=f_X(i,j,X); printf("X_%d= %.6f \n",number,l); X=l; } return 0; } ===================================================================

  • if文について

    ソートのプログラムにおいて昇順・降順を選択して表示させるプログラムを書いてるのですが 下記のように記述するとエラーが出てしまいます。 よく調べたのですがエラー表示もよくわからないものなのでした。 どのようにすればうまく動くようになるのでしょうか? #include <stdio.h> #define swap(type, x, y) do {type t = x; x = y; y = t; } while (0) void bubble(int a[], int n) { int i, j; for (i = 0; i < n - 1; i++) { for (j = n - 1; j > i; j--) if (a[j - 1] > a[j]) swap(int, a[j - 1], a[j]); } } void bubble2(int a[], int n) { int i, j; for (i = 0; i < n - 1; i++) { for (j = n - 1; j > i; j--) if (a[j - 1] < a[j]) swap(int, a[j - 1], a[j]); } } int main(void) { int i; int x[7]; int nx = sizeof(x) / sizeof(x[0]); int select; printf("%d個の整数を入力せよ。\n", nx); for (i = 0; i < nx; i++) { printf("x[%d] : ", i); scanf("%d", &x[i]); } printf("昇順ですか降順ですか? 0:昇順/1:降順 >"); scanf("%d",&select); if (select == 0) bubble(x, nx); puts("昇順にソートしました。"); for (i = 0; i < nx; i++) printf("x[%d] = %d\n", i, x[i]); else bubble2(x, nx); puts("降順にソートしました。"); for (i = 0; i < nx; i++) printf("x[%d] = %d\n", i, x[i]); return (0); }

  • 配列の要素数に変数を入れたい

    配列に数の入力履歴を入れて最後にその数を出力したいのですが、変数を入れることはできないと勉強した記憶がありまさにその通りコンパイルエラーが出ました。 他に何か方法はありませんでしょうか。 /* 課題1-3 */ #include <time.h> #include <stdio.h> #include <stdlib.h> #include <math.h> int main(void) { int i; int no1; /* 範囲1 */ int no2; /* 範囲2 */ int max; /* 大きい乱数 */ int min; /* 小さい乱数 */ int y; /* 当てさせる数 */ int stage; /* 入力回数 */ int x; /* 読み込んだ値 */ int n; /* 入力制限 */ srand(time(NULL)); no1 = rand(); no2 = rand(); if(no1 > no2){ max = no1; min = no2; } else{ max = no2; min = no1; } y = min + rand() % (max-min); n = ceil(log(max-min)/log(2)); int a[n]; /*←配列の要素数をn個にしたい*/ printf("%d以上%d以下の整数を当ててください。\n", min, max); stage = 0; do{ printf("残り%d回。いくつでしょう:\n", n - stage); scanf("%d", &x); a[stage++] = x; if(y > x) printf("小さいです。\n"); else if(y < x) printf("大きいです。\n"); }while(y != x && stage < n); if(y != x) printf("残念でした。正解は%dです。", y); else printf("正解です。%d回目で正解しました。", stage); puts("\n---入力履歴---"); for(i=0; i<stage; i++) printf("%2d : %4d %+4d\n", i+1, a[i], a[i] - y); return (0); }

専門家に質問してみよう