質問編集履歴

6

コードの修正

2018/01/30 06:17

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -64,68 +64,34 @@
64
64
 
65
65
 
66
66
 
67
- //assert.hでは、assertマクロが定義されています。
68
-
69
-
70
-
71
- //assertマクロは関数形式マクロで、引数に偽(すなわち0)が指定されると、
72
-
73
- //ソースファイル名や行番号等の情報を標準エラー出力に出力し、
74
-
75
- //プログラムを終了させます。
76
-
77
- //プログラマは、assertマクロが出力する情報をもとにデバッグを行います。
78
-
79
-
80
-
81
- //NDEBUGマクロが定義されていると、assertマクロは、次のように定義され、
82
-
83
- //何もしません。
67
+ #define N 256
84
-
68
+
85
- //#define assert(ignore) ((void)0)
69
+ #define FILENAME "address.csv"
70
+
71
+
72
+
73
+ struct address{
74
+
75
+ char name[N];
76
+
77
+ char address[N];
78
+
79
+ char tel[N]; // 電話番号
80
+
81
+ char mail[N];
82
+
83
+ struct address *next;
84
+
85
+ struct address *before;
86
+
87
+ };
86
88
 
87
89
 
88
90
 
89
- #define N 256
90
-
91
- #define FILENAME "address.csv"
92
-
93
-
94
-
95
- struct address{
96
-
97
- char name[N];
98
-
99
- char address[N];
100
-
101
- char tel[N]; // 電話番号
102
-
103
- char mail[N];
104
-
105
- struct address *next;
106
-
107
- struct address *before;
108
-
109
- };
110
-
111
-
112
-
113
91
  void data_show(struct address* head);
114
92
 
115
- void data_add(struct address** head);
116
-
117
- void data_delete(struct address** head);
118
-
119
93
  void data_sort(struct address** head);
120
94
 
121
- void data_write(struct address* head);
122
-
123
-
124
-
125
- void data_amend(struct address* head);
126
-
127
- void data_search(struct address* head);
128
-
129
95
 
130
96
 
131
97
  void chop(char *p){
@@ -134,644 +100,396 @@
134
100
 
135
101
  ;
136
102
 
103
+
104
+
105
+ p--;
106
+
107
+ while (*p == '\r' || *p == '\n')
108
+
109
+ *(p--) = 0;
110
+
111
+
112
+
113
+ }
114
+
115
+
116
+
117
+ void list_add(struct address **head, char *name, char *address, char *tel, char *mail)
118
+
119
+ {
120
+
121
+ struct address *p;
122
+
123
+ if ((p = malloc(sizeof(struct address))) != 0) {
124
+
125
+
126
+
127
+ strcpy(p->name, name);
128
+
129
+
130
+
131
+ strcpy(p->address, address);
132
+
137
133
 
138
134
 
135
+ strcpy(p->tel, tel);
136
+
137
+
138
+
139
+ strcpy(p->mail, mail);
140
+
141
+
142
+
139
- p--;
143
+ p->next = *head;
140
-
141
-
142
-
144
+
143
- while (*p == '\r' || *p == '\n')
145
+ if (p->next != 0)
146
+
144
-
147
+ p->next->before = p;
148
+
149
+ p->before = 0;
150
+
145
- *(p--) = 0;
151
+ *head = p;
152
+
153
+ }
154
+
155
+ }
156
+
157
+
158
+
159
+
160
+
161
+ void data_show(struct address *head) {
162
+
163
+ if (head != 0) {
164
+
165
+ printf(" %s, %s, %s, %s\n", head->name, head->address, head->tel, head->mail);
166
+
167
+ data_show(head->next);
168
+
169
+ }
170
+
171
+ }
172
+
173
+
174
+
175
+ struct address **listmin(struct address **head) {
176
+
177
+ struct address **p;
178
+
179
+
180
+
181
+ if (*head == 0)
182
+
183
+ return 0;
184
+
185
+ if ((*head)->next == 0)
186
+
187
+ return head;
188
+
189
+ //
190
+
191
+
192
+
193
+ if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0)
194
+
195
+ return head;
196
+
197
+ else
198
+
199
+ return p;
200
+
201
+ }
202
+
203
+
204
+
205
+ //大小を入れ替える
206
+
207
+ void exchange(struct address **p, struct address **q)
208
+
209
+ {
210
+
211
+ struct address *r, *s, *t;
212
+
213
+ assert(*p != 0 && *q != 0);
214
+
215
+
216
+
217
+ if (p == q)
218
+
219
+ return;
146
220
 
147
221
 
148
222
 
223
+ r = *p; s = *q;
224
+
225
+ if (&((*p)->next) == q || &((*q)->next) == p) {
226
+
227
+
228
+
229
+ if (s->next != 0){
230
+
231
+
232
+
233
+ s->next->before = r;
234
+
235
+
236
+
237
+ }
238
+
239
+ s->before = r->before;
240
+
241
+
242
+
243
+ r->before = s;
244
+
245
+
246
+
247
+ *p = s;
248
+
249
+
250
+
251
+ *q = s->next;
252
+
253
+
254
+
255
+ s->next = r;
256
+
257
+
258
+
259
+ return;
260
+
261
+ } else {
262
+
263
+ if (s->next != 0)
264
+
265
+
266
+
267
+ s->next->before = r;
268
+
269
+
270
+
271
+ if (r->next != 0)
272
+
273
+
274
+
275
+ r->next->before = s;
276
+
277
+
278
+
279
+ t = s->before;
280
+
281
+
282
+
283
+ s->before = r->before;
284
+
285
+
286
+
287
+ r->before = t;
288
+
289
+
290
+
291
+ t = r->next;
292
+
293
+
294
+
295
+ r->next = s->next;
296
+
297
+
298
+
299
+ s->next = t;
300
+
301
+
302
+
303
+ *p = s;
304
+
305
+ *q = r;
306
+
307
+ }
308
+
149
309
  }
150
310
 
151
311
 
152
312
 
153
- void list_add(struct address **head, char *name, char *address, char *tel, char *mail)
313
+ void data_sort(struct address **head)
154
314
 
155
315
  {
156
316
 
157
- struct address *p;
317
+ struct address **p;
318
+
319
+
320
+
158
-
321
+ if (*head != 0) {
322
+
323
+ for (;;) {
324
+
325
+ p = listmin(head);
326
+
327
+ //関数listmin(head)は、名前からリストの全ての要素をチェックして、
328
+
329
+ //いちばん小さいnameを持つ要素を返していると思われます。
330
+
331
+ //そうでないと正しくソートされません。
332
+
333
+
334
+
335
+ if (p == 0)break;
336
+
337
+
338
+
339
+ exchange(head, p);
340
+
341
+ //大小を入れ替える
342
+
343
+
344
+
345
+ head = &((*head)->next);
346
+
347
+ //見つけたいちばん小さい要素を関数exchange(head, p)で先頭に移動しています。
348
+
349
+ }
350
+
351
+ }
352
+
353
+ }
354
+
355
+
356
+
159
- if ((p = malloc(sizeof(struct address))) != 0) {
357
+ void release(struct address **head)
358
+
359
+ {
360
+
361
+ if (*head != 0) {
362
+
363
+ release( &((*head)->next) );
364
+
365
+ free(*head);
366
+
367
+ *head = 0;
368
+
369
+ }
370
+
371
+ }
372
+
373
+
374
+
375
+ int main()
376
+
377
+ {
378
+
379
+ struct address *head;
380
+
381
+ FILE* fp;
382
+
383
+ static char buff[N], name[N], address[N], tel[N], mail[N];
384
+
385
+ char *token=",";
386
+
387
+
388
+
389
+ head = 0;
160
390
 
161
391
 
162
392
 
163
- strcpy(p->name, name);
393
+ if ((fp = fopen(FILENAME,"r")) != 0) {
164
-
165
-
166
-
394
+
167
- strcpy(p->address, address);
395
+ while(fgets(buff, N, fp) != 0){
396
+
168
-
397
+ //本当の大元の文字列を書き換えないようにするために
398
+
169
-
399
+ //bufを確保してコピーし、それをstrtok()の引数にしている。
400
+
170
-
401
+ char *p;
402
+
171
- strcpy(p->tel, tel);
403
+ chop(buff);
404
+
405
+ printf( "ファイルから読んだ文字列:%s\n", buff );
172
406
 
173
407
 
174
408
 
409
+ p = strtok(buff, token);
410
+
411
+ if ( p != NULL ) {
412
+
413
+ strcpy(name, p);
414
+
415
+ } else {
416
+
417
+ printf( "氏名の切り出しに失敗しました。\n");
418
+
419
+ break;
420
+
421
+ }
422
+
423
+ p = strtok(NULL, token);
424
+
175
425
 
176
426
 
427
+ if ( p != NULL ) {
428
+
177
- strcpy(p->mail, mail);
429
+ strcpy(address, p);
430
+
431
+ } else {
432
+
433
+ printf( "住所の切り出しに失敗しました。\n");
434
+
435
+ break;
436
+
437
+ }
438
+
439
+ p = strtok(NULL, token);
178
440
 
179
441
 
180
442
 
443
+ if ( p != NULL ) {
444
+
445
+ strcpy(tel, p);
446
+
447
+ } else {
448
+
449
+ printf( "電話番号の切り出しに失敗しました。\n");
450
+
451
+ break;
452
+
453
+ }
454
+
455
+ p = strtok(NULL, token);
456
+
181
457
 
182
458
 
183
- p->next = *head;
184
-
185
- if (p->next != 0)
459
+ if ( p != NULL ) {
186
-
187
- p->next->before = p;
460
+
188
-
189
- p->before = 0;
461
+ strcpy(mail, p);
462
+
190
-
463
+ } else {
464
+
465
+ printf( "メールアドレスの切り出しに失敗しました。\n");
466
+
191
- *head = p;
467
+ break;
192
-
468
+
193
- }
469
+ }
470
+
471
+ list_add(&head, name, address, tel, mail);
472
+
473
+ }
474
+
475
+ fclose(fp);
476
+
477
+ }
478
+
479
+ data_sort(&head);
480
+
481
+ data_show(head);
482
+
483
+
484
+
485
+ release(&head);
486
+
487
+ return 0;
194
488
 
195
489
  }
