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

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

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

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

Q&A

解決済

3回答

2645閲覧

C言語 GPAを計算し、表示するプログラム

tiroha

総合スコア109

C

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

0グッド

0クリップ

投稿2020/09/03 03:54

編集2020/09/03 04:34

C言語

1#include "wakabalite.h" 2#include "gpa1.h" 3 4// gpa算出関数(単位数, MARK構造体ポインタ, 科目数) 5double get_gpa(int units, Mark *marks, int n){ 6 double gpSum = 0.0; 7 int i; 8 9 for(i=0;i<n;i++){ 10 gpSum += (double)(marks[i].score-54.5)*marks[i].unit/10; 11 } 12 return (double)gpSum/units; 13} 14 15int gpa1(pthread_t selfId, PGconn *con, int soc, char *recvBuf, char *sendBuf){ 16 PGresult *res, *resStd, *resSub, *resMrk, *resMrk2; // SQL実行結果 17 int resultRows, resultRows2, sendLen, i, n; 18 int stNum, units=0; 19 double gpa; 20 char *subCode; 21 char comm[BUFSIZE]; 22 char sql[BUFSIZE]; 23 char *sqlBegin="BEGIN", *sqlCommit="COMMIT", *sqlRollback="ROLLBACK"; 24 char userid[10]; 25 char year[10]; 26 char term[10]; 27 28 WakabaUser account; 29 Student student; 30 Mark marks[100]; 31 32 /* コマンド引数取得 */ 33 n = sscanf(recvBuf, "%s %s %s %s", comm, userid, year, term[0]); 34 if(n!=4){ 35 sprintf("%s %d%s", ER_STAT, E_CODE_2, ENTER); 36 return -1; 37 } 38 39 /*入力された学期を格納*/ 40 marks->term[0] = term[0]; 41 42 /* 学籍番号・科目コード・点数をとりだす*/ 43 sprintf(sql,"SELECT user_id,subject_code,score,year FROM marks WHERE user_id='%s' AND year='%s'", userid, year); 44 printf("[%s]\n",sql); 45 resStd = PQexec(con, sql); 46 if(PQresultStatus(resStd) != PGRES_TUPLES_OK){ 47 printf("%s\n", PQresultErrorMessage(resStd)); 48 sprintf("%s %d%s", ER_STAT, E_CODE_4, ENTER); 49 return -1; 50 } 51 resultRows = PQntuples(resStd); 52 if(resultRows != 1){ 53 sprintf("%s %d%s", ER_STAT, E_CODE_1, ENTER); 54 return -1; 55 } 56 57 // 学生・成績オブジェクトに各値を代入 58 for(i=0; i<resultRows; i++){ 59 strcpy(student.userId,PQgetvalue(resStd, i, 0)); 60 strcpy(marks[i].subCode,PQgetvalue(resStd, i, 1)); 61 marks[i].score = atoi(PQgetvalue(res, i, 2)); 62 strcpy(marks[i].year,PQgetvalue(resStd, i, 3)); 63 } 64 65 // 単位数を取得(科目コードから) 66 sprintf(sql, "SELECT subject_code,unit_number,term FROM subject_t WHERE subject_code = 'marks->subCode' term = 'marks->term[0]'"); 67 68 printf("[%s]\n",sql); 69 resMrk = PQexec(con, sql); 70 if(PQresultStatus(resMrk) != PGRES_TUPLES_OK){ 71 printf("%s\n", PQresultErrorMessage(resMrk)); 72 sprintf("%s %d%s", ER_STAT, E_CODE_4, ENTER); 73 return -1; 74 } 75 resultRows = PQntuples(resMrk); 76 77 for(i=0;i<resultRows;i++){ 78 marks[i].unit = atoi(PQgetvalue(res, i, 1)); 79 80 // 単位数カウント 81 units += marks[i].unit; 82 } 83 84 // GPA算出 85 gpa = get_gpa(units,marks,resultRows); 86 87 // レスポンス送信 88 sendLen = sprintf(sendBuf,"units:%d GPA:%f%s", units, gpa, ENTER); 89 send(soc, sendBuf, sendLen, 0); 90 printf("[C_THREAD %ld] SEND=> %s", selfId, sendBuf); 91 92 return 0; 93}

ーー追記ーー
makeコマンドを使い、以下のファイルを一気にコンパイルしました。

$make gcc wakabalite_server_main.o setup_listen.o wakabalite_controller.o common_func.o get_mark_clerk_func.h mark_divi.o gpa1.o -lpq -lpthread -o wakabalite_s

サーバーに接続してプロトコルコマンドを入力し、挙動を確認。

[C_THREAD 140385380718336] WAKABALITE CONTROLLER START (4) [C_THREAD 140385380718336] RECV=> GPA 66660320 2020 前期 [SELECT user_id,subject_code,score,year FROM marks WHERE user_id='66660320' AND year='2020'] Segmentation fault

コマンドプロンプトで実行したところ、セグメンテーションフォルトが出力されます。
どこがおかしいか教えていただけませんか?

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

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

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

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

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

kay-ws

2020/09/03 04:02

・どのようにコンパイルしたか ・どのように実行したか を追記してください。
tiroha

2020/09/03 04:16

分かりました。
guest

回答3

0

c

1n = sscanf(recvBuf, "%s %s %s %s", comm, userid, year, term[0]);

term[0]になっている。
termもしくは&term[0]とする必要がある。

投稿2020/09/03 04:02

ttyp03

総合スコア17000

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

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

tiroha

2020/09/03 04:15

回答ありがとうございます!termと&term[0]でやってみたとことまだ、セグメンテーションフォルトが出てきてしまいます。
ttyp03

2020/09/03 04:42

ここもおかしいですね。 marks->term[0] = term[0]; marksは配列なので、marks[0].term などと書くべきです。 また文字列のコピーをしたいなら、strcpyなどを使うべきです。 strcpy(marks[0].term, term); しかしmarks配列のtermは使用していないので、これ自体が悪さすることはなさそうです(実装はおかしいので修正したほうがいいです) 他はPQgetvalue()の戻り値を直接strcpyしていますが、PQgetvalue()の戻り値はPGresult構造体のアドレスなのでそのままは使えないでしょう。 詳しくはないのでマニュアルを参照してください。 https://www.postgresql.jp/document/7.3/programmer/libpq-exec.html あとはBUFSIZEの値がいくつかわかりませんが、足りているかなどご確認ください。 要所要所にデバッグ文を入れてどこまで進んだのかも確認してみてください。
guest

0

自己解決

printf(check1\n);

で地道にチェックしていったところ、セグメンテーションフォルトが無くなりました。

投稿2020/09/03 08:15

tiroha

総合スコア109

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

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

0

セグメンテーションフォルトが出力されます。

ってことはどこかでメモリ破壊起こしているということです。
VisualStudioやEclipseなど、ソースコードデバッグできる環境を整え、あなたのコードをデバッグしましょう。

#んで、main関数がないようなので実行しようがないと思いますが、どうやって実行したんでしょうか

投稿2020/09/03 04:01

y_waiwai

総合スコア88042

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

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

tiroha

2020/09/03 04:08

いくつかのファイルを同時にコンパイルしています。このコードはmainの中のモジュールです。サーバーに接続してプロトコルコマンドで挙動をみています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問