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

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

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

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

Q&A

解決済

2回答

1512閲覧

c言語 自己参照型構造体 逆表示

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2020/06/05 12:54

前提・実現したいこと

・前提
http://www9.plala.or.jp/sgwr-t/c/sec15-5.html のサイトを拝見させていただき参考にプログラムを作成しました。また主にこのサイトにある説明でリスト構造については学習をしました。
・実現したいこと
構造体をリスト形式にし、入力をリストに格納。それを逆順(リスト的には逆、入力でみると順になるが)で表示するプログラムの出力を正常にしたいです。
リストに格納した順番(3,3 2,2 1,1)の形では出力がうまくいっているため、自らで作成したreverse_list関数内で間違いが起きてると思いますが、ここで長時間止まってしまっているので質問させていただきます。

発生している問題・エラーメッセージ

2つの数を入力してください(両方0で終了) num1 = 1 num2 = 1 ------------------------- num1 = 2 num2 = 2 ------------------------- num1 = 3 num2 = 3 ------------------------- num1 = 0 num2 = 0 -------------------------

最後の破線の下に入力順に値が表示される予定ですが何も表示されません。

該当のソースコード

C

1#include <stdio.h> 2#include <stdlib.h> 3 4/* 構造体定義 */ 5struct list{ 6 int num1,num2; 7 struct list *next; 8}; 9 10/* 関数定義 */ 11struct list *add_list(int x,int y,struct list *head); 12struct list *reverse_list(struct list *head,struct list *head2); 13void show_list(struct list *p); 14void free_list(struct list *p); 15 16 17int main(void){ 18 struct list *head; //先頭ポインタ 19 struct list *head2; //順(リストを逆から)表示するためのポインタ 20 21 int num1,num2; 22 23 head = NULL; //先頭ポインタにNULLを代入 24 head2 = NULL; 25 26 /* 入力処理 */ 27 printf("2つの数を入力してください(両方0で終了)\n"); 28 while(1){ 29 printf("num1 = "); 30 scanf("%d",&num1); 31 printf("num2 = "); 32 scanf("%d",&num2); 33 printf("-------------------------\n"); 34 35 //終了条件 36 if(num1 == 0 && num2 == 0) break; 37 38 head = add_list(num1,num2,head); 39 } 40 41 head2 = reverse_list(head,head2); 42 show_list(head2); 43 free_list(head); 44 free_list(head2); 45} 46 47/* リストにデータを格納する関数 */ 48struct list *add_list(int num1,int num2,struct list *head){ 49 struct list *p; 50 51 //記憶領域の確保 52 if((p = (struct list *)malloc(sizeof(struct list))) == NULL){ 53 printf("malloc error\n"); 54 exit(EXIT_FAILURE); 55 } 56 57 //リストにデータを登録 58 p->num1 = num1; 59 p->num2 = num2; 60 61 //ポインタの繋ぎ変え 62 p->next = head; //今までの先頭ポインタを次ポインタに 63 head = p; //新たな領域を先頭ポインタに 64 65 return head; 66} 67 68/* データを順に格納する関数 */ 69struct list *reverse_list(struct list *head,struct list *head2) 70{ 71 struct list *p; 72 73 //記憶領域の確保 74 if((p = (struct list *)malloc(sizeof(struct list))) == NULL){ 75 printf("malloc error\n"); 76 exit(EXIT_FAILURE); 77 } 78 79 while(head != NULL){ 80 head2->num1 = head->num1; 81 head2->num2 = head->num2; 82 83 p->next = head2; 84 head2 = p; 85 86 head = head->next; 87 } 88 89 return p; 90} 91 92/* リストのデータを表示する関数 */ 93void show_list(struct list *p) 94{ 95 while (p != NULL) { /* 次ポインタがNULLまで処理 */ 96 printf("num1=%d,num2=%d\n", p->num1, p->num2); 97 p = p->next; 98 } 99} 100 101/* リスト解放の関数 */ 102void free_list(struct list *p) 103{ 104 struct list *p2; 105 106 while (p != NULL) { /* 次ポインタがNULLまで処理 */ 107 p2 = p->next; 108 free(p); 109 p = p2; 110 } 111}

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

