ページ 1 / 1
リストの作り方
Posted: 2018年10月17日(水) 23:36
by teru
ユーザーが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: リストの作り方
Posted: 2018年10月18日(木) 11:04
by かずま
teru さんが書きました: ↑6年前
が、最後のprintfでリストが表示できないので表示する方法をおしえてください
表示は間違っていません。
間違っているのは、2番目以降の入力で、if (i == 0) { の前と、
else の後の 2回 malloc を実行していることです。
if (i == 0) { の前の malloc の行を if の中に入れましょう。
i と count は、常に同じ値を持つので、どちらか一つでいいでしょう。
インデントをちゃんとしましょう。行頭に for や if や else は変です。
無駄な空行も控えましょう。
Re: リストの作り方
Posted: 2018年10月18日(木) 21:11
by かずま
かずま さんが書きました: ↑6年前
if (i == 0) { の前の malloc の行を if の中に入れましょう。
実は、この修正だけでは不完全です。
else の部分の malloc で確保した ListNode の next を
NULL で初期化していません。
gcc でコンパイルしたり、Visual Studio のリリースビルドした場合、
next が NULL であることが多いので、問題が発覚しにくいようです。
デバッグビルドだと未初期化の領域を 0xcd で埋めるので、
例外が発生するでしょう。
質問するときは、フォーラムルールにあるように、
コンパイル環境(OS やコンパイラ)を明記しましょう。
Re: リストの作り方
Posted: 2018年10月19日(金) 16:37
by かずま
データを読み込んだ後、それが最初のデータか、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 をプログラム
中で行うのが行儀のよいプログラムとなるので、追加しました。
Re: リストの作り方
Posted: 2018年10月24日(水) 02:32
by teru
できました!
ありがとうございます
Re: リストの作り方
Posted: 2018年10月24日(水) 12:40
by かずま
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 の終了
}
Re: リストの作り方
Posted: 2018年10月31日(水) 12:28
by teru
少し変更し、このコードをかきました。
ですが、これは表示時に変えているだけとのことです。
どこを、変更すれば良いですか??
コード:
#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: リストの作り方
Posted: 2018年10月31日(水) 13:59
by かずま
なぜ、左詰めで書くんですか?
ループの始まりと終わり、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;
}
どこを変更したか説明してください。