質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

698閲覧

「ポインタのポインタ」のつなぎ替えをしている部分がわからない

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/01/27 23:40

編集2018/01/30 06:17

リストの構造体のデータをソートしているコードがあるんですが、その中の
exchange()関数のところを図を使って書こうと思ったのですが、うまくいきません。
その前に書かれているコードの正確な理解が出来ていないと思います。

exchange()関数のところでご教授してもらいました説明を参考に、コメントをつけました。

if (s->next != 0){}の下の文r->before = s;からs->next = r;までは
if (s->next == 0){}という条件のことでしょうか。

if{},else{}文でしているのは、「ポインタのポインタ」のつなぎ替えと思うのですが、
if{}文で何をしているのか
条件は&((*p)->next) == q でqが(*p)->nextのアドレスをポイントしている。または
&((*q)->next) == pでpが(*q)->nextのアドレスをポイントしている場合。

ということは分かりました。

else{}文で何をしているのか
上のif{}文の条件でないときの作業だと思うのですが、

if (s->next != 0){}から下のコード(r->before = s;から)を

どなたか詳しく、やさしい説明をしてもらえませんか。
よろしくお願いいたします。

//codepad.org/B83f1FSq //正常動作(リスト構造) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> // #define N 256 #define FILENAME "address.csv" struct address{ char name[N]; char address[N]; char tel[N]; // 電話番号 char mail[N]; struct address *next; struct address *before; }; void data_show(struct address* head); void data_sort(struct address** head); void chop(char *p){ for (; *p; p++) ; p--; while (*p == '\r' || *p == '\n') *(p--) = 0; } void list_add(struct address **head, char *name, char *address, char *tel, char *mail) { struct address *p; if ((p = malloc(sizeof(struct address))) != 0) { strcpy(p->name, name); strcpy(p->address, address); strcpy(p->tel, tel); strcpy(p->mail, mail); p->next = *head; if (p->next != 0) p->next->before = p; p->before = 0; *head = p; } } void data_show(struct address *head) { if (head != 0) { printf(" %s, %s, %s, %s\n", head->name, head->address, head->tel, head->mail); data_show(head->next); } } struct address **listmin(struct address **head) { struct address **p; if (*head == 0) return 0; if ((*head)->next == 0) return head; // if (strcmp((*head)->name, (*(p = listmin(&((*head)->next))))->name) < 0) return head; else return p; } //大小を入れ替える void exchange(struct address **p, struct address **q) { struct address *r, *s, *t; assert(*p != 0 && *q != 0); if (p == q) return; r = *p; s = *q; if (&((*p)->next) == q || &((*q)->next) == p) { if (s->next != 0){ s->next->before = r; } s->before = r->before; r->before = s; *p = s; *q = s->next; s->next = r; return; } else { if (s->next != 0) s->next->before = r; if (r->next != 0) r->next->before = s; t = s->before; s->before = r->before; r->before = t; t = r->next; r->next = s->next; s->next = t; *p = s; *q = r; } } void data_sort(struct address **head) { struct address **p; if (*head != 0) { for (;;) { p = listmin(head); //関数listmin(head)は、名前からリストの全ての要素をチェックして、 //いちばん小さいnameを持つ要素を返していると思われます。 //そうでないと正しくソートされません。 if (p == 0)break; exchange(head, p); //大小を入れ替える head = &((*head)->next); //見つけたいちばん小さい要素を関数exchange(head, p)で先頭に移動しています。 } } } void release(struct address **head) { if (*head != 0) { release( &((*head)->next) ); free(*head); *head = 0; } } int main() { struct address *head; FILE* fp; static char buff[N], name[N], address[N], tel[N], mail[N]; char *token=","; head = 0; if ((fp = fopen(FILENAME,"r")) != 0) { while(fgets(buff, N, fp) != 0){ //本当の大元の文字列を書き換えないようにするために //bufを確保してコピーし、それをstrtok()の引数にしている。 char *p; chop(buff); printf( "ファイルから読んだ文字列:%s\n", buff ); p = strtok(buff, token); if ( p != NULL ) { strcpy(name, p); } else { printf( "氏名の切り出しに失敗しました。\n"); break; } p = strtok(NULL, token); if ( p != NULL ) { strcpy(address, p); } else { printf( "住所の切り出しに失敗しました。\n"); break; } p = strtok(NULL, token); if ( p != NULL ) { strcpy(tel, p); } else { printf( "電話番号の切り出しに失敗しました。\n"); break; } p = strtok(NULL, token); if ( p != NULL ) { strcpy(mail, p); } else { printf( "メールアドレスの切り出しに失敗しました。\n"); break; } list_add(&head, name, address, tel, mail); } fclose(fp); } data_sort(&head); data_show(head); release(&head); return 0; } /* 実行結果 naka@naka ~ $ cd kadai/kadai9-8 naka@naka ~/kadai/kadai9-8 $ gcc -o kad9-8b kad9-8b.c -Wall naka@naka ~/kadai/kadai9-8 $ kad9-8b ファイルから読んだ文字列:yamada,tone,090-1122,mail-9 ファイルから読んだ文字列:hosi,nagoya,5436,mail-7 ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2 ファイルから読んだ文字列:koko,yosida,090-2314,mail-6 ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1 ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8 ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3 ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5 hosi, nagoya, 5436, mail-7 kato, kanagawa, 080-8888, mail-2 koko, yosida, 090-2314, mail-6 naka, kamikosaka, 080-4444, mail-1 nakada, nogata, 090-6376, mail-8 saito, yamanashi, 080-6666, mail-3 suzuki, saitama, 090-2222, mail-5 yamada, tone, 090-1122, mail-9 naka@naka ~/kadai/kadai9-8 $ */ /* 実行結果 naka@naka ~ $ cd kadai/kadai9-8 naka@naka ~/kadai/kadai9-8 $ gcc -o kad9-8b kad9-8b.c -Wall naka@naka ~/kadai/kadai9-8 $ kad9-8b ファイルから読んだ文字列:yamada,tone,090-1122,mail-9 ファイルから読んだ文字列:hosi,nagoya,5436,mail-7 ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2 ファイルから読んだ文字列:koko,yosida,090-2314,mail-6 ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1 ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8 ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3 ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5 hosi, nagoya, 5436, mail-7 kato, kanagawa, 080-8888, mail-2 koko, yosida, 090-2314, mail-6 naka, kamikosaka, 080-4444, mail-1 nakada, nogata, 090-6376, mail-8 saito, yamanashi, 080-6666, mail-3 suzuki, saitama, 090-2222, mail-5 yamada, tone, 090-1122, mail-9 naka@naka ~/kadai/kadai9-8 $ */ /* 実行結果 naka@naka ~ $ cd kadai/kadai9-8 naka@naka ~/kadai/kadai9-8 $ gcc -o kad9-8b kad9-8b.c -Wall naka@naka ~/kadai/kadai9-8 $ kad9-8b ファイルから読んだ文字列:yamada,tone,090-1122,mail-9 ファイルから読んだ文字列:hosi,nagoya,5436,mail-7 ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2 ファイルから読んだ文字列:koko,yosida,090-2314,mail-6 ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1 ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8 ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3 ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5 hosi, nagoya, 5436, mail-7 kato, kanagawa, 080-8888, mail-2 koko, yosida, 090-2314, mail-6 naka, kamikosaka, 080-4444, mail-1 nakada, nogata, 090-6376, mail-8 saito, yamanashi, 080-6666, mail-3 suzuki, saitama, 090-2222, mail-5 yamada, tone, 090-1122, mail-9 naka@naka ~/kadai/kadai9-8 $ */ /* 実行結果 naka@naka ~ $ cd kadai/kadai9-8 naka@naka ~/kadai/kadai9-8 $ gcc -o kad9-8b kad9-8b.c -Wall naka@naka ~/kadai/kadai9-8 $ kad9-8b ファイルから読んだ文字列:yamada,tone,090-1122,mail-9 ファイルから読んだ文字列:hosi,nagoya,5436,mail-7 ファイルから読んだ文字列:kato,kanagawa,080-8888,mail-2 ファイルから読んだ文字列:koko,yosida,090-2314,mail-6 ファイルから読んだ文字列:naka,kamikosaka,080-4444,mail-1 ファイルから読んだ文字列:nakada,nogata,090-6376,mail-8 ファイルから読んだ文字列:saito,yamanashi,080-6666,mail-3 ファイルから読んだ文字列:suzuki,saitama,090-2222,mail-5 hosi, nagoya, 5436, mail-7 kato, kanagawa, 080-8888, mail-2 koko, yosida, 090-2314, mail-6 naka, kamikosaka, 080-4444, mail-1 nakada, nogata, 090-6376, mail-8 saito, yamanashi, 080-6666, mail-3 suzuki, saitama, 090-2222, mail-5 yamada, tone, 090-1122, mail-9 naka@naka ~/kadai/kadai9-8 $ */

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ところで、ソートは自前で実装する必要はありません。標準ライブラリを使いましょう。

