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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

1268閲覧

明解c言語 中級 9章 自由課題1

nmkhg

総合スコア13

C

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2017/07/23 12:53

参考書「明解c言語 中級」の自由課題でエラーの原因がわかりません。

###発生している問題・エラーメッセージ

visual studio 2017で、ビルドは成功しています。 ただ実行時、retryしないを選択すると以下のエラーメッセージが表示されます。 Run-Time Check Failure #2 - Stack around the variable 'best' was corrupted.

###該当のソースコード

c

1 2/*ラックナンバーサーチ(前回の日時と過去のベスト10と過去10回の成績を記録)*/ 3 4#include <time.h> 5#include <float.h> 6#include <stdio.h> 7#include <stdlib.h> 8#include <ctype.h> 9#include <conio.h> 10 11#define MAX_STAGE 10 12#define swap(type, x, y) do{ type t = x; x = y; y = t; }while(0) 13 14char dtfile[] = "9_1_lacknum.txt"; 15 16 17/*ファイルから前回のデータを読み取る*/ 18void get_data(double *best, double *recent) { 19 FILE *fp; 20 int i; 21 22 if ((fp = fopen(dtfile, "r")) == NULL) { 23 printf("\n初めてプログラムを実行しました。\n"); 24 } 25 else { 26 int y, mon, d, h, m, s; 27 28 /*前回の日時の取得*/ 29 fscanf(fp, "%d%d%d%d%d%d", &y, &mon, &d, &h, &m, &s); 30 31 /*過去ベスト10を取得*/ 32 for (i = 0; i < 10; i++) { 33 fscanf("%f", &best[i]); 34 } 35 36 /*直近10回を取得*/ 37 for (i = 0; i < 10; i++) { 38 fscanf("%f", &recent[i]); 39 } 40 41 printf("\n前回の挑戦は%d年%d月%d日 %d時%d分%d秒でした。\n", y, mon, d, h, m, s); 42 printf("過去の最高記録(最短所要時間)は %0.2f です。\n", best[0]); 43 fclose(fp); 44 } 45} 46 47/*ファイルに実行時の時間と最高記録を書き込む*/ 48void put_data(double *best, double *recent) { 49 FILE *fp; 50 int i; 51 time_t t = time(NULL); 52 struct tm *local = localtime(&t); 53 54 if ((fp = fopen(dtfile, "w")) == NULL) { 55 printf("\nエラーが発生しました。\a\n"); 56 } 57 else { 58 /*実行日時の書き込み*/ 59 fprintf(fp, "%d %d %d %d %d %d\n", local->tm_year + 1900, local->tm_mon + 1, local->tm_mday, 60 local->tm_hour, local->tm_min, local->tm_sec); 61 62 /*ベスト10の書き込み*/ 63 for (i = 0; i < 10; i++) { 64 fprintf(fp, "%f ", best[i]); 65 } 66 fprintf(fp, "\n"); 67 68 /*過去10回の成績を書き込み*/ 69 for (i = 0; i < 10; i++) { 70 fprintf(fp, "%f ", recent[i]); 71 } 72 fprintf(fp, "\n"); 73 fclose(fp); 74 } 75} 76 77/*トレーニングの実行*/ 78double go(void) { 79 int i, j, stage; 80 int qnum[] = { 1,2,3,4,5,6,7,8,9, }; 81 int a[8]; 82 time_t start, end; 83 84 printf("\nスペースキーで開始します。\n"); 85 while (getch() != ' ') 86 ; 87 88 start = time(NULL); 89 90 for (stage = 0; stage < MAX_STAGE; stage++) { 91 int x = rand() % 9; 92 int no; 93 94 /*添え字xのqnumを飛ばして格納*/ 95 for (i = 0, j = 0; i < 9; i++) { 96 if (i != x) a[j++] = qnum[i]; 97 } 98 99 /*配列aをランダム配置にする*/ 100 for (i = 7; i > 0; i--) { 101 int j = rand() % (i + 1); 102 swap(int, a[i], a[j]); 103 } 104 105 /*問題表示*/ 106 for (i = 0; i < 8; i++) { 107 printf("%d ", a[i]); 108 } 109 putchar(':'); 110 fflush(stdout); 111 112 do { 113 no = getch(); 114 if (isprint(no)) { 115 putch(no); 116 if (no != '0' + qnum[x]) { 117 putch('\b'); 118 } 119 else { 120 printf("\n"); 121 } 122 fflush(stdout); 123 } 124 } while (no != '0' + qnum[x]); 125 } 126 end = time(NULL); 127 128 printf("\n%.2f秒かかりました。\n", difftime(end, start)); 129 130 return difftime(end, start); 131} 132 133/*得点データの更新*/ 134void update_score(double *a, double score, int n) { 135 int i; 136 137 for (i = 10; i > n; i--) { 138 a[i] = a[i - 1]; 139 } 140 a[n] = score; 141} 142 143int main(void) { 144 int i; 145 int retry; 146 int n; 147 double score; /*今回の得点*/ 148 double best[10]; 149 double recent[10]; 150 151 get_data(best, recent); 152 153 srand((unsigned int)time(NULL)); 154 155 for (i = 0; i < 10; i++) { 156 best[i] = DBL_MAX; 157 recent[i] = DBL_MAX; 158 } 159 160 do { 161 score = go(); 162 163 /*ベスト10を更新*/ 164 if (score < best[0]) printf("最高得点を更新しました!\n"); 165 for (n = 0; n < 10; n++) { 166 if (best[n] > score) { 167 update_score(best, score, n); 168 break; 169 } 170 } 171 172 /*過去10回を更新*/ 173 n = 0; 174 update_score(recent, score, n); 175 176 printf("\n best10 直近の10回\n"); 177 for (i = 0; i < 10; i++) { 178 printf("No.%2d:%.2f %.2f\n", i + 1, (best[i] != DBL_MAX) ? best[i] : 0, (recent[i] != DBL_MAX) ? recent[i] : 0); 179 } 180 181 printf("\nもう一度プレーしますか?\n"); 182 printf("はい...(0) いいえ...(1) :"); 183 scanf("%d", &retry); 184 } while (retry == 0); 185 186 put_data(best, recent); 187 188 return 0; 189} 190 191

