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

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

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

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

Q&A

解決済

2回答

1667閲覧

c言語 リスト ノード

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2020/07/24 08:40

編集2020/07/24 13:20

C

1 2void insert(struct node *p, char x) { 3 struct node *n; 4 5 n = (struct node*)malloc(sizeof(struct node)); 6 7 n->element = x; 8 n->next = p->next; 9 p->next = n; 10

このコードで文字を追加(例:abc)すると返ってくる値がcbaとなってしまいます。例えば ./a.out abc としたとき abc と返ってきてほしいです。値の返し方はリストの先頭から順に返していくやり方です。リストの先頭に追加してしまっているのが原因だと思うんですが、リストの末尾に追加する方法がいまいちよくわかりません。insert内を変えたいのですがどう変えたら良いのかわかりません。アドバイスを頂ければ幸いです。

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

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

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

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

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

y_waiwai

2020/07/24 08:46

どこにどう返ってくる値なんでしょうか。 言ってることが意味不明です
退会済みユーザー

退会済みユーザー

2020/07/24 08:59

初学者なのでわかりにくくなってしまい申し訳ありません。解答になっているのかわかりませんが、例えば ./a.out abc としたとき abc と返ってきてほしいのですが、このコードでは cba となって返ってきてしまいます。
y_waiwai

2020/07/24 09:00

えーと、提示されてるコードはコンパイルできませんし、実行することはできません。 本当にこのコードだけで実行ファイルを作ってるんでしょうか?
退会済みユーザー

退会済みユーザー

2020/07/24 09:03

このコードは一部です。
y_waiwai

2020/07/24 09:10

なら全部提示しましょうよ
退会済みユーザー

退会済みユーザー

2020/07/24 09:15

修正しました。
kazuma-s

2020/07/24 11:06

修正するのなら、ソースコードの前後に ```C と ``` を付けてください。 行が全部左詰めになっているのを何とも思わないのですか?
退会済みユーザー

退会済みユーザー

2020/07/24 11:23

使い方がよくわかっていませんでした。すいません。
kazuma-s

2020/07/25 01:54

質問のコードを改変してはいけません。逆順に表示される元のコードがないと、質問の趣旨が伝わりません。コードを修正したかったら追記してください。そうでないと、後からこの質問と回答を見た人が何のことか理解できません。元に戻してください。
guest

回答2

0

C

1#include <stdio.h> 2#include <stdlib.h> 3 4struct node { 5 char element; 6 struct node *next; 7}; 8 9void insert(struct node *p, char x) 10{ 11 struct node *n = (struct node *)malloc(sizeof(struct node)); 12 if (n == NULL) abort(); 13 14 n->element = x; 15 n->next = p->next; 16 p->next = n; 17} 18 19void append(struct node *p, char x) 20{ 21 if (p->next == NULL) { 22 insert(p, x); 23 return; 24 } 25 append(p->next, x); 26} 27 28int main(void) 29{ 30 struct node *str = (struct node *)malloc(sizeof(struct node)); 31 if (str == NULL) abort(); 32 str->element = 'a'; 33 str->next = NULL; 34 35 append(str, 'b'); 36 append(str, 'c'); 37 struct node *p = str; 38 while (p != NULL) { 39 printf("%c", p->element); 40 p = p->next; 41 } 42 printf("\n"); 43 return 0; 44}

【解説】

insertの実装自体は問題ありません(あえていえばmalloc失敗時のエラー処理が抜けているぐらい)。しかし、この関数は名前の通り「pの次に文字を挿入する」というものです。"a"に対して'b'を'a'の次に文字を挿入したら"ab"、"ab"に対して'c'を'a'の次に文字を挿入したら"acb"です。文字の先頭だけを指定しても最後に挿入されることはありません。

では、どうすれば良いのかというと、一番単純なのは最後の文字を探して、それに対してinsertよびだしすればいいと言うことです。一番最後の文字かどうかはp->nextNULLかどうかで確認できます。もし、NULLであれば、最後なのでinsertを呼び出します。NULLでなかったら、pp->nextにして再度確認すれば良いとなります。NULLになるまで確認はwhileでループを回しても良いですし、上のコードのように再帰関数にしてもいいでしょう(末尾再帰であるため適切に最適化されていればスタックオーバーフローはおきません)。

なお、最後の文字を探すのはO(n)の計算量が必要であり、文字列が長くなればなるほど遅くなります。O(1)で処理させたい場合は双方向循環連結リストにするなどの工夫が必要でしょう。

投稿2020/07/24 09:15

raccy

総合スコア21737

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

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

0

ベストアンサー

リストのある要素の前に追加する insert ではなく、
リストのある要素の後に追加する append を用意して、それを使えばよいのでは?

C

1#include <stdio.h> 2#include <stdlib.h> 3struct node{ 4 char element; 5 struct node *next; 6}; 7 8struct node *initlist() { 9 struct node *n; 10 11 n = (struct node*)malloc(sizeof(struct node)); 12 n->next = NULL; 13 return n; 14} 15 16struct node *append(struct node *p, char x) { // ★ 17 struct node *n; // ★ 18 n = (struct node*)malloc(sizeof(struct node)); // ★ 19 n->element = x; // ★ 20 n->next = p->next; // ★ 21 p->next = n; // ★ 22 return n; // ★ 23} 24 25void printlist(struct node *p) { 26 if(p->next == NULL) { 27 putchar('\n'); 28 }else { 29 p = p->next; 30 putchar(p->element); 31 printlist(p); 32 // putchar(p->element); // ★ 削除 33 } 34} 35 36int main(int argc, char *argv[]) { 37 struct node *list, *head, *tail; // ★ tail を追加 38 char *p; 39 if (argc<2) 40 exit(-1); 41 42 tail = list = initlist(); // ★ tail を追加 43 for (p = argv[1]; *p; p++) // ★ 44 tail = append(tail, *p); // ★ tail に追加。tail を更新 45 46 printlist(list); 47 // printf("\n"); // ★ 削除 48 for (; list; ) { 49 head = list; 50 list = list->next; 51 free(head); 52 } 53 return 0; 54}

追記

C

1void insert(struct node *p, char x) { 2 while (p->next != NULL) p = p->next; // ★ 追加: 最後を見つける 3 4 struct node *n; 5 n = (struct node*)malloc(sizeof(struct node)); 6 n->element = x; 7 n->next = p->next; 8 p->next = n; 9} 10 11void printlist(struct node *p) { 12 if(p->next == NULL) { 13 putchar('\n'); 14 }else { 15 p = p->next; 16 putchar(p->element); 17 printlist(p); 18 // putchar(p->element); // ★ 削除 19 } 20}

投稿2020/07/24 12:17

編集2020/07/24 13:03
kazuma-s

総合スコア8224

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

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

退会済みユーザー

退会済みユーザー

2020/07/24 12:47

解答ありがとうございます。ですが、あくまでもinsert内を変更して書きたいのですが、appendでなくても書けるのでしょうか?
退会済みユーザー

退会済みユーザー

2020/07/24 13:18

納得できました。お手数おかけしました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問