bash

1#include <stdlib.h> 2#include <string.h> 3 4int compare_address_name(struct address *l, struct address *l) { 5 return strcmp(l->name, r->name); 6} 7 8void data_sort(struct address **head) { 9 struct address *array[MAX_LIST_SIZE]; # サイズは決め打ち:-) 10 struct address *h, **a; 11 12 if (head == 0 || *head == 0) { 13 return; 14 } 15 16 # リストの各要素のポインタを配列に代入する。 17 h = *head; 18 a = array; 19 while (h != 0) { 20 *a++ = h; 21 h = h->next; 22 } 23 24 # 配列の各要素をソートする。 25 qsort(array, sizeof(struct address *), a - array, compare_address_name); 26 27 # 配列の各要素をリストに追加する。 28 h = 0; 29 while (--a >= array) { 30 *a->next = h; 31 *a->before = 0; 32 h = *a; 33 } 34 35 *head = h; 36}

投稿2018/01/28 04:49

編集2018/01/28 05:28
hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/01/28 05:59

わたしが何をしたいのかよく表現できていないで、すみません。 教科書で電話帳プログラムを作る課題がありまして。ネットで探したプログラムの解読をしています。 プログ自体は面倒くさいことをしているみたいなのですが、ポインタのポインタが出てきて、理解できないので勉強になると思ってやっていますが。みなさん見たくないと言われるくらい、よくないコードのようです。 標準のソート関数まで間口が広がると、そこをまた勉強しなければいけないので、 とりあえず、このexchange()関数の中身をりかいしたいのですが。 単方向のリストのつなぎ替えを完全に理解してから、ここに来るべきでしょうか。 ご助言をお願いいたします。
退会済みユーザー

