下記の住所録プログラムについて分からないところを質問させてください。
質問1:if (1 <= i && i <= 5) cnt = func[i - 1](ad, cnt);
質問2:while (j++ < cnt){}条件がよくわかりません
質問3:for (j = i - 1; j < cnt - 1; j++)
ap[j]= ap[j + 1];がいまいちわかりません。
よろしくお願いします。
コード // アドレス帳 住所録プログラム #include <stdio.h> #include <stdlib.h> #include <string.h> // プログラム中で多用する配列の大きさ #define BUFSIZE 128 #define DATASIZE 100 // 構造体の宣言 -- typedefを使用して以後srtuctを省略できるようにした typedef struct address { char szAdd[51]; // 住所 char szName[21]; // 氏名 char szTel[21]; // 電話番号 } Address; // 関数のプロトタイプ宣言 -- ジャンプテーブルに入れるため引数及び返却値型は // すべて同じとした int search(Address *ap, int cnt); int add(Address *ap, int cnt); int amend(Address *ap, int cnt); int del(Address *ap, int cnt); int printall(Address *ap, int cnt); // 関数のジャンプテーブル int (*func[])(Address *, int) = {search, add, amend, del, printall}; // 処理を番号で選ばせ、所定の関数に飛ばす // 処理によっては配列の要素数が変化する事があるので常に要素数 cnt を返させる // 構造体の配列 -- 大きくてスタックを消費する可能性があるので静的に定義した Address ad[DATASIZE]; int main(void) { char dummy[BUFSIZE]; int i, cnt = 0; while (1) { puts("●メニューを入力して下さい"); puts("1.検索\n2.追加\n3.修正\n4.削除\n5.全体表\示\n6.終了"); scanf("%d", &i); gets(dummy); if (1 <= i && i <= 5) cnt = func[i - 1](ad, cnt); //cntは要素番号 else if (i == 6) break; } return 0; } // 検索するデータをswitch文によって処理を選択 int search(Address *ap, int cnt) { char buf[BUFSIZE], dummy[BUFSIZE]; char *target[] = {"住所", "氏名", "電話番号"}; int i, j = 0, count = 0; Address *t = ap; while (1) { puts("何で探しますか?\n1.住所 2.氏名 3.電話番号"); scanf("%d", &i); gets(dummy); //scanfは変換が終わったら入力の残りをそのままにします。 //つまり、改行が内部バッファーに残り、これがgetsに渡ってしまいます。 //getsはこれを受け取り、新たなキー入力を待たずに終了してしまいます。 //一番簡単な修正はscanf後にfgetsでダミーで一行を読み込むことでしょう。 if (1 <= i && i <= 3) break; } printf("%sを入力して下さい:", target[--i]); gets(buf); while (j++ < cnt) { switch (i) { case 0: // 住所 if (!strcmp(t->szAdd, buf)) goto print; break; case 1: // 氏名 if (!strcmp(t->szName, buf)) goto print; break; case 2: // 電話番号 if (!strcmp(t->szTel, buf)) goto print; break; default: // no condition、ここには来ない break; } t++; continue; print:; printf("%d: 住所:%s 氏名:%s 電話番号:%s\n", j, t->szAdd, t->szName, t->szTel); t++; count++; } printf("%d件見つかりました\n", count); return cnt; } // 構造体の*最後*の次に新しいデータを付け加える // もし既に構造体の配列が一杯になっていたら警告を発して戻る // 追加に成功したら構造体の要素数が 1 増えるので cnt + 1 を返す int add(Address *ap, int cnt) { Address *t = ap + cnt; // 配列の最後の次のアドレスの計算 、配列の最後の要素の // 次のアドレスを指してもよい if (cnt == DATASIZE) { puts("これ以上追加できません"); return cnt; } printf("住所:"); // 住所 gets(t->szAdd); printf("氏名:"); // 氏名 gets(t->szName); printf("電話番号:"); // 電話番号 gets(t->szTel); // 表示 // printf("%s %s %s\n", t->szAdd, t->szName, t->szTel); return cnt + 1; } // 任意の構造体の内容を修正する // 修正しない要素はreturnで飛ばせるようにした int amend(Address *ap, int cnt) { Address *t; char buf[BUFSIZE]; int i; puts("何番を修正しますか?"); scanf("%d", &i); gets(buf); if (i > 0 && i <= cnt) { t = ap + i - 1; // 配列のアドレスの計算 puts("変更しない場合は単に[return]を押して下さい"); printf("住所: %s -> ", t->szAdd); gets(buf); if (strlen(buf)) strcpy(t->szAdd, buf); printf("氏名: %s -> ", t->szName); gets(buf); if (strlen(buf)) strcpy(t->szName, buf); printf("電話番号: %s -> ", t->szTel); gets(buf); if (strlen(buf)) strcpy(t->szTel, buf); } else puts("番号が不適切です"); return cnt; } // 任意の構造体を削除する // 削除方法はそれより後ろの構造体を一つ前にずらし cnt - 1 を返す // i == cnt の時は実際には cnt - 1 を返すだけである int del(Address *ap, int cnt) { char buf[BUFSIZE]; int i, j; puts("何番を削除しますか?"); scanf("%d", &i); gets(buf); if (i > 0 && i <= cnt) { for (j = i - 1; j < cnt - 1; j++) ap[j]= ap[j + 1]; return cnt - 1; } else { puts("番号が不適切です"); return cnt; } } // 格納された構造体を全部表示する // 構造体には番号が付いてないので、カウンタ i で内部的に処理する(構造体の添え字i + 1) int printall(Address *ap, int cnt) { int i = 0; while (i < cnt) { printf("%d: 住所:%s 氏名:%s 電話番号:%s\n", ++i, ap->szAdd, ap->szName, ap->szTel); ap++; // 配列へのポインタが次の配列要素を指すようにする } return cnt; }
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/11/12 10:24
2017/11/12 10:48
退会済みユーザー
2017/11/12 11:01
2017/11/12 11:12