ケンシロウさん。なんと最後の章です。(ダジャレです。)
長かったなあ~。日記を更新しようと思ったらでかいミスが見つかって修正がやっと終わりました。
問題は全部で5個なんだけど、いくつかをピックアップして1個のそーすにまとめました。
結果的に扱った問題はこんな感じです。
課題10-1から、月名の英単語を学習するプログラムを作る。ランダムな順序で出題する。
不正解の場合は正解を見るか確認して表示する。
ある月に対して5回間違えた場合は、確認することなく正解を表示する。
最後に学習結果を表示させる。正解した月を昇順に表示する。
課題10-2はスルー。
課題10-3はスルー。
課題10-4から、外部からファイルを読み込むようにする。
課題10-5はスルー。
こうしてみるとほとんどスルーしているなあ・・・。
まあいい!(自由な課題だし)
そーす
$ cat list10-11.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#define swap(type, x, y) do { type t = x; x = y; y = t; } while (0)
int QNO;
char **jptr;
char **eptr;
// 単語を読み込む
int
read_tango(char *argv)
{
int i;
FILE *fp;
printf("ファイル名 %s \n", argv);
if((fp = fopen(argv, "r")) == NULL) goto Free;
fscanf(fp, "%d", &QNO);
if((jptr = calloc(QNO, sizeof(char *))) == NULL) goto Free;
if((eptr = calloc(QNO, sizeof(char *))) == NULL) goto Free;
for(i = 0; i < QNO; i++){
char etemp[1024];
char jtemp[1024];
fscanf(fp, "%s%s", etemp, jtemp);
if((eptr[i] = malloc(strlen(etemp) + 1)) == NULL) goto Free;
if((jptr[i] = malloc(strlen(jtemp) + 1)) == NULL) goto Free;
strcpy(eptr[i], etemp);
strcpy(jptr[i], jtemp);
}
fclose(fp);
return 0;
Free:
for(i = 0; i < QNO; i++){
free(eptr[i]);
free(jptr[i]);
}
free(jptr);
free(eptr);
return 1;
}
int
main(int argc, char *argv[])
{
int i;
int ok = 0;
int nq;
int na;
int sw;
int retry;
int stage;
if(read_tango(*++argv) == 1){
printf("単語ファイルの読み込み失敗\n");
return 1;
}
srand(time(NULL));
int q, r;
int pq[QNO];
for(r = 0; r < QNO; r++){
do{
nq = rand() % QNO;
for(q = 0; q < r; q++)
if(nq == pq[q])
break;
}while(q < r);
pq[r] = nq;
}
int mi=0;
int *exam;
exam = calloc(QNO, sizeof(int));
if(exam == NULL){puts("examの確保に失敗"); return 1;}
for(stage = 0; stage < QNO; stage++){
char answer[1024];
int num = 0; //間違い回数、初期化
int nocon = 0; //ギブアップ初期化
printf("\n%d問目\n%s ? : ", stage+1, jptr[pq[stage]]);
do{
scanf("%s", &answer);
if(strcmp(answer, eptr[pq[stage]]) == 0){
printf("せいかい!!\n");
exam[mi++] = pq[stage];
ok++;
break;
}
printf("間違いです。\n正解をみたいですか?? yes = 9 : ");
scanf("%d", &nocon);
if(nocon == 9){
printf("正解は%sですよ。 \n\n", eptr[pq[stage]]);
break; //正解を見たら次のゲームへ
}else {printf("入力してください\n");}
num++; //間違い回数追加
// 5回間違いで強制的に次に進む。
if(num == 5){
printf("正解は%sですよ。\n\n", eptr[pq[stage]]);
break;
}
}while(strcmp(answer, eptr[pq[stage]]) != 0);
}
int ch, dh;
int min;
min = ok - 1;
while(min >= 0){
int c, d;
for(c = 1, d = -1; c <= min; c++)
if(exam > exam){
d = c - 1;
swap(int, exam, exam[d]);
}
min = d;
}
printf("正解したのは");
if(ok > 0) printf("%d個で、", ok);
if(ok == 0) puts("ない!もっとがんばれ");
for(ch = 0; ch < ok; ch++){printf("%s", jptr[exam[ch]]);}
puts("\n");
for(i = 0; i < QNO; i++){
free(eptr[i]);
free(jptr[i]);
}
free(jptr);
free(eptr);
return 0;
}
今回は一部を修正っていう訳ではないので、そーすが汚い!
まあいい。
実行結果 何個かわざと間違えてるんだよ。
$ ./a.out YEAR ファイル名 YEAR 1問目 4月 ? : april せいかい!! 2問目 10月 ? : octobar 間違いです。 正解をみたいですか?? yes = 9 : 9 正解はoctoberですよ。 3問目 8月 ? : august せいかい!! 4問目 6月 ? : july 間違いです。 正解をみたいですか?? yes = 9 : 9 正解はjuneですよ。 5問目 11月 ? : november せいかい!! 6問目 12月 ? : december せいかい!! 7問目 2月 ? : february せいかい!! 8問目 3月 ? : march せいかい!! 9問目 7月 ? : june 間違いです。 正解をみたいですか?? yes = 9 : 9 正解はjulyですよ。 10問目 9月 ? : september せいかい!! 11問目 1月 ? : january せいかい!! 12問目 5月 ? : may せいかい!! 正解したのは9個で、1月2月3月4月5月8月9月11月12月
日記更新前に見つかった失敗がなかなか治せなかったんだけど、ピースがうまくはまったときは気持ちいいもんだな。
最後の10章でいくつか気になった点があったのでメモ書き。
・似てるけど違うものらしい。
*p[15]; (*p)[15]; は意味が違う らしい
・2次元配列をメモリ確保するとこんな弱点ができるらしい。
2次元配列をmallocで確保する 文字列は何個: 3 p[0] : fwagjfpawfhawh4t08awyhtg08awyharghawrgarga p[1] : jfawfjawhfawfhawufh0a8hw04awhfa p[2] : afhwhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff p[0] = fwagjfpawfhawh4jfawfjawhfawfhaafhwhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff p[1] = jfawfjawhfawfhaafhwhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff p[2] = afhwhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff *** glibc detected *** ./a.out: free(): invalid next size (fast): 0x0000000001088010 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x76166)[0x7f3e0a10b166] /lib64/libc.so.6(+0x78c93)[0x7f3e0a10dc93] ./a.out[0x40070e] /lib64/libc.so.6(__libc_start_main+0xfd)[0x7f3e0a0b3d1d] ./a.out[0x400549] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 fd:00 920273 /home/takochan/c/program/a.out 00600000-00601000 rw-p 00000000 fd:00 920273 /home/takochan/c/program/a.out 01088000-010a9000 rw-p 00000000 00:00 0 [heap] 7f3e09e7f000-7f3e09e95000 r-xp 00000000 fd:00 914334 /lib64/libgcc_s-4.4.7-20120601.so.1 7f3e09e95000-7f3e0a094000 ---p 00016000 fd:00 914334 /lib64/libgcc_s-4.4.7-20120601.so.1 7f3e0a094000-7f3e0a095000 rw-p 00015000 fd:00 914334 /lib64/libgcc_s-4.4.7-20120601.so.1 7f3e0a095000-7f3e0a220000 r-xp 00000000 fd:00 913935 /lib64/libc-2.12.so 7f3e0a220000-7f3e0a41f000 ---p 0018b000 fd:00 913935 /lib64/libc-2.12.so 7f3e0a41f000-7f3e0a423000 r--p 0018a000 fd:00 913935 /lib64/libc-2.12.so 7f3e0a423000-7f3e0a424000 rw-p 0018e000 fd:00 913935 /lib64/libc-2.12.so 7f3e0a424000-7f3e0a429000 rw-p 00000000 00:00 0 7f3e0a429000-7f3e0a449000 r-xp 00000000 fd:00 913925 /lib64/ld-2.12.so 7f3e0a63e000-7f3e0a641000 rw-p 00000000 00:00 0 7f3e0a644000-7f3e0a648000 rw-p 00000000 00:00 0 7f3e0a648000-7f3e0a649000 r--p 0001f000 fd:00 913925 /lib64/ld-2.12.so 7f3e0a649000-7f3e0a64a000 rw-p 00020000 fd:00 913925 /lib64/ld-2.12.so 7f3e0a64a000-7f3e0a64b000 rw-p 00000000 00:00 0 7fffd7f5b000-7fffd7f70000 rw-p 00000000 00:00 0 [stack] 7fffd7fff000-7fffd8000000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] アボートしました
・mallocとcallocの違い
malloc #include <stdlib.h> void *malloc(size_t size); calloc #include <stdlib.h. void *calloc(size_t nmemb, size_t size);
・治した方がいい癖
プログラムを修正していて、余った変数を 変数がほしくなった時にその余った変数を使う。
てな感じで次に進むー。