退会済みユーザー

2018/01/28 06:01

疲れてきたので、今日も自爆しそうです。少し休みます。
rubato6809

2018/01/28 07:08

「教科書で電話帳プログラムを作る課題がありまして。ネットで探したプログラム…」 ネットで探した、どこで見つけたのか、そのURLを示してもらえますか? 先の質問にあったコードを動かしてみたら、動きが大体見えてきましたが、私も「よくないコード」、少なくともお手本にしてもらいたくないコードだと思います。時間をかければ解説できますが、もっと質の良いコードを学んだほうが良いと思っています。
退会済みユーザー

退会済みユーザー

2018/01/28 07:11

ありがとうございます。ポインタのポインタの動きを知りたいのですが、 なんとかなりませんか。
退会済みユーザー

退会済みユーザー

2018/01/28 07:12

途中まで何とか理解しています。
rubato6809

2018/01/28 07:21

で、どこにあったコードですか?
退会済みユーザー

退会済みユーザー

2018/01/28 07:28

URL codepad.org/B83f1FSq です。すみません。よろしくおねがいします。 色々コメントをしていて、コードが違っている可能性があります。
退会済みユーザー

退会済みユーザー

2018/01/28 07:57

コードを修正しました。正常動作します。
a_saitoh

2018/01/30 01:27

