私はあるプログラムを作ったのですが、すべてmain文内につくってしまい、これを関数そして、ファイル分割をしてよりわかりやすくしたいです。どのように変更すればいいでしょうか?関数化してみたら、ポインタや引数がうまいあいませんでした。
プログラムの内容は、ユーザ 1 と好みが似ているユーザの ID をその度合い(類似性スコア)が高い順番に出力するものです。1行目にユーザの数を表す整数 N と書籍の数を表す整数 M が空白区切りで与えられる。続く N 行に N × M 個
の要素 e からなる行列が空白区切りで与えられる。ei,j はユーザ i の書籍 j に対する評価を表す。ただし、ei,j が負の値の場合、評価しなかったことを表すものとします。
C
1#include <stdio.h> 2#include <math.h> 3int main() 4{ 5 int N, M; //Nは行M、は列 6 scanf("%d%d", &N, &M); 7 double e[N][M]; //入力データを格納した 8 9 for (int i = 0; i < N; i++) 10 { 11 for (int j = 0; j < M; j++) 12 { 13 scanf("%lf", &e[i][j]); 14 } 15 } 16 17 double score[2][N]; 18 double sum[N]; 19 20 for (int i = 1; i < N; i++) 21 { 22 for (int j = 0; j < M; j++) 23 { 24 if (e[0][j] == -1 || e[i][j] == -1) 25 continue; 26 sum[i] += pow(e[0][j] - e[i][j], 2); 27 } 28 } 29 30 for (int i = 0; i < N; i++) 31 { 32 score[1][i] = 1 / (sqrt(sum[i]) + 1); 33 score[0][i] = i + 1; 34 } 35 //バブルソート 36 double tmp; 37 for (int i = 1; i < N - 1; i++) 38 { 39 for (int j = N - 1; j >= i + 1; j--) 40 { 41 if (score[1][j - 1] < score[1][j]) 42 { 43 tmp = score[1][j - 1]; 44 score[1][j - 1] = score[1][j]; 45 score[1][j] = tmp; 46 47 tmp = score[0][j - 1]; 48 score[0][j - 1] = score[0][j]; 49 score[0][j] = tmp; 50 } 51 } 52 } 53 54 for (int i = 1; i < N; i++) 55 { 56 printf("%d %lf\n", (int)score[0][i], score[1][i]); 57 } 58 59 return 0; 60}
どのように関数化するべきか、ファイル分割するべきか、という問いには正解はありません。
まずは自分でやってみてください。
> 関数化してみたら、ポインタや引数がうまいあいませんでした。
具体的にどんなコードを書いてどんなエラーが出たのか記載してください。
「わかりやすく」と言うのはどちらかと言うと主観的なことなので、第三者には分かりません。回答者による分割、関数化が質問者にとっては分かりづらくなる可能性もあります。「どのように変更すればよいでしょうか?」となると丸投げ感が伴うので、まずは質問者さんが関数化して問題になった部分「ポインタや引数がうまく渡せない?」を質問としてみてはどうでしょう。
たぶん、適切に関数に分けることが先決なのであって、ファイルを分割しなければならないことは無いです。
まぁ、「こんな分け方、関数化はどうでしょう。」的な提案ベースの回答をいただけることはあるかもしれません。(ただし、それに期待をしてはいけません。私も回答は避けます)
質問の趣旨は、
・プログラムのどの部分をどうやって切り出して関数化するかという一般論
・C 言語の関数間で配列 (特に可変長 2 次元配列) をやり取りする具体的な方法
のどちらでしょうか? (後者に関しては C 言語ではいろいろ面倒すぎますよね…。)
あと、どういうプログラムかにもよります。再利用を考慮した一般的なプログラミング手法を前提とするか、特定の環境に最初から最適化して書いてしまうかですね。(特に、競プロであれば N, M の最大値が提示されてると思うので、最大サイズのグローバル配列を作ってしまうとか…。)