196
490
 
197
491
 
198
492
 
199
-
200
-
201
- void data_show(struct address *head) {
202
-
203
- if (head != 0) {
204
-
205
- printf(" %s, %s, %s, %s\n", head->name, head->address, head->tel, head->mail);
206
-
207
- data_show(head->next);
208
-
209
- }
210
-
211
- }
212
-
213
-
214
-
215
- struct address **listmin(struct address **head) {
216
-
217
- struct address **p;
218
-
219
-
220
-
221
- if (*head == 0)
222
-
223
- return 0;
224
-
225
- if ((*head)->next == 0)
226
-
227
- return head;
228
-
229
- //
230
-
231
-
232
-
233
- if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0)
234
-
235
- return head;
236
-
237
- else
238
-
239
- return p;
240
-
241
- }
242
-
243
-
244
-
245
- //大小を入れ替える
246
-
247
- void exchange(struct address **p, struct address **q)
248
-
249
- {
250
-
251
- struct address *r, *s, *t;
252
-
253
- assert(*p != 0 && *q != 0);
254
-
255
-
256
-
257
- if (p == q)
258
-
259
- return;
260
-
261
-
262
-
263
- r = *p; s = *q;
264
-
265
- if (&((*p)->next) == q || &((*q)->next) == p) {
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
- // &((*p)->next) == q において、**pはaddress構造体型ですから、
308
-
309
- //*pはaddress構造体へのポインタです。
310
-
311
- //従って、(*p)もaddress構造体へのポインタです。
312
-
313
- //であれば、(*p)->nextはaddress構造体のnextメンバですね。
314
-
315
- //ならば、&((*p)->next)はそのアドレスですから、nextメンバのアドレスとなります。
316
-
317
-
318
-
319
- //それと q が等しいという条件ですから、qはadress構造体のnextメンバを
320
-
321
- //ポイントしているのだろうと思います。
322
-
323
-
324
-
325
- //つまり、*pが指すaddress構造体のnextメンバを
326
-
327
- //qがポイントしているならば、この条件が成立します。
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
- if (s->next != 0){
336
-
337
- s->next->before = r;
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
- }
396
-
397
- s->before = r->before;
398
-
399
-
400
-
401
-
402
-
403
- r->before = s;
404
-
405
-
406
-
407
- *p = s;
408
-
409
-
410
-
411
-
412
-
413
- *q = s->next;
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
- s->next = r;
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469
- return;
470
-
471
- } else { //if ((&((*p)->next)) != q && (&((*q)->next) != p)) の時だと思う
472
-
473
- if (s->next != 0)
474
-
475
- // (*q)->nextが0でないとき
476
-
477
-
478
-
479
- s->next->before = r;
480
-
481
- // (s->next)->before=*p
482
-
483
-
484
-
485
- if (r->next != 0)
486
-
487
- // (*p)->nextが0でないとき
488
-
489
-
490
-
491
- r->next->before = s;
492
-
493
- // (r->next)->before=*q
494
-
495
-
496
-
497
- t = s->before;
498
-
499
- // s->before==(*q)->before
500
-
501
- // t=(*q)->before
502
-
503
-
504
-
505
- s->before = r->before;
506
-
507
- // s->beforeにr->before==(*p)->before(これはポインタ)を代入する。
508
-
509
-
510
-
511
- r->before = t;
512
-
513
- // r->before==(*p)->before
514
-
515
- // t=s->before
516
-
517
- // r->beforeにs->before==(*q)->before(これはポインタ)を代入する。
518
-
519
-
520
-
521
- t = r->next;
522
-
523
- // r->next==(*p)->nextが0でないときであるから
524
-
525
- // t=(*p)->next
526
-
527
-
528
-
529
- r->next = s->next;
530
-
531
- // s->next==(*q)->next
532
-
533
- // r->next =(*q)->next
534
-
535
-
536
-
537
- s->next = t;
538
-
539
- // t=(*p)->next
540
-
541
- // s->next=(*p)->next
542
-
543
-
544
-
545
- *p = s;
546
-
547
- *q = r;
548
-
549
- }
550
-
551
- }
552
-
553
-
554
-
555
- void data_sort(struct address **head)
556
-
557
- {
558
-
559
- struct address **p;
560
-
561
-
562
-
563
- if (*head != 0) {
564
-
565
- for (;;) {
566
-
567
- p = listmin(head);
568
-
569
- //関数listmin(head)は、名前からリストの全ての要素をチェックして、
570
-
571
- //いちばん小さいnameを持つ要素を返していると思われます。
572
-
573
- //そうでないと正しくソートされません。
574
-
575
-
576
-
577
- if (p == 0)break;
578
-
579
- //「リストの先頭が空のとき、返り値が0になるので、ソートが完了したとして、
580
-
581
- //ループを抜けます。」ですね.
582
-
583
-
584
-
585
- //次のように使うことが出来る。
586
-
587
-
588
-
589
- // char *p = NULL;
590
-
591
-
592
-
593
- // if (!p) { … /* if (p==0) と等価 */
594
-
595
-
596
-
597
- //世の中には様々なマイクロプロセッサーがあり、
598
-
599
- //現実にNULLポインターの内部表現が「0番地」では無いものも存在する。
600
-
601
-
602
-
603
- //しかしこの場合でも、ソースコード中の値は0のままで良い。
604
-
605
- //なぜなら、NULLポインターというものは抽象的な概念であり、
606
-
607
- //物理的なアドレスを指しているわけではないからである。
608
-
609
-
610
-
611
- //もし内部表現が0でない計算機の場合、必要に応じてCコンパイラーは
612
-
613
- //その値に自動的に変換してくれる。
614
-
615
- //従って、NULLポインターと0は完全に等価であり、
616
-
617
- //可換であるとして扱うことが出来るのである。
618
-
619
-
620
-
621
- exchange(head, p);
622
-
623
- //大小を入れ替える
624
-
625
-
626
-
627
- head = &((*head)->next);
628
-
629
- //見つけたいちばん小さい要素を関数exchange(head, p)で先頭に移動しています。
630
-
631
- }
632
-
633
- }
634
-
635
- }
636
-
637
-
638
-
639
- void release(struct address **head)
640
-
641
- {
642
-
643
- if (*head != 0) {
644
-
645
- release( &((*head)->next) );
646
-
647
- free(*head);
648
-
649
- *head = 0;
650
-
651
- }
652
-
653
- }
654
-
655
-
656
-
657
- int main()
658
-
659
- {
660
-
661
- struct address *head;
662
-
663
- FILE* fp;
664
-
665
- static char buff[N], name[N], address[N], tel[N], mail[N];
666
-
667
- char *token=",";
668
-
669
-
670
-
671
- head = 0;
672
-
673
-
674
-
675
- if ((fp = fopen(FILENAME,"r")) != 0) {
676
-
677
- while(fgets(buff, N, fp) != 0){
678
-
679
- //本当の大元の文字列を書き換えないようにするために
680
-
681
- //bufを確保してコピーし、それをstrtok()の引数にしている。
682
-
683
- char *p;
684
-
685
- chop(buff);
686
-
687
- printf( "ファイルから読んだ文字列:%s\n", buff );
688
-
689
-
690
-
691
- p = strtok(buff, token);
692
-
693
- if ( p != NULL ) {
694
-
695
- strcpy(name, p);
696
-
697
- } else {
698
-
699
- printf( "氏名の切り出しに失敗しました。\n");
700
-
701
- break;
702
-
703
- }
704
-
705
- p = strtok(NULL, token);
706
-
707
-
708
-
709
- if ( p != NULL ) {
710
-
711
- strcpy(address, p);
712
-
713
- } else {
714
-
715
- printf( "住所の切り出しに失敗しました。\n");
716
-
717
- break;
718
-
719
- }
720
-
721
- p = strtok(NULL, token);
722
-
723
-
724
-
725
- if ( p != NULL ) {
726
-
727
- strcpy(tel, p);
728
-
729
- } else {
730
-
731
- printf( "電話番号の切り出しに失敗しました。\n");
732
-
733
- break;
734
-
735
- }
736
-
737
- p = strtok(NULL, token);
738
-
739
-
740
-
741
- if ( p != NULL ) {
742
-
743
- strcpy(mail, p);
744
-
745
- } else {
746
-
747
- printf( "メールアドレスの切り出しに失敗しました。\n");
748
-
749
- break;
750
-
751
- }
752
-
753
- list_add(&head, name, address, tel, mail);
754
-
755
- }
756
-
757
- fclose(fp);
758
-
759
- }
760
-
761
- data_sort(&head);
762
-
763
- data_show(head);
764
-
765
-
766
-
767
- release(&head);
768
-
769
- return 0;
770
-
771
- }
772
-
773
-
774
-
775
493
  /* 実行結果
776
494
 
777
495
  naka@naka ~
@@ -834,6 +552,8 @@
834
552
 
835
553
 
836
554
 
555
+
556
+
837
557
  /* 実行結果
838
558
 
839
559
  naka@naka ~
@@ -894,6 +614,8 @@
894
614
 
895
615
 
896
616
 
617
+
618
+
897
619
  /* 実行結果
898
620
 
899
621
  naka@naka ~
@@ -954,6 +676,66 @@
954
676
 
955
677
 
956
678
 
679
+ /* 実行結果
680
+
681
+ naka@naka ~
682
+
683
+ $ cd kadai/kadai9-8
684
+
685
+
686
+
687
+ naka@naka ~/kadai/kadai9-8
688
+
689
+ $ gcc -o kad9-8b kad9-8b.c -Wall
690
+
691
+
692
+
693
+ naka@naka ~/kadai/kadai9-8
694
+
695
+ $ kad9-8b
696
+
697
+ ファイルから読んだ文字列:yamada,tone,090-1122,mail-9
698
+
699
+ ファイルから読んだ文字列:hosi,nagoya,5436,mail-7
700
+
701
+ ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2
702
+
703
+ ファイルから読んだ文字列:koko,yosida,090-2314,mail-6
704
+
705
+ ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1
706
+
707
+ ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8
708
+
709
+ ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3
710
+
711
+ ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5
712
+
713
+ hosi, nagoya, 5436, mail-7
714
+
715
+ kato, kanagawa, 080-8888, mail-2
716
+
717
+ koko, yosida, 090-2314, mail-6
718
+
719
+ naka, kamikosaka, 080-4444, mail-1
720
+
721
+ nakada, nogata, 090-6376, mail-8
722
+
723
+ saito, yamanashi, 080-6666, mail-3
724
+
725
+ suzuki, saitama, 090-2222, mail-5
726
+
727
+ yamada, tone, 090-1122, mail-9
728
+
729
+
730
+
731
+ naka@naka ~/kadai/kadai9-8
732
+
733
+ $
734
+
735
+ */
736
+
737
+
738
+
957
739
 