課題でやってるというのなら、ネットで探したプログラムの解読を、というのは下策でしょう。exchangeでソートってのは配列ではいいけどリストではそんなによくないし。てか、自力で解読できるのならそれもいいけど、解読を他人に頼るようならそれは勉強が足りないので、もっと前の段階から総復習したほうがいいのでは?と職業柄考えてしまいます。あと、解読して理解したうえで自力で書くのはいいですが、ネットで拾ったのを手直しして課題として提出するのは不正行為。
guest

0

if(&((*p)->next) == q || &((*q)->next) == p)の条件式が何を意味しているかは理解していますか?
ifの条件式が真になる場合は図のようになりますが、elseの場合はどのようなケースが考えられますか?
イメージ説明

[追記]
提示されたexchange()関数を実行してみました。
仕様が不明なので何とも言えないのですが、正常に動作しているようには見えません。
exchange()関数実行後にリンクリストが壊れているように見えますが・・・。
正常動作はどのように確認しましたか?

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <assert.h> 4 5#define N 256 6#define FILENAME "address.csv" 7 8struct address{ 9 char name[N]; 10 char address[N]; 11 char tel[N]; // 電話番号 12 char mail[N]; 13 struct address *next; 14 struct address *before; 15}; 16 17void exchange(struct address **p, struct address **q) 18{ 19 struct address *r, *s, *t; 20 assert(*p != 0 && *q != 0); 21 22 if (p == q) 23 return; 24 25 r = *p; 26 s = *q; 27 if (&((*p)->next) == q || &((*q)->next) == p) { 28 if (s->next != 0){ 29 s->next->before = r; 30 } 31 r->before = s; 32 s->before = r->before; 33 *p = s; 34 *q = s->next; 35 s->next = r; 36 return; 37 } else { 38 if (s->next != 0){ 39 s->next->before = r; 40 } 41 t = s->before; 42 s->before = r->before; 43 if (r->next != 0){ 44 r->next->before = s; 45 } 46 r->before = t; 47 t = r->next; 48 r->next = s->next; 49 s->next = t; 50 *p = s; 51 *q = r; 52 } 53} 54 55void data_create( struct address **head ) 56{ 57 int i; 58 struct address data[8] = { 59 { "yamada","tone","090-1122","mail-9", NULL, NULL }, 60 { "hosi","nagoya","090-1122","mail-9", NULL, NULL }, 61 { "kato","kanagawa","090-1122","mail-9", NULL, NULL }, 62 { "koko","yosida","090-1122","mail-9", NULL, NULL }, 63 { "naka","kamikosaka","090-1122","mail-9", NULL, NULL }, 64 { "nakada","nogata","090-1122","mail-9", NULL, NULL }, 65 { "saito","yamanashi","090-1122","mail-9", NULL, NULL }, 66 { "suzuki","saitama","090-1122","mail-9", NULL, NULL } 67 }; 68 struct address *p[9] = {NULL}; 69 70 for ( i = 0; i < 8; i++ ) { 71 p[i] = malloc( sizeof(struct address)); 72 *p[i] = data[i]; 73 } 74 75 for ( i = 0; i < 8; i++ ){ 76 if ( p[i] != NULL ) { 77 p[i]->next = p[i+1]; 78 if ( i > 0 ) { 79 p[i]->before = p[i-1]; 80 } 81 } 82 } 83 84 *head = p[0]; 85} 86 87int main() 88{ 89 struct address *head = NULL; 90 struct address *p = NULL; 91 struct address *q = NULL; 92 data_create( &head ); 93 94 printf( "オリジナルデータ表示\n"); 95 p = head; 96 while ( p != NULL ) { 97 printf("addr=%08x, next=%08x, before=%08x, %s\n", p, p->next, p->before, p->name ); 98 p = p->next; 99 } 100 printf("###################\n"); 101 printf( "exchange() 実行前\n"); 102 p = head->next; 103 q = head->next->next; 104 printf("p: addr=%08x, next=%08x, before=%08x, %s\n", p, p->next, p->before, p->name ); 105 printf("q: addr=%08x, next=%08x, before=%08x, %s\n", q, q->next, q->before, q->name ); 106 exchange( &p, &q ); 107 printf( "exchange() 実行後\n"); 108 printf("p: addr=%08x, next=%08x, before=%08x, %s\n", p, p->next, p->before, p->name ); 109 printf("q: addr=%08x, next=%08x, before=%08x, %s\n", q, q->next, q->before, q->name ); 110 111 printf("###################\n"); 112 printf( "変更後データ表示\n"); 113 p = head; 114 while ( p != NULL ) { 115 printf("addr=%08x, next=%08x, before=%08x, %s\n", p, p->next, p->before, p->name ); 116 p = p->next; 117 } 118 119 120 return 0; 121}

