• ベストアンサー

配列とポインタでの書き直しその2

配列とポインタでの書き直し(c++)その1 のつづき cout << endl; cout << setw(5) << "Sum" << setw(12) << "Number" << setw(14) << "Probability" << setw(10) << "Error" << endl; cout << "-----------------------------------------" << endl << endl; cout << setiosflags(ios::fixed | ios::showpoint); for (int k = 0; k <= 10; k++) { probability = static_cast<double>(sum[k])/throws; cout << setw(4) << k+2 << setw(12) << sum[k] << setprecision(6) << setw(14) << probability << setprecision(2) << setw(11) << getError(probability, k, error) << endl; } return 0; } // Roll two dice. int rollDice() { int dice1, dice2; dice1 = rand()%6 +1; dice2 = rand()%6 +1; return (dice1 + dice2); } // Example: for error dice 12 // // prob = sum[10] / throws, // // // |prob - e[10]| // error = ----------------- x 100 // e[10] // double getError(double p, int i, double e[]) { return ((fabs(p - e[i])/e[i])*100); } 関連URL: http://www.okweb.ne.jp/kotaeru.php3?q=243537

  • lilno
  • お礼率22% (6/27)

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

  • ベストアンサー
  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.5

switch文をどこで使うか、見えてきませんでしたのでこの部分は割愛しますが、プログラム自体をもっとすっきりさせてみましょう。 処理のサブルーチン化です。現在メインの中にあるサイコロを指定回数分転がすところですが、これを  rolling (int* sum, int throws) として作ればポインタの課題はクリア、プログラムも見やすくなると思います。 また、結果を表示するとき、確率とエラー(?)の計算をやりながら出力していますが、これも予め別の配列をそれぞれ用意して、別のサブルーチン内で計算するようにしてみてください。 そうすると main関数内は main {  int sum[11];  double error[11], probability[11];  初期化処理();  rolling (sum, throws);  // サイコロを指定回数転がす  calc_prob (probability, sum, throws);  // 確率計算  calc_error (error, probability);  // エラー計算  結果表示処理(); } のようにすっきりすると思います。

その他の回答 (5)

  • onosuke
  • ベストアンサー率67% (310/456)
回答No.6

おおっと。よくみたら,ちゃんとポインタ使ってますね。 << getError(probability, k, error) << endl; このgetErrorの引数 error が,配列 error[] の先頭のアドレスを示すポインタになっています。ということは,課題として,もとから問題はなかった!! 配列 arrayを関数に渡す際は,値渡し value argument ではなく,参照渡し reference argument を使わねばならない。って,やつです。 しかし,課題の意図としては,'sum' を同じような形で,ポインタとして扱って欲しかったように思います。 yatokesaさんのご意見では,ちょうどそのような形になりますね。 > A CASE statement for the count of the number of times that a given sum occurs. これなら,あのswitch文もしょうがないですね。お上には逆らえません。 ん~でも, [Practice Exam. Q-2] Replace the SWITCH block as a 1-line-statement. とか,やはりあって欲しいなぁ。

  • zzzzzz
  • ベストアンサー率61% (70/113)
回答No.4

そもそも宣言以外では一次元配列とポインタは同じものだと思いますが。 無理矢理書き換えるなら array_name[index] を全て *(array_name+index) に変えれば(例:sum[i]を*(sum+i)に変える)変えたと言えなくもないかな、という程度でしょう。 それよりも、他の部分に課題があります。 ・「エラー」と書かれているが、error(誤差)の誤訳と思われる ・変数の名前付けに問題が多い(sumが回数を表したり、errorが確率の理論値を表したり) ・変数の名前付けが危ない(throwが予約語だと知ってthrowsという名前を付けているのか) ・基本型のstatic_castは明示の必要はない。(((double)sum[k])/throwsで十分) ・相対誤差を算出するgetError()関数の機能分離が不完全(iとeの両方を引数にするのは論理的におかしい。e[i]を引数にすべき) なお、sumの初期化は、memset()を使用するとすっきり書けます。

noname#30727
noname#30727
回答No.3

for などの繰り返し処理を、ポインタと++演算子を使ってアクセスせよという課題なのだとは思いますが、もう少し先読みすると、設計力を問われているような気もします。 1つの関数の守備範囲を単純化していく事を考えると、今は main 関数だけが長いですが、初期化関数、入力関数、ダイスを振ってサムを更新させる関数、結果の表示関数などに分割する事でプログラムは読みやすくなります。その結果、引数にもポインタを使う事になるはずです。

  • sssohei
  • ベストアンサー率33% (33/98)
回答No.2

正直、何をしたいのか?何がわからないのか?がさっぱりわかりません。 問題を絞ってください。 下の方もかかれているので繰り返すのも何ですが、 errorへの代入やsumのインクリメントは一文にするべきです(みやすい、バグを出しにくい(修正しやすい)) まぁ、どつぼにはまることもありますが(範囲外アクセスなど、注意しないといけませんが) C/C++の場合配列名が、その配列の先頭へのポインタとして利用できます。 int array[10]; 中略 *(array+0) = 0 /* array[0] = 0 と同じ */ *(array+1) = 1 /* array[1] = 1 と同じ */ 後、throws という変数名は紛らわしいのでやめた方がいいと思います(throwが予約語です。かといってtryも予約語ですが、、、countじゃわかりにくいですか?(指定されてたらよけいなお世話なんですが

  • onosuke
  • ベストアンサー率67% (310/456)
回答No.1

ポインタは教科書やWebで「配列をポインタに置き換える方法」を調べれば,すぐに分かるでしょう。 それよりも, switch(roll) { .... } を sum[roll-2]++; に置き換えることができます。 こちらのほうが,ポインタより重要かも。

lilno
質問者

補足

補足なのですが、この課題では A CASE statement for the count of the number of times that a given sum occurs. と書かれてあり、SWITCH を授業で習ったので、絶対使わないといけないらしいのですが、私自身もなんだか読みにくいプログラムになってしまったなぁって思っております、、、。その部分をSWITCHの別の使い方とかであてがうことはできないんでしょうか?case の使い方私のようなやりかたで正解なのでしょうか?

関連するQ&A

  • 角度の計算(C++)

    Theta cos(theta) sin(theta) 0.0    1.00     0.00 .    .     . .    .     . 上のような表示ができるプログラムを書いてます。角度は0度、5度、10度、15度、、、と5度毎に表示させないといけません。表示角度は角度は0-360度までです。 下のように書いてみましたがエラーが出てしまいます。何が問題なんでしょうか? int main(){ const double PI = 3.1415; double r = PI /180; cout<<setw(5)<<"theta"<<setw(13)<<"cos(theta)"<<setw(13)<<"sin(theta)"<<endl; for( int theta=0; theta<=360; <<theta += 5) cout<<setw(5)<<setprecision(1)<<(double)theta <<setw(14)<<setprecision(2)<<sin(theta * r) <<setw(10)<<cos(theta * r)<<endl; return 0; }

  • 配列とポインタでの書き直し(c++)その1

    2つのサイコロの合計と、回数、確率、エラーを配列を使って表示する課題に取り組んでいます。配列を使っては何とかできましたが、課題では配列とポインターの両方を使ってこれを書かなくてはいけません。ポインターに関しては本を読んでも実際応用できないので困っています。ポインターについてわかる方、ヒントください。  ちょっと長いので2つに分けて掲示します。(みにくくてごめんなさい!) #include<>....省略 int rollDice(void); double getError(double, int, double []); int main(void) { int sum[11]; double error[11]; int throws; double probability; error[0] = 1.0/36.0; error[1] = 2.0/36.0; error[2] = 3.0/36.0; error[3] = 4.0/36.0; error[4] = 5.0/36.0; error[5] = 6.0/36.0; error[6] = 5.0/36.0; error[7] = 4.0/36.0; error[8] = 3.0/36.0; error[9] = 2.0/36.0; error[10] = 1.0/36.0; srand((unsigned) time(NULL)); for (int i=0; i<11; i++) sum[i] = 0; cout << "\n何回サイコロを転がしますか?: "; cin >> throws; for (int j= 0; j<throws; j++) { int roll = rollDice(); switch(roll) { case 2: sum[0]++; break; case 3: sum[1]++; break; case 4: sum[2]++; break; case 5: sum[3]++; break; case 6: sum[4]++; break; case 7: sum[5]++; break; case 8: sum[6]++; break; case 9: sum[7]++; break; case 10: sum[8]++; break; case 11: sum[9]++; break; case 12: sum[10]++; break; } } 配列とポインタでの書き直し(c++)その2 につづく

  • C++言語の非常に初歩的な質問(数表)

    今、C++言語を勉強中です。 そこで数表を作るみたいな例題があるのですがどうしても思ったとおりになってくれません。 いろんなことを考えましたが自分の力ではどうにもなりません・・・・。 そこで間違いがあれば指摘していただけたらと思い質問させていただきます。 以下がそのプログラム?です。よろしくお願いします。 #include<iostream.h> #include<math.h> #include<iomanip.h> main() { int n ; double n3 , n5; cout << setw(5) << "n" << setw(10) << "1/n" << setw(10) << "n^1/3" << "\n"; cout << setiosflags(ios::fixed); for(n=1 ; n<=25 ; ++n) { n3=1/n ; n5=pow(n,1/3) ; cout << setw(5) << n << setw(10) << setprecision(5) << n3 << setw(10) << setprecision(5) << n5 << "\n" ; } return 0 ; }

  • C++でのeの近似値の求め方

    問題はeの値は次の近似式で求めることができる。 e=1+1/1!+1/2!+1/3!+...+1/(n-1)!+1/n! nの値を12としてeの近似値を求めるプログラムを作成せよ。 <出力形式>  n n! 1/n! e 誤差  1 1 1.0000000000 2.0000000000 0.7182818285 2 2 0.5000000000 2.5000000000 0.2182818285 . . . . . 12 <小数点以下10桁まで表示> が問題なんです。 ヒントとして <1から25までの合計> #include<iostream.h> #include<imanip.h> main() { int k,sum; sum=0; for(k=1;k<25;++k) {sum+=k; cout<<setw(5)<<k <<setw(7)<<sum<<"\n";} return 0; } これと <nの階乗を求める> #include<iostream.h> #include<imanip.h> main() {   int n,k,ki(1); cout <<"nの値は?==>";cin>>n; for (k=1;k<=n;++k) { ki*=k; cout<<setw(5)<<k <<setw(12)<<ki<<"\n";} return 0; } がヒントとして与えられているんです。この2つをうまく使ったら良いよって言われたんですけどよく考えてもわからないんです。どなたかこの問題を解ける人がいたら教えてください。お願いします。

  • 配列受け渡し

    要素数nであるint型配列xから値がkである要素の添え字を返却する関数(ただし、値がkである要素が存在しなければ-1を返却するものとし、そのような要素が複数存在する場合は、先頭側の最も小さい添え字を返却する)を作成しています。 #include<iostream.h> #include<iomanip.h> int search(int x[],int n,int k) { int i,j; int result=-1; for(i=0;i<n;i++){ if(x[i]==k){ result=i; return(result); } else return(-1); } } int main(void) { const int ninzu = 5; int height[ninzu]; cout << ninzu << "要素:\n"; int i; for (i = 0; i < ninzu; i++) { cout << setw(2) << i+1 << "番目:"; cin >> height[i]; } cout << "検索要素は?:"; int target; cin >> target; int result=search(height, ninzu, target); if(result==-1) cout<<"ないよ"<<endl; else cout<<result+1<<"番目が"<<target<<endl; return (0); } このようにしたのですが、うまくいきません。また、複数の要素が発生したときの返却の仕方がわかりません。 どなたかアドバイス等よろしくお願いします。

  • C++で,配列に計算した値を入れたいです.

    C++で疑似乱数を発生させてサイコロをつくったのですが, サイコロを5回転がしたときのそれぞれの値をソートしたいと思い,配列に入れれば簡単だと考えてとりあえず配列に入れるプログラムを書いてみました. しかし,int array[i] = Dice(); のところでエラーが出てしまいます. ローベルのC++入門講座という本を使って独学で勉強している初心者なため,配列の使い方がいまいちよくわかりません. ご教授よろしくお願いします. 以下ソースコード #include <iostream> #include <cstdlib> #include <ctime> using namespace std; void InitRand(){ srand((unsigned int) time (NULL)); } int Dice(){ return rand() % 6 + 1; } int main(void){ int n = 0; //nはサイコロを転がす回数 cout <<"サイコロを何回転がしますか?" << flush; cin >> n; cout << "回転がします" << endl; InitRand(); for(int i = 0; i < n; ++i){ cout << Dice() << endl; int array[i] = Dice(); //エラーが発生する.i回目のサイコロの値をi番目の配列に入れたい. } }

  • C++で乱数を重複しないように発生させる

    C++で乱数を重複しないように発生させるようにプログラムを変更しろと言われたのですが、できません。 教えていただきたいです。 #include<iostream> #include<cstdlib> #include<cstring> #include<ctime> using namespace std; int main() { int i,n; int *p; cout<<"何個記憶しますか?"<<endl; cin>>n; p=new int[n]; if(p==NULL){ cout<<"記憶域の確保に失敗しました。"<<endl; return 1; } srand((unsigned)time(NULL)); rand(); i=0; while(i<n){ p[i]=1+(int)((double)rand()/(RAND_MAX+1.0)*75); if(p[i]==p[i]) cout<<"p["<<i<<"]の値"<<p[i]<<endl; i++; } delete[] p; return 0; }

  • 初心者です。エラーが分かりません。

    エラーが二つ出てしまいます。 自分ではよく分からなく、図々しく質問しました。 誰か助けてください。 #include<iostream> using namespace std; double fan(double,double angle=360.0); /* angleはデフォルト360 */ double fan(double r, double angle){ return 3.1415926*r*r*angle/360.0; /* 面積を返す */ } int main(void){ double r,angle; cout << "半径を入力してください。 : "; cin >> r; cout << "角度を入力してください。 : "; cin >> angle; cout << "半径 : " << r << " 角度 : " << angle << endl; cout << "面積 : " << fan(r,angle) << endl << endl; cout << "半径 : " << r << " の円なら" << endl; cout << "面積 : " << fan(r) << endl; return 0; }

  • char型配列について

    基本的なことですが、 char str[5]="Hello"; --> str[0]='H' str[1]='e' str[2]='l' str[3]='l' str[4]='o' str[5]='\0' では、ないのでしょうか? エラーが出ます。 //error C2117: 'str' : 指定された配列には、初期化子が多すぎます。 char str[6]="Hello"; では、コンパイルできます。 ---------------------------------- また、 #include<iostream> using namespace std; int main() { char str[6]="Hello"; cout << str << endl; for(int i=0;i<7;i++) { cout << "i=" << str[i]; if(str[i]=='\0'){cout << " NULL" << endl;} else{cout << endl;} } getchar();return 0; } ----------------------------------------------- とすると、 Hello i=H i=e i=l i=l i=o i= NULL <--ここで、NULLなら、 i=フ <--このぶんは、いらないと思うのですが、、、 となります。 str[6] i=6 は、何を意味するのでしょうか? Visual C++ NET を使用しています。 よろしくお願いします。

  • 下記、プログラム内の「char *」の役割

    C++初心者です。 縦長になってしまいますが、 『 #include <iostream.h> void show(int); void show(double); void show(char *);   ←左記の記述の使い方 int main(void) { show(1); show(0.25); show("文字列"); return 0; } void show(int x) { cout << x << endl; } void show(double y) { cout << y << endl; } void show(char *z) { cout << z << endl; } 』 のプログラムにおいて、「char *」の使い方がいまいち理解できません。 上記プログラムですとエラーが表示されないのですが、下記のプログラムだとエラーが発生します。 『 #include <iostream.h> void show(int); void show(double); void show(char);   //←---------上記と違う行 int main(void) { show(1); show(0.25); show("文字列"); return 0; } void show(int x) { cout << x << endl; } void show(double y) { cout << y << endl; } void show(char z) {  //←---------上記と違う行 cout << z << endl; } 』 なぜ、ポインタ(*)を付けないといけないのか分かりやすく教えていただけましょうか。