直しました。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4/* 構造体定義 */ 5struct list{ 6 int num1,num2; 7 struct list *next; 8}; 9 10/* 関数定義 */ 11struct list *add_list(int x,int y,struct list *head); 12struct list *reverse_list(struct list *head); 13void show_list(struct list *p); 14void free_list(struct list *p); 15 16 17int main(void){ 18 struct list *head; //先頭ポインタ 19 struct list *head2; //順(リストを逆から)表示するためのポインタ 20 21 int num1,num2; 22 23 head = NULL; //先頭ポインタにNULLを代入 24 head2 = NULL; 25 26 /* 入力処理 */ 27 printf("2つの数を入力してください(両方0で終了)\n"); 28 while(1){ 29 printf("num1 = "); 30 scanf("%d",&num1); 31 printf("num2 = "); 32 scanf("%d",&num2); 33 printf("-------------------------\n"); 34 35 //終了条件 36 if(num1 == 0 && num2 == 0) break; 37 38 head = add_list(num1,num2,head); 39 } 40 41 head2 = reverse_list(head); 42 show_list(head2); 43 free_list(head); 44 free_list(head2); 45} 46 47/* リストにデータを格納する関数 */ 48struct list *add_list(int num1,int num2,struct list *head){ 49 struct list *p; 50 51 //記憶領域の確保 52 if((p = (struct list *)malloc(sizeof(struct list))) == NULL){ 53 printf("malloc error\n"); 54 exit(EXIT_FAILURE); 55 } 56 57 //リストにデータを登録 58 p->num1 = num1; 59 p->num2 = num2; 60 61 //ポインタの繋ぎ変え 62 p->next = head; //今までの先頭ポインタを次ポインタに 63 head = p; //新たな領域を先頭ポインタに 64 65 return head; 66} 67 68/* データを順に格納する関数 */ 69struct list *reverse_list(struct list *head) 70{ 71 struct list *head2; 72 73 if (head == NULL) 74 return NULL; 75 76 // 記憶領域の確保 77 if ((head2 = (struct list *)malloc(sizeof(struct list))) == NULL) { 78 printf("malloc error\n"); 79 exit(EXIT_FAILURE); 80 } 81 head2->num1 = head->num1; 82 head2->num2 = head->num2; 83 head2->next = reverse_list(head->next); 84 85 return head2; 86} 87 88/* リストのデータを表示する関数 */ 89void show_list(struct list *p) 90{ 91 while (p != NULL) { /* 次ポインタがNULLまで処理 */ 92 printf("num1=%d,num2=%d\n", p->num1, p->num2); 93 p = p->next; 94 } 95} 96 97/* リスト解放の関数 */ 98void free_list(struct list *p) 99{ 100 struct list *p2; 101 102 while (p != NULL) { /* 次ポインタがNULLまで処理 */ 103 p2 = p->next; 104 free(p); 105 p = p2; 106 } 107}

ちょっと楽をしましたが動くはずです。
あなたにはいろいろ足りてない部分があります。
まず、struct listはtypedefを使えばstructを省略できます。

C

1typedef struct tag_list { 2 int num1, num2; 3 struct tag_list *next; 4} list;

Cについての熟練度が足りない。これはAOJ(Aizu Online Judge)の基本的な問題を少しやれば身につくでしょう。AOJは他の人の回答を見ることもできるので、自分のコードスタイルをよくすることも簡単にできます。

次に、再帰関数についての造詣を深めたほうがよろしいかと。それはSICP(Structure and Interpretation of Computer Programs)を2章の終わりまでやればいいです。日本語訳も無料で読めます。ただしCではなくSchemeです。Cはシステムプログラミング用の言語なので一回GC付きの言語で世界観をひっくり返しておいたほうがいいでしょう。3章はオブジェクト指向等々、4章はインタプリタ、5章はコンパイラについての解説ですがSICPの3〜5章を読まずとももっとよい良書があるのでSICPを完読することはおすすめしないです。

投稿2020/06/05 14:21

anndonut

総合スコア667

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

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

退会済みユーザー

退会済みユーザー

2020/06/05 23:48

何から何までありがとうございます。コードを見たところ無理に継続条件としてheadを進めずに、再帰関数としてheadのnextを与え、NULLなら終わるとすることにとても納得できました。 AOJやSICPといったサイトも拝見します。本当にありがとうございました。
guest

0

C言語である程度のコードを書くなら、まずはデバッグできる環境を整えましょう。
Eclipseとか、WindowsならVisualStudioとか。
コードの途中で実行を止めて、変数のナカミを参照したり、1行づつ実行させたりできます。

そうすればアテずっぽでコードを書かなくて済むようになります

投稿2020/06/05 13:32

y_waiwai

総合スコア88042

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

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

退会済みユーザー

退会済みユーザー

2020/06/05 23:51

Visual Studio Codeでの開発をしております。デバックを繰り返し、あまりに解決しないため質問をさせていただきました。しかし質問をする前にもう少し理解を深めるべきだと把握しました。 環境の記述を怠っていました。申し訳ありませんでした。
y_waiwai

2020/06/06 00:01

VSCodeじゃなくて、VisualStudio入れましょうよ。 ブレークポイントで止めて、ステップ実行させれば何故そういう結果になるかぐらいはわかるでしょうに。
退会済みユーザー

退会済みユーザー

2020/06/06 00:33

過去に使用したことがあり、環境も整っていたためVSCodeを使用していました。少し調べてからVisualStudioにするかは検討させていただきます。 仰る通りで、それでどこが原因かまでは把握できたつもりだったのですがその先が力不足で進まずという感じでした。ご指摘ありがとうございます。こちらの実力不足が原因であるのにそれに答えてくださり、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問