回答編集履歴
6
add_book() を改善
answer
CHANGED
@@ -200,26 +200,25 @@
|
|
200
200
|
return 0; // ok
|
201
201
|
}
|
202
202
|
|
203
|
-
TPBook * add_book(char *name, char *number, TPBook *head)
|
203
|
+
TPBook * add_book(char *name, char *number, TPBook *head) // 修正版
|
204
204
|
{
|
205
|
-
TPBook *p = head;
|
206
|
-
|
207
|
-
while (p && p->next) {
|
208
|
-
p = p->next;
|
209
|
-
}
|
210
|
-
// この時点で p はリストの最後を指している
|
211
|
-
|
212
205
|
// 追加する構造体メモリを獲得
|
213
|
-
TPBook *tp = malloc(sizeof(TPBook));
|
206
|
+
TPBook * tp = malloc(sizeof(TPBook));
|
214
207
|
|
215
208
|
// メンバを初期化する
|
216
209
|
tp->next = NULL;
|
217
210
|
strcpy(tp->name, name);
|
218
211
|
strcpy(tp->number, number);
|
219
212
|
|
220
|
-
if (
|
213
|
+
if (head == NULL) // 一回目は tp 自身が先頭になる
|
221
214
|
return tp;
|
222
215
|
|
216
|
+
TPBook *p = head;
|
217
|
+
|
218
|
+
while (p->next)
|
219
|
+
p = p->next;
|
220
|
+
|
221
|
+
// この時点で p はリストの最後を指している
|
223
222
|
// 今作った構造体 tp をリストの最後に追加する。
|
224
223
|
p->next = tp; // 新しい構造体をリストの最後に
|
225
224
|
return head; // 二回目以降は head そのまま
|
5
完全版を追加
answer
CHANGED
@@ -102,4 +102,143 @@
|
|
102
102
|
}
|
103
103
|
return 0;
|
104
104
|
}
|
105
|
+
```
|
106
|
+
---
|
107
|
+
サービス。私の手元で動作確認した完全版。
|
108
|
+
```C
|
109
|
+
#include <stdio.h>
|
110
|
+
#include <string.h>
|
111
|
+
#include <stdlib.h>
|
112
|
+
#include <ctype.h>
|
113
|
+
|
114
|
+
typedef struct TelephoneBook {
|
115
|
+
char name[16];
|
116
|
+
char number[16];
|
117
|
+
struct TelephoneBook *next;
|
118
|
+
} TPBook;
|
119
|
+
|
120
|
+
TPBook * add_book(char *name, char *num, TPBook *head);
|
121
|
+
void print_book(TPBook *p);
|
122
|
+
void free_book(TPBook *p);
|
123
|
+
int check_name(char *name);
|
124
|
+
int check_number(char *number);
|
125
|
+
|
126
|
+
int main(void)
|
127
|
+
{
|
128
|
+
TPBook *head = NULL;
|
129
|
+
char name_number[33];
|
130
|
+
char name[16]; // 入力した名前を格納する
|
131
|
+
char number[16]; // 入力した電話番号を格納する
|
132
|
+
int check_na; // 仕様通りに入力されてなければ1,\qが入力されていれば2が代入される
|
133
|
+
int check_nu; // 仕様通りに入力されてなければ1が代入される
|
134
|
+
|
135
|
+
while (1) {
|
136
|
+
printf("input>");
|
137
|
+
fgets(name_number, sizeof(name_number), stdin);
|
138
|
+
sscanf(name_number, "%s %s", name, number);
|
139
|
+
check_na = check_name(name);
|
140
|
+
|
141
|
+
if (check_na == 2) {
|
142
|
+
print_book(head);
|
143
|
+
free_book(head);
|
144
|
+
return EXIT_SUCCESS;
|
145
|
+
}
|
146
|
+
if (check_na == 1) {
|
147
|
+
printf("error");
|
148
|
+
return EXIT_FAILURE;
|
149
|
+
}
|
150
|
+
check_nu = check_number(number);
|
151
|
+
if (check_nu == 1) {
|
152
|
+
printf("error");
|
153
|
+
return EXIT_FAILURE;
|
154
|
+
}
|
155
|
+
if (check_na == 0 && check_nu == 0) {
|
156
|
+
printf("Ok\n");
|
157
|
+
}
|
158
|
+
head = add_book(name, number, head);
|
159
|
+
print_book(head); // show result
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
int check_name(char *name)
|
164
|
+
{
|
165
|
+
char *chr1 = "\q";
|
166
|
+
char *chr2 = "\Q";
|
167
|
+
|
168
|
+
if (strcmp(name, chr1) == 0 || strcmp(name, chr2) == 0)
|
169
|
+
return 2;
|
170
|
+
|
171
|
+
int len = strlen(name);
|
172
|
+
if (!isupper(name[0])) // 先頭は英大文字であるべし
|
173
|
+
return 1;
|
174
|
+
|
175
|
+
for (int i = 1; i < len; i++) {
|
176
|
+
if (!islower(name[i])) // 残りは英小文字であるべし
|
177
|
+
return 1;
|
178
|
+
}
|
179
|
+
return 0; // ok
|
180
|
+
}
|
181
|
+
|
182
|
+
int check_number(char *number)
|
183
|
+
{
|
184
|
+
/* format: 090-1234-5678 */
|
185
|
+
for (int i = 0; i <= 2; i++) { // 0, 1, 2 が
|
186
|
+
if (!isdigit(number[i])) // 数字でないなら
|
187
|
+
return 1;
|
188
|
+
}
|
189
|
+
for (int i = 4; i <= 7; i++) { // 4, 5, 6, 7 が
|
190
|
+
if (!isdigit(number[i])) // 数字でないなら
|
191
|
+
return 1;
|
192
|
+
}
|
193
|
+
for (int i = 9; i <= 12; i++) { // 9, 10, 11, 12 が
|
194
|
+
if (!isdigit(number[i])) // 数字でないなら
|
195
|
+
return 1;
|
196
|
+
}
|
197
|
+
if (number[3] != '-' || number[8] != '-') {
|
198
|
+
return 1;
|
199
|
+
}
|
200
|
+
return 0; // ok
|
201
|
+
}
|
202
|
+
|
203
|
+
TPBook * add_book(char *name, char *number, TPBook *head)
|
204
|
+
{
|
205
|
+
TPBook *p = head;
|
206
|
+
|
207
|
+
while (p && p->next) {
|
208
|
+
p = p->next;
|
209
|
+
}
|
210
|
+
// この時点で p はリストの最後を指している
|
211
|
+
|
212
|
+
// 追加する構造体メモリを獲得
|
213
|
+
TPBook *tp = malloc(sizeof(TPBook));
|
214
|
+
|
215
|
+
// メンバを初期化する
|
216
|
+
tp->next = NULL;
|
217
|
+
strcpy(tp->name, name);
|
218
|
+
strcpy(tp->number, number);
|
219
|
+
|
220
|
+
if (p == NULL) // 一回目は tp 自身が先頭になる
|
221
|
+
return tp;
|
222
|
+
|
223
|
+
// 今作った構造体 tp をリストの最後に追加する。
|
224
|
+
p->next = tp; // 新しい構造体をリストの最後に
|
225
|
+
return head; // 二回目以降は head そのまま
|
226
|
+
}
|
227
|
+
|
228
|
+
void print_book(TPBook *p)
|
229
|
+
{
|
230
|
+
while (p) {
|
231
|
+
printf("%s : %s\n", p->name, p->number);
|
232
|
+
p = p->next;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
void free_book(TPBook *p)
|
237
|
+
{
|
238
|
+
while (p) { /* 次ポインタがNULLまで処理 */
|
239
|
+
TPBook *p2 = p->next;
|
240
|
+
free(p);
|
241
|
+
p = p2;
|
242
|
+
}
|
243
|
+
}
|
105
244
|
```
|
4
for 文のバグを修正
answer
CHANGED
@@ -58,6 +58,9 @@
|
|
58
58
|
P.S.
|
59
59
|
それにしてもヘンな判定をしてますね。リスト操作をしようという段階になって、isdigit(), isupper(), islower() といった標準ライブラリ関数を知らないの?
|
60
60
|
それに、いちいちローカルな配列にコピーしなくても、そのまま判定できますよ。
|
61
|
+
for (int i = 1; i <= len; i++) { これはバグ
|
62
|
+
for (int i = 1; i < len; i++) { これが正しい
|
63
|
+
|
61
64
|
```C
|
62
65
|
#include <ctype.h>
|
63
66
|
int check_name(char *name)
|
@@ -72,7 +75,7 @@
|
|
72
75
|
if (!isupper(name[0])) // 先頭は英大文字であるべし
|
73
76
|
return 1;
|
74
77
|
|
75
|
-
for (int i = 1; i <
|
78
|
+
for (int i = 1; i < len; i++) { // !!条件を修正した!!
|
76
79
|
if (!islower(name[i])) // 残りは英小文字であるべし
|
77
80
|
return 1;
|
78
81
|
}
|
3
main() にも #ifdef ORG を
answer
CHANGED
@@ -47,8 +47,12 @@
|
|
47
47
|
```C
|
48
48
|
int main(void)
|
49
49
|
{
|
50
|
+
#ifdef ORG
|
51
|
+
struct TelephoneBook *head = NULL;
|
52
|
+
#else
|
50
|
-
|
53
|
+
struct TelephoneBook dummy = { "Dummy", "000-0000-0000", NULL };
|
51
|
-
|
54
|
+
struct TelephoneBook *head = &dummy; // ダミーエントリをポイントして開始
|
55
|
+
#endif
|
52
56
|
```
|
53
57
|
|
54
58
|
P.S.
|
2
main() の修正を追加
answer
CHANGED
@@ -43,6 +43,14 @@
|
|
43
43
|
}
|
44
44
|
```
|
45
45
|
|
46
|
+
質問者のコードは head = NULL; でスタートしており、それだとORGコードが動作するが、私のコードではSegmentation Fault を起こし動作しない。そこで例えば次のようにダミーエントリを作っておく手がある。当座をしのいで動作確認はできるはず。
|
47
|
+
```C
|
48
|
+
int main(void)
|
49
|
+
{
|
50
|
+
struct TelephoneBook dummy = { "Dummy", "000-0000-0000", NULL };
|
51
|
+
struct TelephoneBook *head = &dummy; // ダミーエントリをポイントして開始
|
52
|
+
```
|
53
|
+
|
46
54
|
P.S.
|
47
55
|
それにしてもヘンな判定をしてますね。リスト操作をしようという段階になって、isdigit(), isupper(), islower() といった標準ライブラリ関数を知らないの?
|
48
56
|
それに、いちいちローカルな配列にコピーしなくても、そのまま判定できますよ。
|
1
修正した関数を追加
answer
CHANGED
@@ -44,4 +44,47 @@
|
|
44
44
|
```
|
45
45
|
|
46
46
|
P.S.
|
47
|
-
それにしてもヘンな判定をしてますね。リスト操作をしようという段階になって、isdigit(), isupper(), islower() といった標準ライブラリ関数を知らないの?
|
47
|
+
それにしてもヘンな判定をしてますね。リスト操作をしようという段階になって、isdigit(), isupper(), islower() といった標準ライブラリ関数を知らないの?
|
48
|
+
それに、いちいちローカルな配列にコピーしなくても、そのまま判定できますよ。
|
49
|
+
```C
|
50
|
+
#include <ctype.h>
|
51
|
+
int check_name(char *name)
|
52
|
+
{
|
53
|
+
char *chr1 = "\q";
|
54
|
+
char *chr2 = "\Q";
|
55
|
+
|
56
|
+
if (strcmp(name, chr1) == 0 || strcmp(name, chr2) == 0)
|
57
|
+
return 2;
|
58
|
+
|
59
|
+
int len = strlen(name);
|
60
|
+
if (!isupper(name[0])) // 先頭は英大文字であるべし
|
61
|
+
return 1;
|
62
|
+
|
63
|
+
for (int i = 1; i <= len; i++) {
|
64
|
+
if (!islower(name[i])) // 残りは英小文字であるべし
|
65
|
+
return 1;
|
66
|
+
}
|
67
|
+
return 0; // OK
|
68
|
+
}
|
69
|
+
|
70
|
+
int check_number(char *number)
|
71
|
+
{
|
72
|
+
/* number[] format: 090-1234-5678 */
|
73
|
+
for (int i = 0; i <= 2; i++) { // 0, 1, 2 が
|
74
|
+
if (!isdigit(number[i])) // 数字でないなら
|
75
|
+
return 1;
|
76
|
+
}
|
77
|
+
for (int i = 4; i <= 7; i++) { // 4, 5, 6, 7 が
|
78
|
+
if (!isdigit(number[i])) // 数字でないなら
|
79
|
+
return 1;
|
80
|
+
}
|
81
|
+
for (int i = 9; i <= 12; i++) { // 9, 10, 11, 12 が
|
82
|
+
if (!isdigit(number[i])) // 数字でないなら
|
83
|
+
return 1;
|
84
|
+
}
|
85
|
+
if (number[3] != '-' || number[8] != '-') {
|
86
|
+
return 1;
|
87
|
+
}
|
88
|
+
return 0;
|
89
|
+
}
|
90
|
+
```
|