質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

1回答

1056閲覧

変数に入力された合格点以上の人数を求める関数

kennzi_665

総合スコア4

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

1クリップ

投稿2020/11/23 13:22

編集2020/11/23 13:28

配列sに点数が順に代入され、変数gに入力された合格点以上の人数を求める関数 calc_pass のお手本を作成して頂きたいです。

//関数原型宣言
double calc_pass(int data[], int n);

int main(void)
{
int s[10] = {91, 46, 68, 72, 89, 52, 94, 70, 43, 61};
int g, num;

scanf("%d", &g); //関数calc_passを呼び出す printf( "合格者数:%d\n", num );

return 0;
}
//関数を作成
double calc_pass(int data[], int n)

以下に合格者数を求めるコードを作成して貰いたいです。
何卒よろしくお願いいたします。(関数calc_passの中身自体を変更しても大丈夫です。)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

どうやって合格者の人数を把握するか? という方法について考えます.

i番目の人物の点数がs点であるとき,この人物を座標(s,i)に立たせることを考えてみます.

int s[10] = {91, 46, 68, 72, 89, 52, 94, 70, 43, 61};

に対しては,10人の立ち位置は下図の青い点の位置になります.
イメージ説明

ここで仮に合格点が80点だったとしましょう.
この場合,あなたが図内の赤丸の位置(80,0)に赤矢印の方向を向いて立ったときに,あなたから見て右手側(または真正面)にいるやつらは合格者であり,左手側に突っ立っているやつらは不合格者なのです.
この例では図を見れば合格者は3人であることがわかります.


上記の話を実装します.
「右手側にいるか,左手側にいるか」というのは,外積を使えば判断できます:
赤丸から各青丸に向かうベクトルと赤矢印のベクトルとの外積(※)の符号を見れば,それぞれの青丸がどちら側にあるかがわかります.

(※:2次元のベクトル(x,y)を,3次元ベクトル(x,y,0)と見立てて外積を計算した結果のz成分)

typedef struct Vec { int x,y; } Vec; int CrossProd( const Vec *pV1, const Vec *pV2 ){ return pV1->x * pV2->y - pV1->y * pV2->x; } int calc_pass(int data[], int n, int g ) { int i; int count = 0; Vec V2 ={0,1}; //赤矢印 for( i=0; i<n; ++i ) { Vec V1 = { data[i] - g, i+1 }; //赤丸→青丸 のベクトル if( CrossProd( &V1, &V2 ) >= 0 ){ ++count; } } return count; } int main(void) { int s[10] = {91, 46, 68, 72, 89, 52, 94, 70, 43, 61}; int g = 80; printf( "%d\n", calc_pass( s,10, g ) ); return 0; }

なお,このコード例では,関数calc_passの仕様を以下のように変更しました.

  • 引数に閾値gを追加
  • 戻り値をintにした(人数を返すのであれば,その型をdoubleとする意味がわからなかったので)

投稿2020/11/25 04:42

編集2020/11/25 04:45
fana

総合スコア11632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kennzi_665

2020/11/30 07:21

ありがとうございます!助かりました!(ベストアンサー遅れて申し訳なしです。)
kennzi_665

2020/11/30 07:34

質問をまたするようで申し訳ないのですが、Vecを使わないでこの問題を解くやり方はありますか?勿論回答してくださったやり方でも全然ありがたいのですが、参考として聞きたいです。
fana

2020/11/30 07:50 編集

行っている計算をきちんと追ってみてください. そこに無用な演算が含まれているとしたら,それを除去することができるでしょう. 例えば,ある計算処理の中に, x + (0 * y) とかいう記述がある(とか,あるいは結果としてそうなる)ような場合,()内のyを用いた演算部分は完全に不要であり,結局それは単なる x として簡略化できるでしょう. 同様に,( 1 * x ) みたいなのも x にできます. このコードにもそのような「突き詰めれば,なくしてもよい」要素が存在しています. そこを簡略化すれば,結果として Vec を使わない形になるでしょう.
fana

2020/11/30 07:46

ヒント: 図の意味を考えれば,青点群の位置というのは,図内の上下方向に移動しても判定結果が変わらない. すなわち,この上下方向の座標は結果に一切影響を与えていない.
kennzi_665

2020/11/30 07:51

わかりました!長文の回答本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問