• ベストアンサー

繰り返しのプログラム

自作関数stress1とstress2を使用した時の繰り返しのプログラムです。 実行はできるのですがyとzの値が変化が現れずに表示されてしまいます。自作関数を使わずにfor文の中に計算式を入れた場合はきちんと変化して値が表示されます。 自作関数を使用した場合の繰り返しはどうしたら良いのでしょうか? int main(void) { double v,w,x,y,z; printf("W0="); scanf("%lf",&w); printf("W1="); scanf("%lf",&x); for (v=w; v<=x; v+=100) { y= stress1(v); z= stress2(v); printf("σ1=%lf,σ2=%lf\n",y,z);  } return 0; }

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

  • ベストアンサー
回答No.1

C言語には、ローカル変数とグローバル変数というものがあります。最初に習ってるうちはローカル変数しかでてきません。ローカル変数というのは、関数内(および関数の引数として)で宣言された変数です。その関数内でしか使用できません。グローバル変数は関数の外で宣言された変数でどの関数でも使用できます。 ですから、自作関数を使用した場合、渡した引数はその関数の処理が終わると消えてしまいます。要するに、元の関数(main関数など)では、変化が現れないわけです。そこでポインタの登場ですね。 ポインタ変数を*pとすると、そのアドレスの値を変えることができます。メモリ上のアドレスの値を変えてしまうので、当然、もとの変数の値もかわります。以下、プログラム例を示します。 void kansu(int *, int *); int main(void) {   int num = 1, num2 = 2;   kansu(&num1,&num2) // &は住所を渡す際の記号   printf("%d %d\n",num1,num2);   return 0; } // 値を交換する関数 void kansu(int *p, int *p2) {   int a;  //交換のためには変数が3つ必要   a=*p;   *p=*p2;   *p2=a; } なお、上記ソースはint変数num,num2の値を交換するプログラムです。 また、スペースには全角を使っているので、コンパイルするとエラーになりますので、ご注意を。 ポインタのアドレスを渡すときは&記号を使い、そのアドレスの変数を変えたり見たりする時は*記号を使います。難しいといわれてますが、それだけです。なぜポインタと大騒ぎされるのか理由がさっぱりわからないです(これ本当)。では、がんばってください。

その他の回答 (6)

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

★回答 ・回答者 No.2 さんの補足から、関数の戻り値の型が double 型が正しいのに質問者さんは  int 型で定義しています。→このため、回答者 No.5 さんの補足で小数点以下がカット  された『σ1=3.000000』、『σ2=2.000000』が続くのです。 ・自作関数を使用しない場合が正しく『σ1=2.057815』、『σ1=2.062388』、『σ1=2.066961』  と変化したのは double 型の小数点以下をカットしなかったからです。  つまり、自作関数の 『stress1』、『stress2』関数の戻り値が int 型なので小数点以下を  カットされて正しく出来なかったのです。→回答者 No.6 さんの回答どおりですね。 正しくは: double stress1( double v ) {  double ans1;    ans1 = v * E / (A * E + a * e);  return ans1; } double stress2( double v ) {  double ans2;    ans2 = v * e / (A * E + a * e);  return ans2; } 最後に: ・コンパイラの警告レベルを一番高く設定すれば、今回のミスは未然に防げます。  つまり、戻り値が int 型なのに double 型をリターンしようとしているので、ここで警告  メッセージが出るのです。→もし本当に int 型でリターンしたい場合はキャストします。  『return (int)ans1;』という感じです。 ・よって、オプション設定などを見直して下さい。 ・私は警告レベルを一番高く設定していますので、今回のようなミスはコンパイラさんから  ときどき教えてもらいます。→さすが構文解析をちゃんと行ってコンパイルしているだけある! ・という訳で一度オプション設定を変更してみましょう。 ・以上。おわり。

ykiyki
質問者

お礼

ありがとうございます。 おかげでちゃんとしたプログラムが出来ました。 コンパイラの警告レベルの設定の設定があるのも知りませんでした。。 これから設定してプログラムを作っていきたいと思います。

  • taunamlz
  • ベストアンサー率20% (175/843)
回答No.6

int stress1(double v) ここがおかしいと思います。 戻り値の double ans1; がdoubleなのですから、 double stress1(double v) とすべきだと思います。 int stress2(double v) も同様です。

ykiyki
質問者

お礼

ありがとうございます。 きちんと動きました。

noname#38837
noname#38837
回答No.5

No.4の回答者さんがおっしゃるように stress1()とstress2()のリターン値が間違っているというのが一番考えられそうですが 各自作関数の内容と、 >yとzの値が変化が現れずに表示されてしまいます >計算式を入れた場合はきちんと変化して値が表示されます の実際の表示例を示していただけるとなにか糸口がつかめるかもしれません また >for (v=w; v<=x; v+=100) { のwとxには何が入っていますか? 何を入れても不具合は同じですか?

ykiyki
質問者

補足

例えばwには45000、xに65000を入れるとσ1=2.000000 σ2=1.000000 w=65000,x=85000とするとσ1=3.000000 σ2=2.000000 が続きます。 自作関数を使用しない場合、45000と65000とすると σ1は2.057815 2.062388 2.066961と変化していき、σ2も同様に変化しています。

  • PG_RankB
  • ベストアンサー率40% (12/30)
回答No.4

ゲームプログラマやソフトウェアエンジニアしています。 既出ですが、stress1とstress2と言う関数の中身が見れないと答えようが無いですね。 ただし、yとzが変化しないとあるので、それらは関数の戻り値格納用の様ですし、stress関数の中で何らかの計算をした結果をきちんとreturnしていないのでは無いかと思いますが。

回答No.3

ちょっと訂正。 「ポインタ変数を*p」というのは、本当は変数名はpです。*はポイントしてくれって言う命令です。ポインタ変数の宣言は以下のとおりです。 int *p; しかし初心者にわかりやすくいうと (int *)p; って感じになります。まぁ、細かいことは気にせずにどんどんプログラムを組んでください。一種の約束事ですので、どうしようもありません。C言語の規約を作っているアメリカの協会に文句をいうしかないです。要するに、「こう書け!」という約束事ですね。 がんばってください。 **************************以下、余談************************* void kansu(int a, int b); int main(void) {   int num=1, num=2;   kansu(num1, num2);   printf("%d %d\n", num1, num2);   return 0; } void kansu(int a, int b) {   int temp;   temp=a;   a=b;   b=temp; }  // int 変数a, b, tempはローカル変数(関数内変数)ですので、kansuが終わった時点でメモリから消滅します。よって、main関数内の変数にはなんら変化があらわれません。kansu関数のa,bとmain関数のnum1,num2は別の変数であり、関連性はありません。 がんばってくだあし。

ykiyki
質問者

お礼

ポインタ変数の意味が今まで分からなかったのですがkamkamkam3さんのおかげで理解できました。 プログラムを作るときは注意してやりたいと思います。

noname#26650
noname#26650
回答No.2

>自作関数stress1とstress2 これらの関数の中身がわかれば、何かがわかるかもしれません。 現在は、これらの関数がブラックボックス状態であるため、 何も回答できません。

ykiyki
質問者

補足

自作関数はこう作りました。 アドバイスよろしくお願いします。 #include <stdio.h> #define E 21000 #define e 12500 #define A 7850 #define a 23550 int stress1(double v) { double ans1; ans1=v*E/(A*E+a*e); return ans1; } int stress2(double v) { double ans2; ans2=v*e/(A*E+a*e); return ans2; }

関連するQ&A

  • 3つの整数が等しいかどうか調べるプログラム

    3つの整数が等しいかどうか調べるプログラムがよくわからないので、どなたか教えていただけないでしょうか?ちなみに、わからないながらに作ってみました。 #include <stdio.h> int main(void) { int x, y, z; puts("3つの整数を入力してください。"); printf("整数1:"); scanf("%d",&x); printf("整数2:"); scanf("%d",&y); printf("整数3:"); scanf("%d",&z); if (x==y==z) puts("3つの整数の値は同じです。"); else puts("3つの整数の値は違います。"); return (0); }

  • C言語のプログラミングがうまくいきません!

    先日のプログラムを作り直しました。アドバイスのおかげでエラーは減りましたが、まだ完ぺきではないようです。恐らく、elseのところがいけないと思うのですが、どうしたらいいか分かりません。 ご指摘お願いします。 #include <stdio.h> #include <math.h> void main(void) { double x ,y ,z ,error ,menseki ; double ans; printf("x ?"); scanf("%lf", &x); printf("y ?"); scanf("%lf", &y); printf("z ?"); scanf("%lf", &z); if(x<y+z || y<x+z || z<x+y) { ans=(x+y+z)/2; menseki=sqrt(ans*(ans-x)*(ans-y)*(ans-z)); } if(x==y && y==z && z==x) { printf("正三角形です"); printf("面積は%lfです" , menseki); } else if(x==y || y==z || z==x) { printf("二等辺三角形です"); printf("面積は%lfです" , menseki); } else { printf("三角形です"); printf("面積は%lfです" , menseki); } else { printf("error"); } }

  • プログラムの作成

    Cで、キ-ボ-ドから整数を1個(mとする)、実数を1個(xとする)それぞれ入力し、 S=Σ(n=0からmまで)1/2n+1×(x-1/x+1)^2n+1 の値を求めるプログラムを作ってみたのですが、あってるかどうかわかりますか? #include<stdio.h> #include<math.h> main() { double y=0; int i,m,x; printf(\" Input m: \") scanf(\"%lf\", &m); printf(\" Input x: \") scanf(\"%lf\", &x); for(i=0; i <= m; i++) { y += 1/(2*i+1)*pow((x-1)/(x+1),2*i+1) } printf(\" S = %d\n\", y) }

  • C言語のプログラムについて質問

    明解C言語という書籍に 大きい方を表示するプログラム #include <stdio.h> int maxof(int x, int y) {  if (x > y)   return (x);  else   return (y); } int main(void) {  int na, nb;  puts("二つの整数を入力してください。");  printf("整数1:"); scanf("%d", &na);  printf("整数1:"); scanf("%d", &na);  printf("大きいほうの値は%dです。\n", maxof(na, nb));  return (0); } の関数maxofを利用し、 int max4(int w, int x, int y, int z) {  return (maxof(maxof(w, x), maxof(y, z))); } を挿入して変えれば四つの整数から最大値を求められるとのことですが、 コンパイルがうまくいきません。 関数maxofのwとx,yとzをそれぞれ比較し最大値を求めてさらにmaxof(w, x)とmaxof(y, z)を比較して最大値を求めるということですよね?ですので、 maxof(w, x) {  if (w > x)   return (w);  else   return (x); } maxof(y, z) {  if(y > z)   return (y);  else   return (z); を挿入しようとしたらmaxofはすでにありますというようなことが表示されてだめでした。 また、 int maxof(maxof(int w, int x), maxof(int y, int z)) { if (w > x)   return (w); if (w < x)   return (x); if (y > z)   return (y); if (y < z)   return (z); if (maxof(w, x) > maxof(y, z))   return (maxof(w, x)); if (maxof(w, x) < maxof(y, z))   return (maxof(y, z)); } としてみましたがやはりだめでした。 前のページの説明を読み返したりネットで調べてもわかりませんでした。 何がわからないのかがわからないのでもうお手上げです。 長くなってすいません プログラム例と説明をお願いします。

  • 構造体の自作関数内で入力した値の返し方

    こんばんはm(_ _)m C言語の構造体に関する質問です。 (当方初心者なので用語等見苦しい点があると思いますがご了承&指摘をお願いします。) 日付を元号に直したりする構造体のプログラムでmain関数ではなく自作関数内で値を入力する問題を解いていまして… #include<stdio.h> typedef struct{ int year; int month; int day; }date; date put_date(date x) /*ここで日付を入力*/ { date x;       printf("年:"); scanf("%d",x.year); printf("月:″); scanf("%d",x.month); printf("日:"); scanf("%d",x.day); return x; } int main(void) { date x; x.year=0; /*問題では関数外で宣言した変数では足りないため         に他の自作関数で変数を使いまわすために必要な処         理で初期化しました。*/ put_date(x);     gen(x); /*西暦の日付を元号で表す自作関数でここへput_date        で取得したx,y,zを送りたいのですがmainに来た時点        でput_dataで入力した値が出ませんでした。(元号に        直す関数は省略いたしました)*/ } put_date内でprintfしましたところx,y,zの値が入力した通りに出ましたが、main内ではx.year=0,x.month=12,x.day=0という値になってしまいます。 put_dateで入力した値をmain関数内だけでなく他の自作関数内でも使用したいのですがどうすればよろしいでしょうか?

  • C言語のプログラムについて

    三角形を判定するプログラムを作ったのですが直角三角形ができるはずがないのに直角三角形の判定が出てしまいます。簡単なことなのかもしれませんが自分ではわからなくなってしまったのでご指摘してもらいたいです。 #include<stdio.h> void tri(int x,int y,int z) { if((x*x==y*y+z*z)||(y*y==x*x+z*z)||(z*z==x*x+y*y)) { printf("これは直角三角形です。"); printf("これは三角形です。"); }else if((x+y>=z)||(x+z>=y)||(y+z>=x)) { printf("これは三角形ではありません。"); }else{ printf("これは三角形です。"); } } int main(void) { int e1,e2,e3; printf("3辺を入力してください"); scanf("%f,%f,%f",&e1,&e2,&e3); tri(e1,e2,e3); return(0); }

  • γ関数のプログラム(初心者です)

    以下のようにγ関数のプログラムを組みました。 とりあえず整数値を入力すれば、正しい値は返しているということがprintfの4で確認できました。 もとはfortranで組んだプログラムをCに置き換えました。 ですが、実際走らせてみると、4で値は確認できますがsegmentation faultが出てしまいます。 ですからサブルーチンファイル(ユーザー関数?)として利用できません。 何がいけないのでしょうか? 正しくyが帰ってくるようにどうなおしたらよいのか教えてください。 #include <stdio.h> #include <math.h> double gamma(double x) { double c[8],y,a,r,b,s; int i; a=1.; r=1.; c[1]=5.771916e-01; c[2]=9.882058e-01; c[3]=8.970569e-01; c[4]=9.182068e-01; c[5]=7.567040e-01; c[6]=4.821993e-01; c[7]=1.935278e-01; c[8]=3.586834e-02; printf("0 %f\n",x); while(1){ if(x>2.){ x=x-1.; a=a*x; printf("1 %f %f\n",x,a); } else if(x<1.){ a=a/x; x=x+1.; printf("2 %f %f\n",x,a); } else{ break; } } x=x-1.; for(i=1;i<8;i++){ b=(double)(i); s=(c[i]*((double)(pow(-1,b))) *((double)(pow(x,b)))); printf("3 %d %f\n",i,c[i]); r=r+s; } y=a*(r+(0.03586834*((double)(pow(-1,8)))*((double)(pow(x,8))))); printf("4 %f\n",y); return y; } main() { double x,y; printf("数字を入力してください。"); scanf("%lf",&x); printf("メインプログラム %lf\n",x); y=gamma(x); printf("%f\n",y); }

  • 二分法のプログラムについて

    下の用なプログラムを作ったのですがどうしても正しい答えを導くことができません。自分でもいろいろ調べてみましたがわかりません。誰かご教授宜しくお願いします。 #include<stdio.h> #include<stdlib.h> #define MAX 10 int n , count; double c[MAX+1]; double a,b,e; void nyuuryoku(void) { int i; printf("nの入力>"); scanf("%d",&n); if(n>MAX){printf("最大次数を超えている");exit(1);} else if(n<0){printf("nが負");exit(2);} else{for(i=0;i<=n;i++){printf("係数の値>");scanf("%lf",&c[i]);} }} double f(double x) {double y; int i; y = c[0]; for(i=1;i<=n;i++){ y=y*x+c[i];} return y; } void hani(void){ printf("aの値>");scanf("%lf",&a); printf("bの値>");scanf("%lf",&b); printf("eの値>");scanf("%lf",&e); if(e<=0){printf("eが0または負"); exit(3);} if(f(a)==0){printf("%f",f(a)); exit(4);} if(f(b)==0){printf("%f",f(b)); exit(5);} if(f(a)*f(b)>0){printf("初期値異常"); exit(6);}} double nibun(void) {double c; if(b>a){ while(b-a>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(a)*f(c)<0){b=c;} if(f(b)*f(c)<0){a=c;} } return a;} if(a>b){ while(a-b>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(b)*f(c)<0){a=c;} if(f(a)*f(c)<0){b=c;} } return a;} } void syutsuryoku(double x){ printf("x=%lf\n",x); printf("f(x)=%lf\n",f(x)); printf("繰り返し回数=%d\n",count); } int main(void){ double ans; count=0; nyuuryoku(); hani(); ans = nibun(); syutsuryoku(ans); }

  • 分数の足し算をさせるプログラムが分かりません。どなたか分かりませんか?

    分数の足し算をさせるプログラムが分かりません。 C言語の問題で分数の足し算までは一応できるんですが、答えがでたときに整数で出すやり方と約分して表す方法が分かりません。 どなたか知恵を貸してくれませんか? ユーザから4つの整数を入力し、はじめに入力された2個の整数と後に入力された2個の整数を分数と考え、その分数の和を表示するプログラムを作成せよ。 例えば、「3」「4」「5」「6」と入力されたときは、3/4 + 5/6を計算する。 そのプログラム内では分数の和を計算する関数を作成する。 さらに、 約分を行う関数を 再帰呼び出しを利用して作成する。 void yakubun(int *a1, int *a2) 例えば、以下の場合1/2と表示される。 int i=10,j=20; yakubun(&i,&j); printf(“%d / %d”, i, j); ちなみにここまでできました↓ #include<stdio.h> void bunsu_tasizan(int a1,int a2,int b1,int b2, int *c1,int *c2 ) { *c1=(a1*b2)+(b1*a2); *c2=(a2*b2); } int main() { int x1,x2,y1,y2,z1,z2; printf("整数を入力してください"); scanf("%d",&x1); scanf("%d",&x2); scanf("%d",&y1); scanf("%d",&y2); if(x2==0||y2==0||x2==0&&y2==0) printf("0以外を入力してください"); else{ bunsu_tasizan(x1,x2,y1,y2,&z1,&z2); printf("%d/%d",z1,z2);} return (0); }

  • C言語で連立一次方程式

    C言語で連立一次方程式 /* 連立一次方程式 a*x + b*y = e c*x + d*y = f の解を求めるプログラムを作成したい。 a,b,c,d,e,f をキーボード入力させる ことで、 行列 [a b c d] の逆行列、及び、連立方程式の解( x= , y= )を求めたい。 なお、a b c d の値によっては、逆行列を求めることが 出来ません。その時は、 【解を求めることはできません】 と表示してプログラムを終了するようにして下さい。 (注) [a,b,c,d,e,f]を 2次元配列 ma[2][3]とする. [逆行列[a,b,c,d]と解x,y]を 2次元配列 mb[2][3]とする. ma[][] の値をmain関数内でキーボード入力する mb[][] の値は,mat_keisan関数内で計算 mb[][] の値をmain関数内で表示 関数 mat_keisan の戻り値として,「解」が求まる方程式か どうかを知らせる「int 型のフラグ(旗)」として用いるとよい. */ #include<stdio.h> int mat_keisan(int ma , int mb); int main(void) { int inverse; double ma[2][3]; double mb[2][3]={0}; printf("連立一次方程式の計算\n"); printf("a * x + b * y= e\n"); printf("c * x + d * y= f\n"); printf("Input a :"); scanf("%lf",&ma[1][1]); printf("Input b :"); scanf("%lf",&ma[1][2]); printf("Input c :"); scanf("%lf",&ma[1][3]); printf("Input d :"); scanf("%lf",&ma[2][1]); printf("Input e :"); scanf("%lf",&ma[2][2]); printf("Input f :"); scanf("%lf",&ma[2][3]); printf("%4.2f* x + %4.2f * y = %4.2f\n", ma[1][1],ma[1][2],ma[1][3]); printf("%4.2f* x + %4.2f * y = %4.2f\n", ma[2][1],ma[2][2],ma[2][3]); inverse=mat_keisan(ma,mb); if(inverse==1) printf("計算できません\n"); else{ printf("逆行列\n"); printf("%4.2f %4.2f\n", mb[1][1],mb[1][2]); printf("%4.2f %4.2f\n", mb[2][1],mb[2][2]); printf("解\n"); printf("x=%4.2f\n",mb[1][3]); printf("y=%4.2f\n",mb[3][3]); } return (0); } /* 配列の足し算 */ int mat_keisan(int ma ,int mb ) { int x,y,z;// 1/ma[1][1]*mb[2][2]-ma[1][2]*mb[2][2]; //逆行列と解を求めるプログラムを作成する。 //そしてその値をmb[][] に入力する。 return(#######); } 関数内が手も足もでません; 他のサイトを調べてみたのですが逆行列を求めるプログラムがよくわかりません; >int mat_keisan(int ma ,int mb ) は、あってないかもです; それとinverseの意味がわかりません; ヒントや、解説を よろしくお願いします;。

専門家に質問してみよう