C言語の課題がわかりません
C言語の課題がわかりません
プログラムを初めて学んで約2ヶ月しかたっていない学生の者です。
明日提出しなければならないC++の課題が、まったくわからなくて困っています。
課題内容は…
高さh[m]の地点から速度u0(これはuに数字の0を下付けたやつです)[m/s]で質点を水平に投げたとき、質点が地上に到達するまでの時間T、および水平到達距離L[m]を算出するプログラムを作成せよ。ただし、0.1s毎の質点の位置x,yおよび速度成分u,vを画面に出力させること。またTおよいLは質点の位置が地面より下になった時点の値とし、厳密に求める必要はない。下記の関数は必ず作成すること。
・初期条件h、u0を入力する関数
・位置x,yを計算する関数
・速度成分u,vを計算する関数
以上、課題内容です。
今のところ、このプログラムはまったく進んでないです。
下2つの必要記入の関数は何となく理解できるのですが、1つ目の「初期条件h、u0を入力する関数」というものがよくわかりません。
数値演算関数内にprintfを書けということなのでしょうか。
最近、何とかポインタを理解できたという程度の知識しかもっていません。
どうぞよろしくお願いします。
明日提出しなければならないC++の課題が、まったくわからなくて困っています。
課題内容は…
高さh[m]の地点から速度u0(これはuに数字の0を下付けたやつです)[m/s]で質点を水平に投げたとき、質点が地上に到達するまでの時間T、および水平到達距離L[m]を算出するプログラムを作成せよ。ただし、0.1s毎の質点の位置x,yおよび速度成分u,vを画面に出力させること。またTおよいLは質点の位置が地面より下になった時点の値とし、厳密に求める必要はない。下記の関数は必ず作成すること。
・初期条件h、u0を入力する関数
・位置x,yを計算する関数
・速度成分u,vを計算する関数
以上、課題内容です。
今のところ、このプログラムはまったく進んでないです。
下2つの必要記入の関数は何となく理解できるのですが、1つ目の「初期条件h、u0を入力する関数」というものがよくわかりません。
数値演算関数内にprintfを書けということなのでしょうか。
最近、何とかポインタを理解できたという程度の知識しかもっていません。
どうぞよろしくお願いします。
Re:C言語の課題がわかりません
ウィーヤさん、こんにちは。
3つの項目に上から番号を振りましょう。
1番はプログラムの問題ですが、2,3は単純に物理の問題ですね。
プログラムの書き方は、わかりますか?
物理的な式の解き方はわかりますか?
最初に出てくる物理の運動に関する3大公式を用いれば解けます。
最初にプログラムは関係なく、紙とペンでとけるかどうかが重要です。
紙とペンでとけなければ、プログラムがわかっても解けません。
一度問題を解いてみてください。
3つの項目に上から番号を振りましょう。
1番はプログラムの問題ですが、2,3は単純に物理の問題ですね。
プログラムの書き方は、わかりますか?
物理的な式の解き方はわかりますか?
最初に出てくる物理の運動に関する3大公式を用いれば解けます。
最初にプログラムは関係なく、紙とペンでとけるかどうかが重要です。
紙とペンでとけなければ、プログラムがわかっても解けません。
一度問題を解いてみてください。
Re:C言語の課題がわかりません
まず、1番はこのようにすればOKです。
必要な変数はここに宣言しました。
必要な変数はここに宣言しました。
#include <stdio.h> void main(){ double l,u_0,T,L,x,y,u,v; printf("初速度 u_0(m/s) -> ") , scanf("%lf",&u_0); printf("高さ h (m) -> ") , scanf("%lf",&h ); }以後キーボードから代入された値が(u_0,h)使えます。
Re:C言語の課題がわかりません
後は、物理の公式に代入するだけです。
水平方向に投げたということは、速度のx成分は初速度に等しく、一定です。
初速度がそのままv_xとなります。
xの距離は素直に、速さ*時間になります。
y方向には最初力が加わっていないので、自由落下と同じになります。
速さのy成分v_yはgtとなります。
yの式から地上にぶつかる時のtが求まります。
この式を使えば解けます。
厳密に計算する必要はないということなので、
0.1秒ごとに増えていく値がこの値より大きくなった時点の値とすればよいわけです。
tを0.1ずつ増加させて計算しましょう。
水平方向に投げたということは、速度のx成分は初速度に等しく、一定です。
初速度がそのままv_xとなります。
xの距離は素直に、速さ*時間になります。
y方向には最初力が加わっていないので、自由落下と同じになります。
速さのy成分v_yはgtとなります。
yの式から地上にぶつかる時のtが求まります。
この式を使えば解けます。
厳密に計算する必要はないということなので、
0.1秒ごとに増えていく値がこの値より大きくなった時点の値とすればよいわけです。
tを0.1ずつ増加させて計算しましょう。
Re:C言語の課題がわかりません
ご回答有り難うございます。
今後、質問がわかりやすいように、かつ回答しやすいようにするために、項目に番号を振るようにします。
さて、項目1についてはわかりました。
しかし、理由がいまいちわからないです。
「関数として」というと、
#include <math.h>
は必要なのではないのでしょうか。
また
void main()
内に入れた場合は関数と言えないのでは?
上辺だけの知識しかありませんが、その教えていただけるとあり難いです。
また項目2・3の方ですが、物理の方は何ら問題はありません。
ペンと紙ですぐに解けます(^^
ただ、プログラムとして記入するのはちょっと自信がないですが…。
今後、質問がわかりやすいように、かつ回答しやすいようにするために、項目に番号を振るようにします。
さて、項目1についてはわかりました。
しかし、理由がいまいちわからないです。
「関数として」というと、
#include <math.h>
は必要なのではないのでしょうか。
また
void main()
内に入れた場合は関数と言えないのでは?
上辺だけの知識しかありませんが、その教えていただけるとあり難いです。
また項目2・3の方ですが、物理の方は何ら問題はありません。
ペンと紙ですぐに解けます(^^
ただ、プログラムとして記入するのはちょっと自信がないですが…。
Re:C言語の課題がわかりません
まず、これをコンパイルしてみてください。
実行してみて、自分のやりたいことがあってるか、確認してください。
実行してみて、自分のやりたいことがあってるか、確認してください。
#include <stdio.h> #define g 9.80665 void input(double *v_0,double *h){ printf("初速度 v_0(m/s) -> ") , scanf("%lf",v_0); printf("高さ h (m) -> ") , scanf("%lf",h ); } void calc_xy(double *v_0,double *v_x,double *x,double *t,double *y){ *x = (*v_x) * (*t); *y = 0.5f * g * (*t) * (*t); } void calc_v(double *v_y,double *t){ *v_y= g * (*t); } void main(){ double h,v_0,v_x,v_y,x,y=0,t=0; input(&v_0,&h); v_x=v_0; printf(" t\t x\t y\t v_x\t v_y\n"); while(y<h){ t+=0.1f; calc_xy(&v_0,&v_x,&x,&t,&y); printf("%4.1f\t%7.2f\t%7.2f\t",t,x,y); calc_v(&v_y,&t); printf("%7.2f\t%7.2f\n",v_x,v_y); } printf("T=%4.1f\tL=%7.2f\n",t,x); }よければ説明します。
Re:C言語の課題がわかりません
まず、数値入力を実現したプログラムはこちらです。
scanfは変数をアドレスで指定している点に注意してください。
この入力部分を関数化するとこうなります。
ポインタで渡された関数内では*をつけることで、main内と同じ変数として扱えますね。
ここでポイントなのは、scanf文の変数の前に&がなくなっていること。
ポインタで渡された変数は*をつければ、値をしめし、それをとればアドレスを示すことになります。
ここまでいいですか?
#include <stdio.h> void main(){ double h,v_0; printf("初速度 v_0(m/s) -> ") , scanf("%lf",&v_0); printf("高さ h (m) -> ") , scanf("%lf",&h ); }scanfの使い方さえわかれば、すんなりわかりますね。
scanfは変数をアドレスで指定している点に注意してください。
この入力部分を関数化するとこうなります。
#include <stdio.h> void input(double *v_0,double *h){ printf("初速度 v_0(m/s) -> ") , scanf("%lf",v_0); printf("高さ h (m) -> ") , scanf("%lf",h ); } void main(){ double h,v_0; input(&v_0,&h); }ポインタはわかるとおっしゃっていたので、説明する必要はないとは思いますが、mainからのinput呼び出しの際、アドレスを渡してやってinputでポインタとして受け取っています。
ポインタで渡された関数内では*をつけることで、main内と同じ変数として扱えますね。
ここでポイントなのは、scanf文の変数の前に&がなくなっていること。
ポインタで渡された変数は*をつければ、値をしめし、それをとればアドレスを示すことになります。
ここまでいいですか?
Re:C言語の課題がわかりません
では、具体的な部分へ。
input関数を作って、入力を受け付ける関数を作りました。
では、次は速さを計算する関数を作ってみましょう。
tが最初0の状態から0.1ずつ増やしていき、2秒になるまでループさせます。
while(t<2.0){
t+=0.1f;
ここの部分ですね。
速さのx成分はずっと変わらないので計算する必要はありません。
今回は用意しましたが、v_xという変数もわざわざ用意することも無いでしょう。
例によってポインタで計算するために、アドレスを渡してやります。
&v_y,&t
ここの部分ですね。
calcは計算する、vは速さという意味です。
速さを計算するcalc_vという関数に変数のアドレスを渡してやり、
v_y = g*t;
を計算します。紙とペンではすぐとけるということなので、物理的な解説ははぶきます。
これでy成分の速さが求まりました。
tは0.1ずつ増えていっているので、時間変化によって、v_yも計算されていきます。
ループを抜けた時、t=2の時の速さが求まっているはずです。
printfの出力を見てください。
input関数を作って、入力を受け付ける関数を作りました。
では、次は速さを計算する関数を作ってみましょう。
tが最初0の状態から0.1ずつ増やしていき、2秒になるまでループさせます。
while(t<2.0){
t+=0.1f;
ここの部分ですね。
速さのx成分はずっと変わらないので計算する必要はありません。
今回は用意しましたが、v_xという変数もわざわざ用意することも無いでしょう。
例によってポインタで計算するために、アドレスを渡してやります。
&v_y,&t
ここの部分ですね。
calcは計算する、vは速さという意味です。
速さを計算するcalc_vという関数に変数のアドレスを渡してやり、
v_y = g*t;
を計算します。紙とペンではすぐとけるということなので、物理的な解説ははぶきます。
これでy成分の速さが求まりました。
tは0.1ずつ増えていっているので、時間変化によって、v_yも計算されていきます。
ループを抜けた時、t=2の時の速さが求まっているはずです。
printfの出力を見てください。
#include <stdio.h> #define g 9.80665 void input(double *v_0,double *h){ printf("初速度 v_0(m/s) -> ") , scanf("%lf",v_0); printf("高さ h (m) -> ") , scanf("%lf",h ); } void calc_v(double *v_y,double *t){ *v_y= g * (*t); } void main(){ double h,v_0,v_x,v_y,x,y=0,t=0; input(&v_0,&h); v_x=v_0; while(t<2.0){ t+=0.1f; calc_v(&v_y,&t); } printf("v_x=%f v_y=%f\n",v_x,v_y); }次、最後の解説をします。
Re:C言語の課題がわかりません
あ、今読み返してみると
>3つの項目に上から番号を振りましょう。
この文章は
「3つの項目に上から番号を振ります。」と最初かいていたのに、後から消した文章とつなげて変に「ふりなさいよ!」みたいな発言になってしまってますね^^;
自分が解説しやすいように、番号ふっただけなんで。
気にしてたらごめんなさい^^;
>3つの項目に上から番号を振りましょう。
この文章は
「3つの項目に上から番号を振ります。」と最初かいていたのに、後から消した文章とつなげて変に「ふりなさいよ!」みたいな発言になってしまってますね^^;
自分が解説しやすいように、番号ふっただけなんで。
気にしてたらごめんなさい^^;
Re:C言語の課題がわかりません
ん?
while(t<2.0){
t+=0.1f;
この変数tの増やし方は初めて知りました。
数字の増減方法は
i++ やi--
しか知りませんでした。
この場合は(i++,i<20.0)として
t=0.1*i
と書けばよろしいのでしょうか。
while(t<2.0){
t+=0.1f;
この変数tの増やし方は初めて知りました。
数字の増減方法は
i++ やi--
しか知りませんでした。
この場合は(i++,i<20.0)として
t=0.1*i
と書けばよろしいのでしょうか。
Re:C言語の課題がわかりません
次にx,yを計算する
calc_xy
という関数を作りましょう。
xとyの計算に必要な変数はなんでしょうか?
まず、当然x,yの計算結果を格納するためのx,yという変数が必要です。
その変数を受け取ります。
次に、
xは
x=v_x*t
で計算できますから、v_xとtが必要です。
これも、main関数から引っ張ってきましょう。
後重力加速度gですが、これは不変なので定義します。
#defineの使い方がわからなければ、また聞いてください。
ここでは「g」と書けば、9.80665という意味になると覚えておいてください。
それでは受け取るべき変数をうけとって、計算したものが
なんら難しくないですね?
掛け算の「*」なのか、変数のポインタを表す*なのか混合しそうなので、括弧をつけて明確にしました。
後はmain関数からよんでやればいいだけのことです。
ループの条件はy<hとし、設定したhよりyの方が大きくなれば終了です。
ループを抜けた時の値を表示してやれば、問いの解答となります。
ちなみに
%7.2fとかいたら、
「少なくとも7桁表示し、そのうち小数点以下は2桁表示で浮動小数点型」
という意味になります。
どの数値も7桁表示されるので、値がキレイにそろって表示できます。
これらを全て組み合わせるとこうなります。
これでやりたいことあっていますか?
calc_xy
という関数を作りましょう。
xとyの計算に必要な変数はなんでしょうか?
まず、当然x,yの計算結果を格納するためのx,yという変数が必要です。
その変数を受け取ります。
次に、
xは
x=v_x*t
で計算できますから、v_xとtが必要です。
これも、main関数から引っ張ってきましょう。
後重力加速度gですが、これは不変なので定義します。
#defineの使い方がわからなければ、また聞いてください。
ここでは「g」と書けば、9.80665という意味になると覚えておいてください。
それでは受け取るべき変数をうけとって、計算したものが
void calc_xy(double *v_x,double *x,double *t,double *y){ *x = (*v_x) * (*t); *y = 0.5f * g * (*t) * (*t); }これです。
なんら難しくないですね?
掛け算の「*」なのか、変数のポインタを表す*なのか混合しそうなので、括弧をつけて明確にしました。
後はmain関数からよんでやればいいだけのことです。
ループの条件はy<hとし、設定したhよりyの方が大きくなれば終了です。
ループを抜けた時の値を表示してやれば、問いの解答となります。
ちなみに
printf("%4.1f %7.2f %7.2f %7.2f %7.2f \n",t,x,y,v_x,v_y);という表示の仕方は、数値をキレイにそろえて表示させる方法で、
%7.2fとかいたら、
「少なくとも7桁表示し、そのうち小数点以下は2桁表示で浮動小数点型」
という意味になります。
どの数値も7桁表示されるので、値がキレイにそろって表示できます。
これらを全て組み合わせるとこうなります。
#include <stdio.h> #define g 9.80665 void input(double *v_0,double *h){ printf("初速度 v_0(m/s) -> ") , scanf("%lf",v_0); printf("高さ h (m) -> ") , scanf("%lf",h ); } void calc_xy(double *v_x,double *x,double *t,double *y){ *x = (*v_x) * (*t); *y = 0.5f * g * (*t) * (*t); } void calc_v(double *v_y,double *t){ *v_y= g * (*t); } void main(){ double h,v_0,v_x,v_y,x,y=0,t=0; input(&v_0,&h); v_x=v_0; printf(" t\t x\t y\t v_x\t v_y\n"); while(y<h){ t+=0.1f; calc_xy(&v_x,&x,&t,&y); calc_v(&v_y,&t); printf("%4.1f %7.2f %7.2f %7.2f %7.2f \n",t,x,y,v_x,v_y); } printf("T=%4.1f\tL=%7.2f\n",t,x); }若干むだがあったので、改良しました。
これでやりたいことあっていますか?
Re:C言語の課題がわかりません
>この変数tの増やし方は初めて知りました。
i++
は
i = i+1;
と同じです。
一方
i=i+2;
は
i += 2;
と同じです。
i=i-3;
は
i -= 3;
と同じです。
i=i*0.2;
は
i *= 0.2;
と同じです。
これらはiを2回書かなくて済むので「若干」便利ですw
i++
は
i = i+1;
と同じです。
一方
i=i+2;
は
i += 2;
と同じです。
i=i-3;
は
i -= 3;
と同じです。
i=i*0.2;
は
i *= 0.2;
と同じです。
これらはiを2回書かなくて済むので「若干」便利ですw
Re:C言語の課題がわかりません
なるほど。
よくわかりました。しかし
t+=0.1f
の「f」、位置yの関数でも使用されてますが何なのでしょうか。
あと、実行してみたところ、自分のやりたいこととばっちり合っていました。
よくわかりました。しかし
t+=0.1f
の「f」、位置yの関数でも使用されてますが何なのでしょうか。
あと、実行してみたところ、自分のやりたいこととばっちり合っていました。
Re:C言語の課題がわかりません
最後尾にfを付けるとfloat型になり、
最後尾にdを付けるとdouble型、
lを付けるとlong double型に出来ます。
doubleからfloatにする意味は全くないので、省いてください。
こちらに省いたプログラム載せます。
最後尾にdを付けるとdouble型、
lを付けるとlong double型に出来ます。
doubleからfloatにする意味は全くないので、省いてください。
こちらに省いたプログラム載せます。
#include <stdio.h> #define g 9.80665 void input(double *v_0,double *h){ printf("初速度 v_0(m/s) -> ") , scanf("%lf",v_0); printf("高さ h (m) -> ") , scanf("%lf",h ); } void calc_xy(double *v_x,double *x,double *t,double *y){ *x = (*v_x) * (*t); *y = 0.5 * g * (*t) * (*t); } void calc_v(double *v_y,double *t){ *v_y= g * (*t); } void main(){ double h,v_0,v_x,v_y,x,y=0,t=0; input(&v_0,&h); v_x=v_0; printf(" t\t x\t y\t v_x\t v_y\n"); while(y<h){ t+=0.1; calc_xy(&v_x,&x,&t,&y); calc_v(&v_y,&t); printf("%4.1f %7.2f %7.2f %7.2f %7.2f \n",t,x,y,v_x,v_y); } printf("T=%4.1f\tL=%7.2f\n",t,x); }
Re:C言語の課題がわかりません
そうだったんですか…。
わかりました。
ちょっと頭がオーバーヒートしそうなので、
一息入れてから管理人さんの解説をみて、
なぜこうなるのかを考えながらやってみますね。
今のところ、管理人さんの解説を完璧に理解できている自信はないので、また質問することになると思います。
(たしか新しくトピックを作るんでしたね)
解決したわけではありませんが、とりあえずこのトピックは「解決」状態にしておきます。
長く書いていただき、有り難うございました。
わかりました。
ちょっと頭がオーバーヒートしそうなので、
一息入れてから管理人さんの解説をみて、
なぜこうなるのかを考えながらやってみますね。
今のところ、管理人さんの解説を完璧に理解できている自信はないので、また質問することになると思います。
(たしか新しくトピックを作るんでしたね)
解決したわけではありませんが、とりあえずこのトピックは「解決」状態にしておきます。
長く書いていただき、有り難うございました。
Re:C言語の課題がわかりません
プログラムは一見ゴミゴミして見えますが、
全く難しい処理はしていませんから、落ち着いてみてください。
最初から完成したプログラムをみるのではなく、私の解説にそってみていけば判ると思います。
少しでもわからない部分があれば、そのままにせずに必ず聞いて「完璧」にわかった状態にしてくださいね☆
全く難しい処理はしていませんから、落ち着いてみてください。
最初から完成したプログラムをみるのではなく、私の解説にそってみていけば判ると思います。
少しでもわからない部分があれば、そのままにせずに必ず聞いて「完璧」にわかった状態にしてくださいね☆