実行結果
$gcc -o main *.c
$main
オリジナルデータ表示
addr=01675010, next=01675430, before=00000000, yamada
addr=01675430, next=01675850, before=01675010, hosi
addr=01675850, next=01675c70, before=01675430, kato
addr=01675c70, next=01676090, before=01675850, koko
addr=01676090, next=016764b0, before=01675c70, naka
addr=016764b0, next=016768d0, before=01676090, nakada
addr=016768d0, next=01676cf0, before=016764b0, saito
addr=01676cf0, next=00000000, before=016768d0, suzuki
###################
exchange() 実行前
p: addr=01675430, next=01675850, before=01675010, hosi
q: addr=01675850, next=01675c70, before=01675430, kato
exchange() 実行後
p: addr=01675850, next=01675850, before=01675850, kato
q: addr=01675430, next=01675c70, before=01675430, hosi
###################
変更後データ表示
addr=01675010, next=01675430, before=00000000, yamada
addr=01675430, next=01675c70, before=01675430, hosi
addr=01675c70, next=01676090, before=01675430, koko
addr=01676090, next=016764b0, before=01675c70, naka
addr=016764b0, next=016768d0, before=01676090, nakada
addr=016768d0, next=01676cf0, before=016764b0, saito
addr=01676cf0, next=00000000, before=016768d0, suzuki

投稿2018/01/28 02:51

編集2018/01/28 06:43
TaroToyotomi

総合スコア1430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/01/28 04:39

ありがとうございます。はい理解しています。その他の矢印はこれからかくていするのですか。 上の図のr->before,s->next,s->before,下の図のr->next,r->before、s->beforeはこれから変わってくるのですよね。余談ですがこの図はどのように作られているのですか。わたしは出来ないのでかみでやっています。
TaroToyotomi

2018/01/28 06:47

申し訳ありませんが、仕様がわからないコードの説明はできません。 exchange()関数の仕様を明記してください。 ちなみに、図はWindowsに標準でインストールされているペイントで書きました。
rubato6809

2018/01/28 07:52 編集

「elseの場合はどのようなケースが考えられますか?」 この問いに対する答えがありません。考えるなり、図に描いてみるなり、何かレスポンスしてください。 「上のif{}文の条件でないとき・・・」それはif文だから、そうだけど、そうなる状態はどんな状態か?という問いです。
退会済みユーザー

退会済みユーザー

2018/01/28 08:03

それがどんな場合かわかりません。色々回答いただいて、順番にみています。 そうなる状態はどんな状態か?がわかりません。 「if(&((*p)->next) == q || &((*q)->next) == p)の条件式が何を意味しているか」は丁寧な説明を 何回も読み直して、やっとりかいできているじょうたいです。 よろしくおねがいします。
rubato6809

2018/01/29 00:53

繰り返すが、どんな丁寧な説明よりも図に描いて見ることが一番。 質問者自身はリスト構造の図を描いてみたのかな? 「かみでやっています」・・・紙に描いたものがあるなら、私がやったように、写真に撮って貼り付けてみてください。 TaroToyotomiさん > 実行後にリンクリストが壊れているよう プログラムの中に気になる場所がありました。図を描きながら見なおしたら、そこはバグだとわかりました。リンクリストが壊れるのは、そのせいでしょう。 私は外に出るので、後で時間ができたら説明したいと思います。
退会済みユーザー

