リストの作り方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
teru

リストの作り方

#1

投稿記事 by teru » 6年前

ユーザーがint型のデータを入力してそれが0だったらデータの入力は終了でリストの最初から表示し、2番目と三番目のリストを入れ替えるコードが書きたいです。

が、最後のprintfでリストが表示できないので表示する方法をおしえてください

コード:

#include<stdio.h>
#include<stdlib.h>

struct ListNode {
	struct ListNode *next;
	int data;
};

int main(void) {

	int i = 0 , temp, count=0;
	struct ListNode *node, *head = NULL;


for(i=0;;i++)
	 {
		

		printf("データを入力してください\n");
		scanf_s("%d", &temp);

		if (temp == 0) {

			break;
		}

		else {

			node = (struct ListNode*)malloc(sizeof(struct ListNode));

			if (i == 0) {

				head = node;
				node->data = temp;
				node->next = NULL;


			}

			else {

				node->next = (struct ListNode*)malloc(sizeof(struct ListNode));
				
				node = node->next;
				node->data = temp;
			     

			}
		
		}
		count++;

	}

 

if (count < 5) {

	printf("入力数が足りません");

	}

else {
	   



	for (node = head; node != NULL; node = node->next) {

		printf("%d\n", node->data);
	}

}

	return 0;

}

かずま

Re: リストの作り方

#2

投稿記事 by かずま » 6年前

teru さんが書きました:
6年前
が、最後のprintfでリストが表示できないので表示する方法をおしえてください
表示は間違っていません。