958
740
 
959
741
 

5

コード修正

2018/01/30 06:17

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -54,18 +54,6 @@
54
54
 
55
55
 
56
56
 
57
- //codepad.org/B83f1FSq
58
-
59
- //正常動作(リスト構造)
60
-
61
-
62
-
63
- //codepad.org/B83f1FSq
64
-
65
- //正常動作(リスト構造)
66
-
67
-
68
-
69
57
  #include <stdio.h>
70
58
 
71
59
  #include <stdlib.h>
@@ -844,6 +832,8 @@
844
832
 
845
833
 
846
834
 
835
+
836
+
847
837
  /* 実行結果
848
838
 
849
839
  naka@naka ~
@@ -904,6 +894,66 @@
904
894
 
905
895
 
906
896
 
897
+ /* 実行結果
898
+
899
+ naka@naka ~
900
+
901
+ $ cd kadai/kadai9-8
902
+
903
+
904
+
905
+ naka@naka ~/kadai/kadai9-8
906
+
907
+ $ gcc -o kad9-8b kad9-8b.c -Wall
908
+
909
+
910
+
911
+ naka@naka ~/kadai/kadai9-8
912
+
913
+ $ kad9-8b
914
+
915
+ ファイルから読んだ文字列:yamada,tone,090-1122,mail-9
916
+
917
+ ファイルから読んだ文字列:hosi,nagoya,5436,mail-7
918
+
919
+ ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2
920
+
921
+ ファイルから読んだ文字列:koko,yosida,090-2314,mail-6
922
+
923
+ ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1
924
+
925
+ ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8
926
+
927
+ ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3
928
+
929
+ ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5
930
+
931
+ hosi, nagoya, 5436, mail-7
932
+
933
+ kato, kanagawa, 080-8888, mail-2
934
+
935
+ koko, yosida, 090-2314, mail-6
936
+
937
+ naka, kamikosaka, 080-4444, mail-1
938
+
939
+ nakada, nogata, 090-6376, mail-8
940
+
941
+ saito, yamanashi, 080-6666, mail-3
942
+
943
+ suzuki, saitama, 090-2222, mail-5
944
+
945
+ yamada, tone, 090-1122, mail-9
946
+
947
+
948
+
949
+ naka@naka ~/kadai/kadai9-8
950
+
951
+ $
952
+
953
+ */
954
+
955
+
956
+
907
957
 
908
958
 
909
959
 

4

図の追加

2018/01/30 06:09

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -60,6 +60,12 @@
60
60
 
61
61
 
62
62
 
63
+ //codepad.org/B83f1FSq
64
+
65
+ //正常動作(リスト構造)
66
+
67
+
68
+
63
69
  #include <stdio.h>
64
70
 
65
71
  #include <stdlib.h>
@@ -140,125 +146,501 @@
140
146
 
141
147
  ;
142
148
 
143
-
144
-
145
- //まず、char *p に対して、for(s = p; *p; p++) に現れる、
146
-
147
- //*p の型は(ポインタではなく)char そのものです。
148
-
149
- //ですから、*p は、「p がポイントしているところにある char のデータ」です。
150
-
151
-
152
-
153
- //一方、Cでは、文字列は、「'\0' で終端される」という規定になっています。
154
-
155
- //ですから、ちょっとくどく書けば、
156
-
157
- //for(s = p; *p != '\0' ; p++)ということで,
158
-
159
- //「p がポイントする文字が、終端文字(文字列の終わり)にくるまで」
160
-
161
- //という意味です。
162
-
163
-
164
-
165
- //そして、(Cのいろいろな背景から) *p != '\0' という表記は、
166
-
167
- //*p とだけ書いた時と同じ動作をします。
168
-
169
- //このため、文字列の終端をチェックするために、while(*p) とか、
170
-
171
- //if(! *p) こっちは、終端にきたときの判断)とかよく使われる表現です。
172
-
173
-
174
-
175
- //なお、NULL は、「何もポイントしていないポインタ」の値です。
176
-
177
- //そして、ちょっと面倒なのが、規格上は、
178
-
179
- //「ヌルポインタ(何もポイントしていないポインタ)の値は、
180
-
181
- //定数0と比較したときに等しくなる」と定義されている点です。
149
+
150
+
151
+ p--;
152
+
153
+
154
+
155
+ while (*p == '\r' || *p == '\n')
156
+
157
+ *(p--) = 0;
158
+
159
+
160
+
161
+ }
162
+
163
+
164
+
165
+ void list_add(struct address **head, char *name, char *address, char *tel, char *mail)
166
+
167
+ {
168
+
169
+ struct address *p;
170
+
171
+ if ((p = malloc(sizeof(struct address))) != 0) {
172
+
173
+
174
+
175
+ strcpy(p->name, name);
176
+
177
+
178
+
179
+ strcpy(p->address, address);
180
+
181
+
182
+
183
+ strcpy(p->tel, tel);
184
+
185
+
186
+
187
+
188
+
189
+ strcpy(p->mail, mail);
190
+
191
+
192
+
193
+
194
+
195
+ p->next = *head;
196
+
197
+ if (p->next != 0)
198
+
199
+ p->next->before = p;
200
+
201
+ p->before = 0;
202
+
203
+ *head = p;
204
+
205
+ }
206
+
207
+ }
208
+
209
+
210
+
211
+
212
+
213
+ void data_show(struct address *head) {
214
+
215
+ if (head != 0) {
216
+
217
+ printf(" %s, %s, %s, %s\n", head->name, head->address, head->tel, head->mail);
218
+
219
+ data_show(head->next);
220
+
221
+ }
222
+
223
+ }
224
+
225
+
226
+
227
+ struct address **listmin(struct address **head) {
228
+
229
+ struct address **p;
230
+
231
+
232
+
233
+ if (*head == 0)
234
+
235
+ return 0;
236
+
237
+ if ((*head)->next == 0)
238
+
239
+ return head;
240
+
241
+ //
242
+
243
+
244
+
245
+ if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0)
246
+
247
+ return head;
248
+
249
+ else
250
+
251
+ return p;
252
+
253
+ }
254
+
255
+
256
+
257
+ //大小を入れ替える
258
+
259
+ void exchange(struct address **p, struct address **q)
260
+
261
+ {
262
+
263
+ struct address *r, *s, *t;
264
+
265
+ assert(*p != 0 && *q != 0);
266
+
267
+
268
+
269
+ if (p == q)
270
+
271
+ return;
272
+
273
+
274
+
275
+ r = *p; s = *q;
276
+
277
+ if (&((*p)->next) == q || &((*q)->next) == p) {
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+ // &((*p)->next) == q において、**pはaddress構造体型ですから、
320
+
321
+ //*pはaddress構造体へのポインタです。
322
+
323
+ //従って、(*p)もaddress構造体へのポインタです。
324
+
325
+ //であれば、(*p)->nextはaddress構造体のnextメンバですね。
326
+
327
+ //ならば、&((*p)->next)はそのアドレスですから、nextメンバのアドレスとなります。
328
+
329
+
330
+
331
+ //それと q が等しいという条件ですから、qはadress構造体のnextメンバを
332
+
333
+ //ポイントしているのだろうと思います。
334
+
335
+
336
+
337
+ //つまり、*pが指すaddress構造体のnextメンバを
338
+
339
+ //qがポイントしているならば、この条件が成立します。
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+ if (s->next != 0){
348
+
349
+ s->next->before = r;
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+
386
+
387
+
182
388
 
183
389
 
184
390
 
185
- p--; // *pが\0となりfor()を抜けるとここに来る。
186
-
187
- //ポインタを1個戻して,\0 の前が'\r'か'\n'どうか調べるため。
188
-
189
-
190
-
191
- while (*p == '\r' || *p == '\n')
192
-
193
- *(p--) = 0;
194
-
195
- //
196
-
197
- }//chop()を抜けると\0で区切られた文字列になる。
198
-
199
-
200
-
201
- void list_add(struct address **head, char *name, char *address, char *tel, char *mail)
391
+
392
+
393
+
394
+
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+ }
408
+
409
+ s->before = r->before;
410
+
411
+
412
+
413
+
414
+
415
+ r->before = s;
416
+
417
+
418
+
419
+ *p = s;
420
+
421
+
422
+
423
+
424
+
425
+ *q = s->next;
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+ s->next = r;
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470
+
471
+
472
+
473
+
474
+
475
+
476
+
477
+
478
+
479
+
480
+
481
+ return;
482
+
483
+ } else { //if ((&((*p)->next)) != q && (&((*q)->next) != p)) の時だと思う
484
+
485
+ if (s->next != 0)
486
+
487
+ // (*q)->nextが0でないとき
488
+
489
+
490
+
491
+ s->next->before = r;
492
+
493
+ // (s->next)->before=*p
494
+
495
+
496
+
497
+ if (r->next != 0)
498
+
499
+ // (*p)->nextが0でないとき
500
+
501
+
502
+
503
+ r->next->before = s;
504
+
505
+ // (r->next)->before=*q
506
+
507
+
508
+
509
+ t = s->before;
510
+
511
+ // s->before==(*q)->before
512
+
513
+ // t=(*q)->before
514
+
515
+
516
+
517
+ s->before = r->before;
518
+
519
+ // s->beforeにr->before==(*p)->before(これはポインタ)を代入する。
520
+
521
+
522
+
523
+ r->before = t;
524
+
525
+ // r->before==(*p)->before
526
+
527
+ // t=s->before
528
+
529
+ // r->beforeにs->before==(*q)->before(これはポインタ)を代入する。
530
+
531
+
532
+
533
+ t = r->next;
534
+
535
+ // r->next==(*p)->nextが0でないときであるから
536
+
537
+ // t=(*p)->next
538
+
539
+
540
+
541
+ r->next = s->next;
542
+
543
+ // s->next==(*q)->next
544
+
545
+ // r->next =(*q)->next
546
+
547
+
548
+
549
+ s->next = t;
550
+
551
+ // t=(*p)->next
552
+
553
+ // s->next=(*p)->next
554
+
555
+
556
+
557
+ *p = s;
558
+
559
+ *q = r;
560
+
561
+ }
562
+
563
+ }
564
+
565
+
566
+
567
+ void data_sort(struct address **head)
202
568
 