###試したこと
エラーメッセージにあるとおり、bestに格納してある値等を変えて実行してみたのですがどうもうまくいかず。

###補足情報(言語/FW/ツール等のバージョンなど)
visual studio 2017使用

プログラムの目的は、
1~9の数字のうち欠けている数字を答える問題を10問解く時間をスコアとする。
前回実行日時とベスト10のスコア、直近10回のスコアをテキストファイルに出力する。
というものです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんにちは。

C言語の配列は0から始まります。
ですので、10個の配列はa[0]からa[9]までしか存在せずa[10]は存在しません。
少なくともupdate_score()関数はa[10]に何か書き込んでますので、これがメモリを破壊し、異常動作している可能性があります。

投稿2017/07/23 13:26

Chironian

総合スコア23272

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

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

nmkhg

2017/07/23 14:33

指摘していただいた部分を修正すると無事実行できました。 ありがとうございます。 また、二回目に実行すると何も表示されることなくエラーになります。 もしよければ何か思い当たる部分があるか教えていただけるとありがたいです。
nmkhg

2017/07/23 15:18

何度も申し訳ありません。 全部解決しました。 ありがとうございました。
guest

0

#include <conio.h>

C標準入出力とこのヘッダーにある関数(getch/putchなど)を混ぜて使うのは極めて良くない考えです。C標準関数で置き換えることを検討してください。

二回目に実行すると何も表示されることなくエラー

はこの辺が関係している可能性があります。


fscanf("%f", &best[i]);

fscanfは第一引数にFILE *を要求します。忘れていませんか?


配列を受け取ることを想定するすべての関数の引数は同時に配列の大きさも受け取るべきです。そうしない限り、つねに領域外アクセスの可能性があり、安全ではありません。

c

1//NG 2void update_score(double *a, double score, int n); 3 4//OK 5void update_score(double *arr, size_t arr_size, double score, int n);

またscanf系関数(fscanf含む)を用いで標準入力から数値を受け取ることも避けるべきです。不正な入力の検証を行えません。

C言語で安全に標準入力から数値を取得 - Qiita

を参考に書き直すことを強く推奨します。

投稿2017/07/23 15:19

yumetodo

総合スコア5850

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問