間違っているのは、2番目以降の入力で、if (i == 0) { の前と、
else の後の 2回 malloc を実行していることです。
if (i == 0) { の前の malloc の行を if の中に入れましょう。

i と count は、常に同じ値を持つので、どちらか一つでいいでしょう。
インデントをちゃんとしましょう。行頭に for や if や else は変です。
無駄な空行も控えましょう。

かずま

Re: リストの作り方

#3

投稿記事 by かずま » 6年前

かずま さんが書きました:
6年前
if (i == 0) { の前の malloc の行を if の中に入れましょう。
実は、この修正だけでは不完全です。

else の部分の malloc で確保した ListNode の next を
NULL で初期化していません。

gcc でコンパイルしたり、Visual Studio のリリースビルドした場合、
next が NULL であることが多いので、問題が発覚しにくいようです。
デバッグビルドだと未初期化の領域を 0xcd で埋めるので、
例外が発生するでしょう。

質問するときは、フォーラムルールにあるように、
コンパイル環境(OS やコンパイラ)を明記しましょう。

かずま

Re: リストの作り方

#4

投稿記事 by かずま » 6年前

データを読み込んだ後、それが最初のデータか、2番目以降のデータかで
場合分けをしているため、malloc によるノードの確保が 2個所に必要です。

[1] データを読み込む
[2] ノードを作る
[3] リストにつなぐ

このようにすると、malloc は [2] で行い、場合分けは [3] だけで済みます。

コード:

#include <stdio.h>   // scanf, puts, printf
#include <stdlib.h>  // malloc, free

struct ListNode {
	struct ListNode *next;
	int data;
};

int main(void)
{
	int count, temp;
	struct ListNode *head = NULL, *tail = NULL, *node;

	for (count = 0; ; count++) {
		puts("データを入力してください");
		scanf("%d", &temp);
		if (temp == 0) break;

		node = (struct ListNode *)malloc(sizeof *node);
		node->next = NULL;
		node->data = temp;

		if (head == NULL) tail = head = node;
		else tail = tail->next = node;
	}
	if (count < 5)
		puts("入力数が足りません");
	else
		for (node = head; node != NULL; node = node->next)
			printf("%d\n", node->data);

	// 2番目と 3番目をノードを入れ替えて表示する処理をここに書く

	while (head != NULL)
		node = head, head = node->next, free(node);
	return 0;
}
プログラムが終了してしまえば、メモリはすべて解放されるので
free は不要なのですが、malloc の実行回数と同数の free をプログラム
中で行うのが行儀のよいプログラムとなるので、追加しました。

teru

Re: リストの作り方

#5

投稿記事 by teru » 6年前

できました!
ありがとうございます

かずま

Re: リストの作り方

#6

投稿記事 by かずま » 6年前

teru さんが書きました:
6年前
できました!
できたのなら、フォーラム(掲示板)ルールにありますように、
できたプログラムの提示を希望します。

コード:

d. 義務行為

  "C言語何でも質問掲示板"でのみ適用される事項
  ・トピックを立て、解決した場合は「解決しました」とだけ書かず、どうやって
    解決したか他の人に分かるように書いてからトピックを終了して下さい。
#4 のプログラムには不具合があります。
2番目と 3番目のノードを入れ替えて表示する処理は、
次のように else の部分に書かないといけないでしょう。

コード:

	if (count < 5)
		puts("入力数が足りません");
	else {
		for (node = head; node != NULL; node = node->next)
			printf("%d\n", node->data);

	    // 2番目と 3番目のノードを入れ替えて表示する処理をここに書く
	}
また行儀のよいプログラムにするなら、malloc が失敗した場合の処理も
書いたほうがいいでしょう。

コード:

		node = (struct ListNode *)malloc(sizeof *node);
		if (node == NULL) {
		    puts("out of memory");
			return 1;  // main の終了
		}

teru

Re: リストの作り方

#7

投稿記事 by teru » 6年前

少し変更し、このコードをかきました。
ですが、これは表示時に変えているだけとのことです。

どこを、変更すれば良いですか??

コード:

#include<stdio.h>
#include<stdlib.h>

   typedef struct tagListNode {
     int data;
     struct tagListNode *next;
   }ListNode;

int main(void) {
ListNode *newnode, *firstnode, *lastnode, *thisnode, *t1, *t2, *t3;
int buf;
firstnode = lastnode = NULL;
do {
//データの入力
printf("整数");
scanf("%d", &buf);
//メモリを開放する
newnode = (ListNode *)malloc(sizeof(ListNode));
newnode->data = buf;
newnode->next = NULL;
if (lastnode != NULL) {
lastnode->next = newnode;
lastnode = newnode;
}
else {
firstnode = lastnode = newnode;
}
} while (buf != 0);
//データを順に出力
printf("順番にデータを出力\n");
for (thisnode = firstnode; thisnode != NULL; thisnode = thisnode->next) {
printf("%d\n", thisnode->data);
}
//2番目と3番目のノードを入れ替える
thisnode = firstnode;
t1 = thisnode->next;
thisnode = thisnode->next;
t2 = thisnode->next;
thisnode = thisnode->next;
t3 = thisnode->next;
thisnode = thisnode->next;
//データを出力
printf("2番目と3番目のノードを入れ替える\n");
thisnode = firstnode;
printf("%d\n", thisnode->data);
thisnode = t2;
printf("%d\n", thisnode->data);
thisnode = t1;
printf("%d\n", thisnode->data);
thisnode = t3;
for (thisnode = t3; thisnode != NULL; thisnode = thisnode->next) {
printf("%d\n", thisnode->data);
}
free(newnode);
return 0;
}


かずま

Re: リストの作り方

#8

投稿記事 by かずま » 6年前

なぜ、左詰めで書くんですか?
ループの始まりと終わり、if文の始まりと終わりなどが分かりにくくて
プログラムが読めないと思いませんか?

データ終了の 0 もデータとして加えるんですか?

free の実行回数は、malloc の実行回数と同じにしましょう。

コード:

#include <stdio.h>    // printf, puts
#include <stdlib.h>   // malloc, free

typedef struct tagListNode {
	int data;
	struct tagListNode *next;
} ListNode;

int main(void)
{
	ListNode *newnode, *firstnode, *lastnode, *thisnode, *t2, *t3;
	int buf;
	firstnode = lastnode = NULL;
	do {
//データの入力
		printf("整数 ");
		scanf("%d", &buf);
//メモリを確保する
		newnode = (ListNode *) malloc(sizeof(ListNode));
		if (newnode == NULL) { puts("out of memory"); return 1; }
		newnode->data = buf;
		newnode->next = NULL;
		if (lastnode != NULL) {
			lastnode->next = newnode;
			lastnode = newnode;
		}
		else {
			firstnode = lastnode = newnode;
		}
	} while (buf != 0);
//データを順に出力
	printf("順番にデータを出力\n");
	for (thisnode = firstnode; thisnode != NULL; thisnode = thisnode->next) {
		printf("%d\n", thisnode->data);
	}
//2番目と3番目のノードを入れ替える
	t2 = firstnode->next;  // 値 0 もデータなので、firstnode は NULLではない
	if (t2 == NULL) { puts("only 1 data"); return 1; }
	t3 = t2->next;
	if (t3 == NULL) { puts("only 2 data"); return 1; }

	printf("2番目と3番目のノードを入れ替える\n");
	t2->next = t3->next;  // 4番目を 2番目に繋ぐ
	t3->next = t2;        // 2番目を 3番目に繋ぐ
	firstnode->next = t3; // 3番目を 1番目に繋ぐ

	for (thisnode = firstnode; thisnode != NULL; thisnode = thisnode->next) {
		printf("%d\n", thisnode->data);
	}
	while (firstnode != NULL) {
		thisnode = firstnode;
		firstnode = thisnode->next;
		free(thisnode);  // メモリを解放する
	}
	return 0;
}
どこを変更したか説明してください。

返信

“C言語何でも質問掲示板” へ戻る