退会済みユーザー

2018/01/29 09:56

バグがあって「実行後にリンクリストが壊れているよう」というのは、私にはまだ理解できないです。 ごめんなさい。 今からすこしずつコードを見たいと思います。
rubato6809

2018/01/29 12:09 編集

if (&((*p)->next) == q || &((*q)->next) == p) { if (s->next != 0) s->next->before = r; r->before = s; s->before = r->before; ここの最後の2行は順序が逆。つまり if (&((*p)->next) == q || &((*q)->next) == p) { if (s->next != 0) s->next->before = r; s->before = r->before; r->before = s; とするべきだと思う。
rubato6809

2018/01/29 12:04

else側にある、この5行は t = s->before; s->before = r->before; if (r->next != 0) r->next->before = s; r->before = t; バグではないけど、順序を替えることができる。このように。 if (r->next != 0) r->next->before = s; t = s->before; s->before = r->before; r->before = t; 後半の3行がひとまとまりになり、意味がわかりやすくなります。
退会済みユーザー

退会済みユーザー

2018/01/29 13:12

ありがとうございます。 今書き変えてテストしました。 正常に動作しました。と思っていますが、バグはこれで治っているのでしょうか。
TaroToyotomi

2018/01/29 15:11

rubato6809さんフォローありがとうございます。 自分も図を描きながら腑に落ちないなぁと思ってましたがそれ以上追いかけるのはやめちゃいました。 流石です。 >sanchu52さん ところで、何がバグだったかわかりましたか? 私が貼った実行結果のオリジナルデータとexhange()呼出し後の変更後データを見比べればわかると思います。(1行減ってますよね?)
退会済みユーザー

退会済みユーザー

2018/01/29 16:02

そうですね。私はコメントしているとき、コードがおかしくなったみたいで、 正常に動作していたオリジナルのコードで書き変えたコードは正常にひょうじされました。 ありがとうございます。 今夜はとりあえず、if()文の図は出来ました。あとelse()文の図を書きたいと思います。 TaroToyotomiさん、rubato6809さん今後ともよろしくお願いいたします。
rubato6809

2018/01/29 23:04 編集

> 私はコメントしているとき、コードがおかしくなったみたい いいえ。貴方が見つけたというコードに、初めからバグがありますよ。ちゃんとチェックしてコメントしてますか? http://codepad.org/B83f1FSq > if()文の図は出来ました では、その図をどこかに貼り付けて公開してください。貴方自身が手を動かして努力しているという証しを立ててください。 自分で手を動かし自分でプログラムを書かなければプログラムを書く力はつきません。同じく、リスト構造を自分で描くことが出来なければ何時まで経っても、リスト構造を扱うコードを理解することはおろか、自分で設計し書くことはできません。何度でも繰り返しますが、コードの字面・コメントより、図に描いてみる、或いは図に描ける事、操作する前のリストの状況を示すことができ、それがどういう繋ぎに変化すればよいのかイメージできることが何よりも理解への近道です。
退会済みユーザー

退会済みユーザー

2018/01/29 23:34

はいわかりました。おっしゃるとおりです。がんばります。
rubato6809

2018/01/29 23:46

私はもう少し努力すれば else 以下を図示して解説できるところまできたけど、貴方自身が「if文の図は出来ました」とおっしゃる図を公開しない限り、私自身に努力義務は無いと考えています。そのことをお忘れなく。 私以外に図を描いて説明する方がいらっしゃるなら、私の要求に応えなくても良いけどね。
退会済みユーザー

退会済みユーザー

2018/01/29 23:50

おはようございます。今写真に撮ってアップする準備をしています。 少しお待ちください。
退会済みユーザー

退会済みユーザー

2018/01/30 00:32

sdカードに写真が入っているのですが、 パソコンで見るとデータが表示されません。去年買ったばかりのDELLですが、 カードリーダの不具合ですかね。 データはLibreOffice Impressで作りました。写真はダメ見たいですので、 このデータをアップする方法を教えて頂けますか。
rubato6809

2018/01/30 00:55

「アップする方法」・・・私に答えを期待してるようだけど、それはリストの繋ぎ換えの問題ではないですね。何から何まで私が対応しなきゃならない義理は無い、とコメントしておきます。
退会済みユーザー

退会済みユーザー

2018/01/30 04:38

写真を撮ってフォルダに保存するところまできました。 後はどこかに貼り付けてアップします。 時間がかかりそうです。
退会済みユーザー

退会済みユーザー

2018/01/30 04:44

写真はkadai9-8のフォルダに保存するところまできました。 後はどこに貼り付けるのか、探してあっぷします。 時間かかりそうです。
退会済みユーザー

退会済みユーザー

2018/01/30 04:44

休憩します。
guest

0

長いので少しずつ回答します。

p = listmin(head);
//(*head)->nameと(*head)->next)のnameとを比べて
//小さいほうのポインタのポインタを返却値にしている。

関数listmin(head)は、名前からリストの全ての要素をチェックして、いちばん小さいnameを持つ要素を返していると思われます。そうでないと正しくソートされません。

if (p == 0)
break;

おそらく、リストが残り1つの場合、ソートが完了したとして、ループを抜けます。

exchange(head, p);
//大小を入れ替える

ここでは、見つけたいちばん小さい要素を関数exchange(head, p)で先頭に移動しています。

head = &((*head)->next);

ループの最後では、先頭の次の要素を新たな先頭にして、処理を繰り返します。

で、関数exchange(head, p)の中身ですが、以下の処理を行っています。

  1. リストheadから要素pを引っこ抜いて、抜けた部分を繋ぎ直す。
  2. リストheadの先頭に要素pを追加して、要素pを新しいリストの先頭にする。

if (&((*p)->next) == q || &((*q)->next) == p) {

尚、この条件ではリストの先頭要素と要素pが隣り合っているかどうかチェックしていますが、ポインタのつなぎ替えの順番を工夫すれば、1つにまとめることも可能です。

投稿2018/01/28 02:45

編集2018/01/28 05:35
hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/01/28 04:56

ありがとうございます。 関数exchange(head, p)の中身ですが、以下の処理を行っています。 リストheadから要素pを引っこ抜いて、抜けた部分を繋ぎ直す。 リストheadの先頭に要素pを追加して、要素pを新しいリストの先頭にする。 すみません。この辺を少し詳しく説明していただけませんか。
退会済みユーザー

退会済みユーザー

2018/01/28 05:13

if (p == 0)break; //リストが残り1つの場合、ソートが完了したとして、ループを抜けます。 がよくわからないのですが、
hichon

2018/01/28 05:34

listmin(head)の中身がわからないので、「if (p == 0)break」の部分は推測です。
rubato6809

2018/01/28 07:45

if (p == 0)break; //リストが残り1つの場合、ソートが完了したとして、ループを抜けます。 がよくわからない この if 〜 break; は data_sort()関数の中ですよね?コメントつけてますが、それでもわかりませんか?
退会済みユーザー

退会済みユーザー

2018/01/28 08:11

すみません。回答をもらった人からのコメントを分からなくなる前に、貼り付けてあとで検討するために 貼り付けただけです。まだわたしは分からない箇所なんです。 教わった事を張り付けていけば、図にしたり、理解するのにヒントになるつもりでやっていました。
退会済みユーザー

退会済みユーザー

2018/01/28 08:14

p==0はポインタのポインタがNULLで何も指していない状態ですよね。 リストが残り1つの場合、はどうしてわかるんですか?
hichon

2018/01/28 09:49 編集

listmin(head)のコードを貼ってくれたのですね。 実際のコードは、「リストの先頭が空のとき、返り値が0になるので、ソートが完了したとして、ループを抜けます。」ですね。
退会済みユーザー

退会済みユーザー

2018/01/28 20:34

ありがとうございます。今日お昼仕事です。 帰ったらまた続きをやりたいと思います。 これからもよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問