ケンシロウさん。なんと最後の章です。(ダジャレです。)
長かったなあ~。日記を更新しようと思ったらでかいミスが見つかって修正がやっと終わりました。
問題は全部で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[c - 1] > exam[c]){
d = c - 1;
swap(int, exam[c], 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);
・治した方がいい癖
プログラムを修正していて、余った変数を
変数がほしくなった時にその余った変数を使う。
てな感じで次に進むー。