203
569
  {
204
570
 
205
- struct address *p;
571
+ struct address **p;
572
+
573
+
574
+
206
-
575
+ if (*head != 0) {
576
+
577
+ for (;;) {
578
+
579
+ p = listmin(head);
580
+
207
- if ((p = malloc(sizeof(struct address))) != 0) {
581
+ //関数listmin(head)は、名前からリストの全ての要素をチェックして、
582
+
583
+ //いちばん小さいnameを持つ要素を返していると思われます。
584
+
585
+ //そうでないと正しくソートされません。
586
+
587
+
588
+
589
+ if (p == 0)break;
590
+
591
+ //「リストの先頭が空のとき、返り値が0になるので、ソートが完了したとして、
592
+
593
+ //ループを抜けます。」ですね.
594
+
595
+
596
+
597
+ //次のように使うことが出来る。
598
+
599
+
600
+
601
+ // char *p = NULL;
602
+
603
+
604
+
605
+ // if (!p) { … /* if (p==0) と等価 */
606
+
607
+
608
+
609
+ //世の中には様々なマイクロプロセッサーがあり、
610
+
611
+ //現実にNULLポインターの内部表現が「0番地」では無いものも存在する。
612
+
613
+
614
+
615
+ //しかしこの場合でも、ソースコード中の値は0のままで良い。
616
+
617
+ //なぜなら、NULLポインターというものは抽象的な概念であり、
618
+
619
+ //物理的なアドレスを指しているわけではないからである。
620
+
621
+
622
+
623
+ //もし内部表現が0でない計算機の場合、必要に応じてCコンパイラーは
624
+
625
+ //その値に自動的に変換してくれる。
626
+
627
+ //従って、NULLポインターと0は完全に等価であり、
628
+
629
+ //可換であるとして扱うことが出来るのである。
208
630
 
209
631
 
210
632
 
211
- strcpy(p->name, name);
633
+ exchange(head, p);
212
-
634
+
213
- //文字列のコピー
635
+ //大小を入れ替える
214
-
215
- //【書式】
636
+
216
-
637
+
638
+
217
- //#include <string.h>
639
+ head = &((*head)->next);
218
-
219
- //char *strcpy(char *s1, const char *s2);
640
+
220
-
221
-
222
-
223
- //【説明】
224
-
225
- //文字型配列 *s1 に文字列 *s2 '\0' まコピーします。
641
+ //見つけたいちばん小さい要素関数exchange(head, p)先頭に移動ています。
226
-
227
- //'\0' もコピーするので s1 はその分も考えて大きさを宣言して
642
+
228
-
229
- //おかなければなりません。
230
-
231
- //もし、s1 と s2 が重なっている場合には動作は未定義となります。
232
-
233
-
234
-
235
- strcpy(p->address, address);
236
-
237
- //文字型配列 p->address に文字列 address を '\0' までコピーします。
238
-
239
-
240
-
241
- strcpy(p->tel, tel);
242
-
243
- //文字型配列 p->number に文字列 number を '\0' までコピーします。
244
-
245
-
246
-
247
- strcpy(p->mail, mail);
248
-
249
- //文字型配列 p->mail に文字列 mail を '\0' までコピーします。
250
-
251
-
252
-
253
- p->next = *head;
254
-
255
- if (p->next != 0)
256
-
257
- p->next->before = p;
258
-
259
- p->before = 0;
260
-
261
- *head = p;
643
+ }
262
644
 
263
645
  }
264
646
 
@@ -266,466 +648,142 @@
266
648
 
267
649
 
268
650
 
269
-
270
-
271
- void data_show(struct address *head) {
651
+ void release(struct address **head)
652
+
272
-
653
+ {
654
+
273
- if (head != 0) {
655
+ if (*head != 0) {
274
-
275
- printf(" %s, %s, %s, %s\n", head->name, head->address, head->tel, head->mail);
656
+
276
-
277
- data_show(head->next);
657
+ release( &((*head)->next) );
658
+
278
-
659
+ free(*head);
660
+
661
+ *head = 0;
662
+
279
- }
663
+ }
280
664
 
281
665
  }
282
666
 
283
667
 
284
668
 
285
- //関数listmin(head)は、名前からリストの全ての要素をチェックして、
286
-
287
- //いちばん小さいnameを持つ要素を返していると思われます。
288
-
289
- //そうでないと正しくソートされません。
290
-
291
- struct address **listmin(struct address **head) {
669
+ int main()
670
+
292
-
671
+ {
672
+
293
- struct address **p;
673
+ struct address *head;
674
+
675
+ FILE* fp;
676
+
677
+ static char buff[N], name[N], address[N], tel[N], mail[N];
678
+
679
+ char *token=",";
680
+
681
+
682
+
683
+ head = 0;
294
684
 
295
685
 
296
686
 
687
+ if ((fp = fopen(FILENAME,"r")) != 0) {
688
+
689
+ while(fgets(buff, N, fp) != 0){
690
+
691
+ //本当の大元の文字列を書き換えないようにするために
692
+
693
+ //bufを確保してコピーし、それをstrtok()の引数にしている。
694
+
695
+ char *p;
696
+
697
+ chop(buff);
698
+
699
+ printf( "ファイルから読んだ文字列:%s\n", buff );
700
+
701
+
702
+
703
+ p = strtok(buff, token);
704
+
297
- if (*head == 0)
705
+ if ( p != NULL ) {
706
+
298
-
707
+ strcpy(name, p);
708
+
709
+ } else {
710
+
711
+ printf( "氏名の切り出しに失敗しました。\n");
712
+
713
+ break;
714
+
715
+ }
716
+
717
+ p = strtok(NULL, token);
718
+
719
+
720
+
721
+ if ( p != NULL ) {
722
+
723
+ strcpy(address, p);
724
+
725
+ } else {
726
+
727
+ printf( "住所の切り出しに失敗しました。\n");
728
+
729
+ break;
730
+
731
+ }
732
+
733
+ p = strtok(NULL, token);
734
+
735
+
736
+
737
+ if ( p != NULL ) {
738
+
739
+ strcpy(tel, p);
740
+
741
+ } else {
742
+
743
+ printf( "電話番号の切り出しに失敗しました。\n");
744
+
745
+ break;
746
+
747
+ }
748
+
749
+ p = strtok(NULL, token);
750
+
751
+
752
+
753
+ if ( p != NULL ) {
754
+
755
+ strcpy(mail, p);
756
+
757
+ } else {
758
+
759
+ printf( "メールアドレスの切り出しに失敗しました。\n");
760
+
761
+ break;
762
+
763
+ }
764
+
765
+ list_add(&head, name, address, tel, mail);
766
+
767
+ }
768
+
769
+ fclose(fp);
770
+
771
+ }
772
+
773
+ data_sort(&head);
774
+
775
+ data_show(head);
776
+
777
+
778
+
779
+ release(&head);
780
+
299
- return 0;
781
+ return 0;
300
-
301
- if ((*head)->next == 0)
302
-
303
- return head;
304
-
305
- //リストが残り1つの場合、ソートが完了したとして、ループを抜けます。
306
-
307
-
308
-
309
- if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0)
310
-
311
- return head;
312
-
313
- else
314
-
315
- return p;
316
782
 
317
783
  }
318
784
 
319
785
 
320
786
 
321
- //大小を入れ替える
322
-
323
- void exchange(struct address **p, struct address **q)
324
-
325
- {
326
-
327
- struct address *r, *s, *t;
328
-
329
- assert(*p != 0 && *q != 0);
330
-
331
- //assertマクロは関数形式マクロで、引数に偽(すなわち0)が指定されると、
332
-
333
- //ソースファイル名や行番号等の情報を標準エラー出力に出力し、プログラムを終了させます。
334
-
335
- if (p == q)
336
-
337
- return;
338
-
339
-
340
-
341
- r = *p; s = *q;
342
-
343
- if (&((*p)->next) == q || &((*q)->next) == p) {
344
-
345
- // &((*p)->next) == q において、**pはaddress構造体型ですから、
346
-
347
- //*pはaddress構造体へのポインタです。
348
-
349
-
350
-
351
- //従って、(*p)もaddress構造体へのポインタです。
352
-
353
-
354
-
355
- //であれば、(*p)->nextはaddress構造体のnextメンバですね。
356
-
357
-
358
-
359
- //ならば、&((*p)->next)はそのアドレスですから、nextメンバのアドレスとなります。
360
-
361
-
362
-
363
- //それと q が等しいという条件ですから、qはadress構造体のnextメンバを
364
-
365
- //ポイントしているのだろうと思います。
366
-
367
-
368
-
369
- //つまり、*pが指すaddress構造体のnextメンバを
370
-
371
- //qがポイントしているならば、この条件が成立します。
372
-
373
-
374
-
375
-
376
-
377
- //&((*q)->next) == pにおいて、**qはaddress構造体型ですから、
378
-
379
- //*qはaddress構造体へのポインタです。
380
-
381
-
382
-
383
- //従って、(*q)もaddress構造体へのポインタです。
384
-
385
-
386
-
387
- //であれば、(*q)->nextはaddress構造体のnextメンバですね。
388
-
389
-
390
-
391
- //ならば、&((*q)->next)はそのアドレスですから、
392
-
393
- //nextメンバのアドレスとなります。
394
-
395
-
396
-
397
- //それと p が等しいという条件ですから、pはadress構造体のnextメンバを
398
-
399
- //ポイントしているのだろうと思います。
400
-
401
-
402
-
403
- //つまり、*qが指すaddress構造体のnextメンバを
404
-
405
- //pがポイントしているならば、この条件が成立します。
406
-
407
-
408
-
409
- if (s->next != 0){
410
-
411
- // sと*qはおなじである。s->nextは(*q)->nextであるから
412
-
413
- // (*q)->nextが0でないとき
414
-
415
-
416
-
417
- s->next->before = r;
418
-
419
- //「sの次が存在するなら、そいつの手前をrにする」と読める。
420
-
421
- //つまり" r ← sの次 " ってゆー上り方向のリンクを張り替えたってこと。
422
-
423
- }
424
-
425
-
426
-
427
- r->before = s;
428
-
429
- //「sの次が存在しないなら、r の手前をsにする」と読める。
430
-
431
- //つまり" s ← (r->before ) " ってゆー上り方向のリンクを張りかえたってこと。
432
-
433
-
434
-
435
- s->before = r->before;
436
-
437
- //「sの次が存在しないなら(s->next == NULL)、s->before をr->beforeにする」と読める。
438
-
439
- //つまり" r->before ← s->before " ってゆー上り方向のリンクを張り替えたってこと。
440
-
441
-
442
-
443
- *p = s;
444
-
445
- //*pにs(これはポインタ*q)を代入する。
446
-
447
- //*pをsすなわち*qをさすようにする。
448
-
449
-
450
-
451
- *q = s->next;
452
-
453
- //s->nextはNULLであるから*qにNULLを代入する。
454
-
455
- //*qはどこもさしていない
456
-
457
-
458
-
459
- s->next = r;
460
-
461
- //rは*pであるから,(s->nextに*p(これはポインタ)を代入する。
462
-
463
- //s->nextは*pを指すようにする
464
-
465
-
466
-
467
- return;
468
-
469
- } else { //if ((&((*p)->next)) != q && (&((*q)->next) != p)) の時だと思う
470
-
471
- if (s->next != 0)
472
-
473
- // (*q)->nextが0でないとき
474
-
475
-
476
-
477
- s->next->before = r;
478
-
479
- // (s->next)->before=*p
480
-
481
-
482
-
483
- t = s->before;
484
-
485
- // s->before==(*q)->before
486
-
487
- // t=(*q)->before
488
-
489
-
490
-
491
- s->before = r->before;
492
-
493
- // s->beforeにr->before==(*p)->before(これはポインタ)を代入する。
494
-
495
-
496
-
497
- if (r->next != 0)
498
-
499
- // (*p)->nextが0でないとき
500
-
501
-
502
-
503
- r->next->before = s;
504
-
505
- // (r->next)->before=*q
506
-
507
-
508
-
509
- r->before = t;
510
-
511
- // r->before==(*p)->before
512
-
513
- // t=s->before
514
-
515
- // r->beforeにs->before==(*q)->before(これはポインタ)を代入する。
516
-
517
-
518
-
519
- t = r->next;
520
-
521
- // r->next==(*p)->nextが0でないときであるから
522
-
523
- // t=(*p)->next
524
-
525
-
526
-
527
- r->next = s->next;
528
-
529
- // s->next==(*q)->next
530
-
531
- // r->next =(*q)->next
532
-
533
-
534
-
535
- s->next = t;
536
-
537
- // t=(*p)->next
538
-
539
- // s->next=(*p)->next
540
-
541
-
542
-
543
- *p = s;
544
-
545
- *q = r;
546
-
547
- }
548
-
549
- }
550
-
551
-
552
-
553
- void data_sort(struct address **head) {
554
-
555
- struct address **p;
556
-
557
- if (*head != 0) {
558
-
559
- for (;;) {
560
-
561
- p = listmin(head);
562
-
563
- //関数listmin(head)は、名前からリストの全ての要素をチェックして、
564
-
565
- //いちばん小さいnameを持つ要素を返していると思われます。
566
-
567
- //そうでないと正しくソートされません。
568
-
569
-
570
-
571
- if (p == 0)break;
572
-
573
- //リストが残り1つの場合、ソートが完了したとして、ループを抜けます。
574
-
575
-
576
-
577
- exchange(head, p);
578
-
579
- //大小を入れ替える
580
-
581
-
582
-
583
- head = &((*head)->next);
584
-
585
- //見つけたいちばん小さい要素を関数exchange(head, p)で先頭に移動しています。
586
-
587
- }
588
-
589
- }
590
-
591
- }
592
-
593
-
594
-
595
- void release(struct address **head) {
596
-
597
- if (*head != 0) {
598
-
599
- release( &((*head)->next) );
600
-
601
- free(*head);
602
-
603
- *head = 0;
604
-
605
- }
606
-
607
- }
608
-
609
-
610
-
611
- int main() {
612
-
613
- struct address *head;
614
-
615
- FILE* fp;
616
-
617
- static char buff[N], name[N], address[N], tel[N], mail[N];
618
-
619
- char *token=",";
620
-
621
-
622
-
623
- head = 0;
624
-
625
-
626
-
627
- if ((fp = fopen(FILENAME,"r")) != 0) {
628
-
629
- while(fgets(buff, N, fp) != 0){
630
-
631
- //本当の大元の文字列を書き換えないようにするために
632
-
633
- //bufを確保してコピーし、それをstrtok()の引数にしている。
634
-
635
- char *p;
636
-
637
- chop(buff);
638
-
639
- printf( "ファイルから読んだ文字列:%s\n", buff );
640
-
641
-
642
-
643
- p = strtok(buff, token);
644
-
645
- if ( p != NULL ) {
646
-
647
- strcpy(name, p);
648
-
649
- } else {
650
-
651
- printf( "氏名の切り出しに失敗しました。\n");
652
-
653
- break;
654
-
655
- }
656
-
657
-
658
-
659
- p = strtok(NULL, token);
660
-
661
- if ( p != NULL ) {
662
-
663
- strcpy(address, p);
664
-
665
- } else {
666
-
667
- printf( "住所の切り出しに失敗しました。\n");
668
-
669
- break;
670
-
671
- }
672
-
673
-
674
-
675
- p = strtok(NULL, token);
676
-
677
- if ( p != NULL ) {
678
-
679
- strcpy(tel, p);
680
-
681
- } else {
682
-
683
- printf( "電話番号の切り出しに失敗しました。\n");
684
-
685
- break;
686
-
687
- }
688
-
689
-
690
-
691
- p = strtok(NULL, token);
692
-
693
- if ( p != NULL ) {
694
-
695
- strcpy(mail, p);
696
-
697
- } else {
698
-
699
- printf( "メールアドレスの切り出しに失敗しました。\n");
700
-
701
- break;
702
-
703
- }
704
-
705
- list_add(&head, name, address, tel, mail);
706
-
707
- }
708
-
709
- fclose(fp);
710
-
711
- }
712
-
713
- data_sort(&head);
714
-
715
- data_show(head);
716
-
717
-
718
-
719
-
720
-
721
- release(&head);
722
-
723
- return 0;
724
-
725
- }
726
-
727
-
728
-
729
787
  /* 実行結果
730
788
 
731
789
  naka@naka ~
@@ -786,6 +844,66 @@
786
844
 
787
845
 
788
846
 
847
+ /* 実行結果
848
+
849
+ naka@naka ~
850
+
851
+ $ cd kadai/kadai9-8
852
+
853
+
854
+
855
+ naka@naka ~/kadai/kadai9-8
856
+
857
+ $ gcc -o kad9-8b kad9-8b.c -Wall
858
+
859
+
860
+
861
+ naka@naka ~/kadai/kadai9-8
862
+
863
+ $ kad9-8b
864
+
865
+ ファイルから読んだ文字列:yamada,tone,090-1122,mail-9
866
+
867
+ ファイルから読んだ文字列:hosi,nagoya,5436,mail-7
868
+
869
+ ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2
870
+
871
+ ファイルから読んだ文字列:koko,yosida,090-2314,mail-6
872
+
873
+ ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1
874
+
875
+ ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8
876
+
877
+ ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3
878
+
879
+ ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5
880
+
881
+ hosi, nagoya, 5436, mail-7
882
+
883
+ kato, kanagawa, 080-8888, mail-2
884
+
885
+ koko, yosida, 090-2314, mail-6
886
+
887
+ naka, kamikosaka, 080-4444, mail-1
888
+
889
+ nakada, nogata, 090-6376, mail-8
890
+
891
+ saito, yamanashi, 080-6666, mail-3
892
+
893
+ suzuki, saitama, 090-2222, mail-5
894
+
895
+ yamada, tone, 090-1122, mail-9
896
+
897
+
898
+
899
+ naka@naka ~/kadai/kadai9-8
900
+
901
+ $
902
+
903
+ */
904
+
905
+
906
+
789
907
 
790
908
 
791
909
 

3

コードの修正

2018/01/30 06:04

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -48,11 +48,49 @@
48
48
 
49
49
  ```ここに言語を入力
50
50
 
51
+ //codepad.org/B83f1FSq
52
+
51
- コード
53
+ //正常動作(リスト構造)
54
+
55
+
56
+
52
-
57
+ //codepad.org/B83f1FSq
58
+
59
+ //正常動作(リスト構造)
60
+
61
+
62
+
63
+ #include <stdio.h>
64
+
65
+ #include <stdlib.h>
66
+
67
+ #include <string.h>
68
+
69
+ #include <assert.h> //
70
+
71
+
72
+
73
+ //assert.hでは、assertマクロが定義されています。
74
+
75
+
76
+
77
+ //assertマクロは関数形式マクロで、引数に偽(すなわち0)が指定されると、
78
+
79
+ //ソースファイル名や行番号等の情報を標準エラー出力に出力し、
80
+
53
- // 電話帳プログラムの一部
81
+ //プログラムを終了させます。
82
+
54
-
83
+ //プログラマは、assertマクロが出力する情報をもとにデバッグを行います。
84
+
85
+
86
+
55
-
87
+ //NDEBUGマクロが定義されていると、assertマクロは、次のように定義され、
88
+
89
+ //何もしません。
90
+
91
+ //#define assert(ignore) ((void)0)
92
+
93
+
56
94
 
57
95
  #define N 256
58
96
 
@@ -76,18 +114,186 @@
76
114
 
77
115
  };
78
116
 
79
-
80
-
81
- //(*head)->nameと(*head)->next)のnameとを比べて
117
+
82
-
118
+
83
- //小さいほうのポインタのポインタを返却値にしている。
119
+ void data_show(struct address* head);
120
+
84
-
121
+ void data_add(struct address** head);
122
+
85
- struct address **listmin(struct address **head)
123
+ void data_delete(struct address** head);
124
+
125
+ void data_sort(struct address** head);
126
+
127
+ void data_write(struct address* head);
128
+
129
+
130
+
131
+ void data_amend(struct address* head);
132
+
133
+ void data_search(struct address* head);
134
+
135
+
136
+
137
+ void chop(char *p){
138
+
139
+ for (; *p; p++)
140
+
141
+ ;
142
+
143
+
144
+
145
+ //まず、char *p に対して、for(s = p; *p; p++) に現れる、
146
+
147
+ //*p の型は(ポインタではなく)char そのものです。
148
+
149
+ //ですから、*p は、「p がポイントしているところにある char のデータ」です。
150
+
151
+
152
+
153
+ //一方、Cでは、文字列は、「'\0' で終端される」という規定になっています。
154
+
155
+ //ですから、ちょっとくどく書けば、
156
+
157
+ //for(s = p; *p != '\0' ; p++)ということで,
158
+
159
+ //「p がポイントする文字が、終端文字(文字列の終わり)にくるまで」
160
+
161
+ //という意味です。
162
+
163
+
164
+
165
+ //そして、(Cのいろいろな背景から) *p != '\0' という表記は、
166
+
167
+ //*p とだけ書いた時と同じ動作をします。
168
+
169
+ //このため、文字列の終端をチェックするために、while(*p) とか、
170
+
171
+ //if(! *p) こっちは、終端にきたときの判断)とかよく使われる表現です。
172
+
173
+
174
+
175
+ //なお、NULL は、「何もポイントしていないポインタ」の値です。
176
+
177
+ //そして、ちょっと面倒なのが、規格上は、
178
+
179
+ //「ヌルポインタ(何もポイントしていないポインタ)の値は、
180
+
181
+ //定数0と比較したときに等しくなる」と定義されている点です。
182
+
183
+
184
+
185
+ p--; // *pが\0となりfor()を抜けるとここに来る。
186
+
187
+ //ポインタを1個戻して,\0 の前が'\r'か'\n'どうか調べるため。
188
+
189
+
190
+
191
+ while (*p == '\r' || *p == '\n')
192
+
193
+ *(p--) = 0;
194
+
195
+ //
196
+
197
+ }//chop()を抜けると\0で区切られた文字列になる。
198
+
199
+
200
+
201
+ void list_add(struct address **head, char *name, char *address, char *tel, char *mail)
86
202
 
87
203
  {
88
204
 
205
+ struct address *p;
206
+
207
+ if ((p = malloc(sizeof(struct address))) != 0) {
208
+
209
+
210
+
211
+ strcpy(p->name, name);
212
+
213
+ //文字列のコピー
214
+
215
+ //【書式】
216
+
217
+ //#include <string.h>
218
+
219
+ //char *strcpy(char *s1, const char *s2);
220
+
221
+
222
+
223
+ //【説明】
224
+
225
+ //文字型配列 *s1 に文字列 *s2 を '\0' までコピーします。
226
+
227
+ //'\0' もコピーするので s1 はその分も考えて大きさを宣言して
228
+
229
+ //おかなければなりません。
230
+
231
+ //もし、s1 と s2 が重なっている場合には動作は未定義となります。
232
+
233
+
234
+
235
+ strcpy(p->address, address);
236
+
237
+ //文字型配列 p->address に文字列 address を '\0' までコピーします。
238
+
239
+
240
+
241
+ strcpy(p->tel, tel);
242
+
243
+ //文字型配列 p->number に文字列 number を '\0' までコピーします。
244
+
245
+
246
+
247
+ strcpy(p->mail, mail);
248
+
249
+ //文字型配列 p->mail に文字列 mail を '\0' までコピーします。
250
+
251
+
252
+
253
+ p->next = *head;
254
+
255
+ if (p->next != 0)
256
+
257
+ p->next->before = p;
258
+
259
+ p->before = 0;
260
+
261
+ *head = p;
262
+
263
+ }
264
+
265
+ }
266
+
267
+
268
+
269
+
270
+
271
+ void data_show(struct address *head) {
272
+
273
+ if (head != 0) {
274
+
275
+ printf(" %s, %s, %s, %s\n", head->name, head->address, head->tel, head->mail);
276
+
277
+ data_show(head->next);
278
+
279
+ }
280
+
281
+ }
282
+
283
+
284
+
285
+ //関数listmin(head)は、名前からリストの全ての要素をチェックして、
286
+
287
+ //いちばん小さいnameを持つ要素を返していると思われます。
288
+
289
+ //そうでないと正しくソートされません。
290
+
291
+ struct address **listmin(struct address **head) {
292
+
89
293
  struct address **p;
90
294
 
295
+
296
+
91
297
  if (*head == 0)
92
298
 
93
299
  return 0;
@@ -96,14 +302,12 @@
96
302
 
97
303
  return head;
98
304
 
305
+ //リストが残り1つの場合、ソートが完了したとして、ループを抜けます。
306
+
307
+
308
+
99
309
  if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0)
100
310
 
101
- // #include <string.h>
102
-
103
- // int strcmp( const char *str1 , const char *str2 );
104
-
105
- // str1<str2ならば負の値を返す。
106
-
107
311
  return head;
108
312
 
109
313
  else
@@ -114,205 +318,475 @@
114
318
 
115
319
 
116
320
 
321
+ //大小を入れ替える
322
+
117
323
  void exchange(struct address **p, struct address **q)
118
324
 
119
325
  {
120
326
 
121
- struct address *r, *s, *t;
327
+ struct address *r, *s, *t;
122
-
328
+
123
- assert(*p != 0 && *q != 0);
329
+ assert(*p != 0 && *q != 0);
330
+
331
+ //assertマクロは関数形式マクロで、引数に偽(すなわち0)が指定されると、
332
+
333
+ //ソースファイル名や行番号等の情報を標準エラー出力に出力し、プログラムを終了させます。
334
+
335
+ if (p == q)
336
+
337
+ return;
338
+
339
+
340
+
341
+ r = *p; s = *q;
342
+
343
+ if (&((*p)->next) == q || &((*q)->next) == p) {
344
+
345
+ // &((*p)->next) == q において、**pはaddress構造体型ですから、
346
+
347
+ //*pはaddress構造体へのポインタです。
348
+
349
+
350
+
351
+ //従って、(*p)もaddress構造体へのポインタです。
352
+
353
+
354
+
355
+ //であれば、(*p)->nextはaddress構造体のnextメンバですね。
356
+
357
+
358
+
359
+ //ならば、&((*p)->next)はそのアドレスですから、nextメンバのアドレスとなります。
360
+
361
+
362
+
363
+ //それと q が等しいという条件ですから、qはadress構造体のnextメンバを
364
+
365
+ //ポイントしているのだろうと思います。
366
+
367
+
368
+
369
+ //つまり、*pが指すaddress構造体のnextメンバを
370
+
371
+ //qがポイントしているならば、この条件が成立します。
372
+
373
+
374
+
375
+
376
+
377
+ //&((*q)->next) == pにおいて、**qはaddress構造体型ですから、
378
+
379
+ //*qはaddress構造体へのポインタです。
380
+
381
+
382
+
383
+ //従って、(*q)もaddress構造体へのポインタです。
384
+
385
+
386
+
387
+ //であれば、(*q)->nextはaddress構造体のnextメンバですね。
388
+
389
+
390
+
391
+ //ならば、&((*q)->next)はそのアドレスですから、
392
+
393
+ //nextメンバのアドレスとなります。
394
+
395
+
396
+
397
+ //それと p が等しいという条件ですから、pはadress構造体のnextメンバを
398
+
399
+ //ポイントしているのだろうと思います。
400
+
401
+
402
+
403
+ //つまり、*qが指すaddress構造体のnextメンバを
404
+
405
+ //pがポイントしているならば、この条件が成立します。
406
+
407
+
408
+
409
+ if (s->next != 0){
410
+
411
+ // sと*qはおなじである。s->nextは(*q)->nextであるから
412
+
413
+ // (*q)->nextが0でないとき
414
+
415
+
416
+
417
+ s->next->before = r;
418
+
419
+ //「sの次が存在するなら、そいつの手前をrにする」と読める。
420
+
421
+ //つまり" r ← sの次 " ってゆー上り方向のリンクを張り替えたってこと。
422
+
423
+ }
424
+
425
+
426
+
427
+ r->before = s;
428
+
429
+ //「sの次が存在しないなら、r の手前をsにする」と読める。
430
+
431
+ //つまり" s ← (r->before ) " ってゆー上り方向のリンクを張りかえたってこと。
432
+
433
+
434
+
435
+ s->before = r->before;
436
+
437
+ //「sの次が存在しないなら(s->next == NULL)、s->before をr->beforeにする」と読める。
438
+
439
+ //つまり" r->before ← s->before " ってゆー上り方向のリンクを張り替えたってこと。
440
+
441
+
442
+
443
+ *p = s;
444
+
445
+ //*pにs(これはポインタ*q)を代入する。
446
+
447
+ //*pをsすなわち*qをさすようにする。
448
+
449
+
450
+
451
+ *q = s->next;
452
+
453
+ //s->nextはNULLであるから*qにNULLを代入する。
454
+
455
+ //*qはどこもさしていない
456
+
457
+
458
+
459
+ s->next = r;
460
+
461
+ //rは*pであるから,(s->nextに*p(これはポインタ)を代入する。
462
+
463
+ //s->nextは*pを指すようにする
464
+
465
+
466
+
467
+ return;
468
+
469
+ } else { //if ((&((*p)->next)) != q && (&((*q)->next) != p)) の時だと思う
470
+
471
+ if (s->next != 0)
472
+
473
+ // (*q)->nextが0でないとき
474
+
475
+
476
+
477
+ s->next->before = r;
478
+
479
+ // (s->next)->before=*p
124
480
 
125
481
 
126
482
 
127
- if (p == q)
128
-
129
- return;
130
-
131
-
132
-
133
- r = *p; s = *q;
134
-
135
- if (&((*p)->next) == q || &((*q)->next) == p) {
136
-
137
- // (*p)はポインタで,(*p)->nextも次のポインタである。
138
-
139
- // q(ポインタのポインタ)と(*p)->nextを比較するには&((*p)->next)とする。
140
-
141
-
142
-
143
-   if (s->next != 0){
144
-
145
-    s->next->before = r;
146
-
147
-   //「sの次が存在するなら、そいつの手前をrにする」と読める。
148
-
149
-          //つまり" r sの次 " ってゆー上り方向のリンクを張り替えたってこと。
150
-
151
-       }
152
-
153
-   r->before = s;
154
-
155
-   //rは*pであるから,*p->before = sである。s==*qなので
156
-
157
-   //*p->beforeに*q(これはポインタ)を代入する。
158
-
159
-
160
-
161
-   s->before = r->before;
162
-
163
-   // s->beforeに*q(これはポインタ)を代入する。
164
-
165
-
166
-
167
-   *p = s;
168
-
169
-   //sは*qだから*pに*q(これはポインタ)を代入する。
170
-
171
-
172
-
173
-   *q = s->next;
174
-
175
-   //s->next(*q)->nextであるから*qに(*q)->next(これはポインタ)を代入する。
176
-
177
-
178
-
179
-   s->next = r;
180
-
181
-   //rは*pであるから,(*q)->nextに*p(これはポインタ)を代入する。
182
-
183
-
184
-
185
-   return;
186
-
187
- } else {
188
-
189
-    if (s->next != 0){
190
-
191
-    // (*q)->nextが0でないとき
192
-
193
-
194
-
195
- s->next->before = r;
196
-
197
- // (s->next)->before=*p
198
-
199
-   }
200
-
201
-    t = s->before;
202
-
203
-    // s->before==(*q)->before
204
-
205
-    // t=(*q)->before
206
-
207
-
208
-
209
-    s->before = r->before;
210
-
211
-    // s->beforeにr->before==(*p)->before(これはポインタ)を代入する。
212
-
213
-
214
-
215
-    if (r->next != 0){
216
-
217
-    // (*p)->nextが0でないとき
218
-
219
-
220
-
221
- r->next->before = s;
222
-
223
- // (r->next)->before=*q
224
-
225
-   }
226
-
227
-    r->before = t;
228
-
229
-
230
-
231
-    t = r->next;
232
-
233
-
234
-
235
-    r->next = s->next;
236
-
237
-
238
-
239
-    s->next = t;
240
-
241
-
242
-
243
-    *p = s;
244
-
245
-    *q = r;
246
-
247
- }
483
+ t = s->before;
484
+
485
+ // s->before==(*q)->before
486
+
487
+ // t=(*q)->before
488
+
489
+
490
+
491
+ s->before = r->before;
492
+
493
+ // s->beforeにr->before==(*p)->before(これはポインタ)を代入する。
494
+
495
+
496
+
497
+ if (r->next != 0)
498
+
499
+ // (*p)->next0でないとき
500
+
501
+
502
+
503
+ r->next->before = s;
504
+
505
+ // (r->next)->before=*q
506
+
507
+
508
+
509
+ r->before = t;
510
+
511
+ // r->before==(*p)->before
512
+
513
+ // t=s->before
514
+
515
+ // r->beforeにs->before==(*q)->before(これはポインタ)を代入する。
516
+
517
+
518
+
519
+ t = r->next;
520
+
521
+ // r->next==(*p)->nextが0でないときであるから
522
+
523
+ // t=(*p)->next
524
+
525
+
526
+
527
+ r->next = s->next;
528
+
529
+ // s->next==(*q)->next
530
+
531
+ // r->next =(*q)->next
532
+
533
+
534
+
535
+ s->next = t;
536
+
537
+ // t=(*p)->next
538
+
539
+ // s->next=(*p)->next
540
+
541
+
542
+
543
+ *p = s;
544
+
545
+ *q = r;
546
+
547
+ }
248
548
 
249
549
  }
250
550
 
251
551
 
252
552
 
253
- void data_sort(struct address **head)
553
+ void data_sort(struct address **head) {
254
-
255
- {
554
+
256
-
257
- struct address **p;
555
+ struct address **p;
258
-
556
+
259
- if (*head != 0) {
557
+ if (*head != 0) {
260
-
558
+
261
- for (;;) {
559
+ for (;;) {
262
-
560
+
263
- p = listmin(head);
561
+ p = listmin(head);
264
-
562
+
265
- //(*head)->nameと(*head)->next)nameと比べ
563
+ //関数listmin(head)は、名前からリスト全ての要素チェックし
266
-
564
+
267
- //小さいほうのポインタのポインタを返却値にしている。
565
+ //いちばん小さいname持つ要素を返していると思われます
268
-
269
- //帰ってきたhead(小さいほうのポインタのポインタ),または
566
+
270
-
271
- //p(小いほうのポインタのポインタ)
567
+ //そうでないと正しくソートれません。
272
-
273
-
274
-
568
+
569
+
570
+
275
- if (p == 0)
571
+ if (p == 0)break;
276
-
572
+
277
- break;
573
+ //リストが残り1つの場合、ソートが完了したとして、ループを抜けます。
278
-
279
-
280
-
574
+
575
+
576
+
281
- exchange(head, p);
577
+ exchange(head, p);
282
-
578
+
283
- //大小を入れ替える
579
+ //大小を入れ替える
284
-
285
-
286
-
580
+
581
+
582
+
287
- head = &((*head)->next);
583
+ head = &((*head)->next);
584
+
288
-
585
+ //見つけたいちばん小さい要素を関数exchange(head, p)で先頭に移動しています。
586
+
289
- }
587
+ }
290
-
588
+
291
- }
589
+ }
292
590
 
293
591
  }
294
592
 
295
593
 
296
594
 
297
- データ
298
-
299
- address.csv
300
-
301
- yamada,tone,090-1122,mail-9
302
-
303
- hosi,nagoya,5436,mail-7
304
-
305
- kato,kanagawa,080-8888,mail-2
306
-
307
- koko,yosida,090-2314,mail-6
308
-
309
- naka,kamikosaka,080-4444,mail-1
310
-
311
- nakada,nogata,090-6376,mail-8
312
-
313
- saito,yamanashi,080-6666,mail-3
314
-
315
- suzuki,saitama,090-2222,mail-5
595
+ void release(struct address **head) {
596
+
597
+ if (*head != 0) {
598
+
599
+ release( &((*head)->next) );
600
+
601
+ free(*head);
602
+
603
+ *head = 0;
604
+
605
+ }
606
+
607
+ }
608
+
609
+
610
+
611
+ int main() {
612
+
613
+ struct address *head;
614
+
615
+ FILE* fp;
616
+
617
+ static char buff[N], name[N], address[N], tel[N], mail[N];
618
+
619
+ char *token=",";
620
+
621
+
622
+
623
+ head = 0;
624
+
625
+
626
+
627
+ if ((fp = fopen(FILENAME,"r")) != 0) {
628
+
629
+ while(fgets(buff, N, fp) != 0){
630
+
631
+ //本当の大元の文字列を書き換えないようにするために
632
+
633
+ //bufを確保してコピーし、それをstrtok()の引数にしている。
634
+
635
+ char *p;
636
+
637
+ chop(buff);
638
+
639
+ printf( "ファイルから読んだ文字列:%s\n", buff );
640
+
641
+
642
+
643
+ p = strtok(buff, token);
644
+
645
+ if ( p != NULL ) {
646
+
647
+ strcpy(name, p);
648
+
649
+ } else {
650
+
651
+ printf( "氏名の切り出しに失敗しました。\n");
652
+
653
+ break;
654
+
655
+ }
656
+
657
+
658
+
659
+ p = strtok(NULL, token);
660
+
661
+ if ( p != NULL ) {
662
+
663
+ strcpy(address, p);
664
+
665
+ } else {
666
+
667
+ printf( "住所の切り出しに失敗しました。\n");
668
+
669
+ break;
670
+
671
+ }
672
+
673
+
674
+
675
+ p = strtok(NULL, token);
676
+
677
+ if ( p != NULL ) {
678
+
679
+ strcpy(tel, p);
680
+
681
+ } else {
682
+
683
+ printf( "電話番号の切り出しに失敗しました。\n");
684
+
685
+ break;
686
+
687
+ }
688
+
689
+
690
+
691
+ p = strtok(NULL, token);
692
+
693
+ if ( p != NULL ) {
694
+
695
+ strcpy(mail, p);
696
+
697
+ } else {
698
+
699
+ printf( "メールアドレスの切り出しに失敗しました。\n");
700
+
701
+ break;
702
+
703
+ }
704
+
705
+ list_add(&head, name, address, tel, mail);
706
+
707
+ }
708
+
709
+ fclose(fp);
710
+
711
+ }
712
+
713
+ data_sort(&head);
714
+
715
+ data_show(head);
716
+
717
+
718
+
719
+
720
+
721
+ release(&head);
722
+
723
+ return 0;
724
+
725
+ }
726
+
727
+
728
+
729
+ /* 実行結果
730
+
731
+ naka@naka ~
732
+
733
+ $ cd kadai/kadai9-8
734
+
735
+
736
+
737
+ naka@naka ~/kadai/kadai9-8
738
+
739
+ $ gcc -o kad9-8b kad9-8b.c -Wall
740
+
741
+
742
+
743
+ naka@naka ~/kadai/kadai9-8
744
+
745
+ $ kad9-8b
746
+
747
+ ファイルから読んだ文字列:yamada,tone,090-1122,mail-9
748
+
749
+ ファイルから読んだ文字列:hosi,nagoya,5436,mail-7
750
+
751
+ ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2
752
+
753
+ ファイルから読んだ文字列:koko,yosida,090-2314,mail-6
754
+
755
+ ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1
756
+
757
+ ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8
758
+
759
+ ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3
760
+
761
+ ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5
762
+
763
+ hosi, nagoya, 5436, mail-7
764
+
765
+ kato, kanagawa, 080-8888, mail-2
766
+
767
+ koko, yosida, 090-2314, mail-6
768
+
769
+ naka, kamikosaka, 080-4444, mail-1
770
+
771
+ nakada, nogata, 090-6376, mail-8
772
+
773
+ saito, yamanashi, 080-6666, mail-3
774
+
775
+ suzuki, saitama, 090-2222, mail-5
776
+
777
+ yamada, tone, 090-1122, mail-9
778
+
779
+
780
+
781
+ naka@naka ~/kadai/kadai9-8
782
+
783
+ $
784
+
785
+ */
786
+
787
+
788
+
789
+
316
790
 
317
791
 
318
792
 

2

関数の追加

2018/01/28 07:56

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -78,6 +78,40 @@
78
78
 
79
79
 
80
80
 
81
+ //(*head)->nameと(*head)->next)のnameとを比べて
82
+
83
+ //小さいほうのポインタのポインタを返却値にしている。
84
+
85
+ struct address **listmin(struct address **head)
86
+
87
+ {
88
+
89
+ struct address **p;
90
+
91
+ if (*head == 0)
92
+
93
+ return 0;
94
+
95
+ if ((*head)->next == 0)
96
+
97
+ return head;
98
+
99
+ if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0)
100
+
101
+ // #include <string.h>
102
+
103
+ // int strcmp( const char *str1 , const char *str2 );
104
+
105
+ // str1<str2ならば負の値を返す。
106
+
107
+ return head;
108
+
109
+ else
110
+
111
+ return p;
112
+
113
+ }
114
+
81
115
 
82
116
 
83
117
  void exchange(struct address **p, struct address **q)

1

再投稿

2018/01/28 04:47

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -1,61 +1,55 @@
1
+ リストの構造体のデータをソートしているコードがあるんですが、その中の
2
+
3
+ exchange()関数のところを図を使って書こうと思ったのですが、うまくいきません。
4
+
5
+ その前に書かれているコードの正確な理解が出来ていないと思います。
6
+
7
+
8
+
9
+ exchange()関数のところでご教授してもらいました説明を参考に、コメントをつけました。
10
+
11
+
12
+
13
+ if (s->next != 0){}の下の文r->before = s;からs->next = r;までは
14
+
15
+ if (s->next == 0){}という条件のことでしょうか。
16
+
17
+
18
+
19
+ if{},else{}文でしているのは、「ポインタのポインタ」のつなぎ替えと思うのですが、
20
+
21
+ if{}文で何をしているのか
22
+
23
+ 条件は&((*p)->next) == q でqが(*p)->nextのアドレスをポイントしている。または
24
+
25
+ &((*q)->next) == pでpが(*q)->nextのアドレスをポイントしている場合。
26
+
27
+
28
+
29
+ ということは分かりました。
30
+
31
+
32
+
33
+ else{}文で何をしているのか
34
+
35
+ 上のif{}文の条件でないときの作業だと思うのですが、
36
+
37
+
38
+
39
+ if (s->next != 0){}から下のコード(r->before = s;から)を
40
+
41
+
42
+
43
+ どなたか詳しく、やさしい説明をしてもらえませんか。
44
+
45
+ よろしくお願いいたします。
46
+
47
+
48
+
1
49
  ```ここに言語を入力
2
50
 
3
51
  コード
4
52
 
5
- リストの構造体のデータをソートしているコードがあるんですが、その中の
6
-
7
- exchange()関数のところを図を使って書こうと思ったのですが、うまくいきません。
8
-
9
- その前に書かれているコードの正確な理解が出来ていないと思います。
10
-
11
-
12
-
13
- exchange()関数のところでご教授してもらいました説明を参考に、コメントをつけました。
14
-
15
-
16
-
17
- if (s->next != 0){}の下の文r->before = s;からs->next = r;までは
18
-
19
- if (s->next == 0){}という条件のことでしょうか。
20
-
21
-
22
-
23
- if{},else{}文でしているのは、「ポインタのポインタ」のつなぎ替えと思うのですが、
24
-
25
- if{}文で何をしているのか
26
-
27
- 条件は&((*p)->next) == q でqが(*p)->nextのアドレスをポイントしている。または
28
-
29
- &((*q)->next) == pでpが(*q)->nextのアドレスをポイントしている場合。
30
-
31
-
32
-
33
- ということは分かりました。
34
-
35
-
36
-
37
- else{}文で何をしているのか
38
-
39
- 上のif{}文の条件でないときの作業だと思うのですが、
40
-
41
-
42
-
43
- if (s->next != 0){}から下のコード(r->before = s;から)を
44
-
45
-
46
-
47
- どなたか詳しく、やさしい説明をしてもらえませんか。
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
- よろしくお願いいたします。
56
-
57
-
58
-
59
53
  // 電話帳プログラムの一部
60
54
 
61
55