dポイントプレゼントキャンペーン実施中!

最近C言語でリスト構造を勉強したので自己流でリスト構造のプログラムを作成したのですが正常に作動しません。どなたか解決法を教えてください。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*データ*/
typedef struct {
int num; //学籍番号下三桁
char name[16]; //氏名
}data_t;

/*ノード*/
typedef struct node {
data_t data; //データ
struct node *nextnode; //後ろのノードへのポインタ
}node_t;

/*関数プロトタイプ宣言*/
node_t *make_node(data_t, node_t *);
void add_data(node_t *);
void remove_data(node_t *);
void search_data(node_t *);
void show_data(node_t *);
void release(node_t *);

int main(void)
{
int menu;
node_t *node=NULL;

do {
puts("");
puts("***メニューの選択***");
puts(" 1.データの追加");
puts(" 2.データの削除");
puts(" 3.データの検索");
puts(" 4.データの表示");
puts(" 5.終了");

printf("メニューの選択:"); scanf("%d", &menu);
puts("");

switch (menu)
{
case 1: add_data(node); break;
case 2: remove_data(node); break;
case 3: search_data(node); break;
case 4: show_data(node); break;
case 5: puts("プログラムを終了"); break;
default:puts("番号を再入力"); break;
}
} while (menu != 5);

release(node);
system("pause");
return 0;
}

/*新規ノードの作成*/
node_t *make_node(data_t data, node_t *nextnode)
{
node_t *p;

p = malloc(sizeof(node_t));
if (p == NULL) {
puts("領域確保に失敗");
return NULL;
}
else {
p->data = data;
p->nextnode = nextnode;
return p;
}
}

/*データの追加*/
void add_data(node_t *node)
{
data_t data;
node_t *p=node;

puts("***追加するデータの入力***");
printf("学籍番号の下二桁の番号:"); scanf("%d", &data.num);
printf("氏名:"); scanf("%s", data.name);

while (p->nextnode != NULL) {
p = p->nextnode;
}
p = make_node(data, NULL);
}

/*データの表示*/
void show_data(node_t *node)
{
node_t *p=node;

if (p ==NULL) {
puts("データがありません。データを追加してください。");
return;
}
while (p!=NULL){
printf("番号%*s氏名\n",6,"");
printf("%2d %10s\n", (p->data).num, (p->data).name);
p = p->nextnode;
}
}

/*データの削除*/
void remove_data(node_t *node)
{
int num;
node_t *pre;
if(node==NULL)
puts("データは見つかりませんでした。"); return;
puts("***データの削除***");
printf("番号の入力:"); scanf("%d", &num);

while (node->nextnode != NULL) {
if ((node->data).num == num) {
pre = node->nextnode;
free(node);
return;
}
pre = node;
node = node->nextnode;
}
puts("データは見つかりませんでした。");
}

/*データの検索*/
void search_data(node_t *node)
{
int num;
node_t *p=node;

puts("***データの検索***");
printf("番号の入力:"); scanf("%d", &num);

if (node == NULL)
puts("データは見つかりませんでした"); return;
while (p->nextnode != NULL) {
if ((p->data).num == num) {
puts("---データを発見---");
printf("氏名:%s\n", (p->data).name);
return;
}
p = p->nextnode;
}
puts("データは見つかりませんでした");
}

/*データの後処理*/
void release(node_t *node)
{
node_t *p;

if (node = NULL) return;
while (node->nextnode != NULL) {
p = node;
node = node->nextnode;
free(p);
}
}

A 回答 (5件)

とりあえず #1 に 2点ほど突っ込んでおく.


・「make_node()関数でmallocを何度も呼び出すのはパフォーマンス的に良いとは言えません」っていわれてもしょうがないっちゃしょうがないんだよな.
・「add_data()関数でwhileループをした後pはNULLを指しますので、NULLポインタへの代入でエラーになります」は多分気のせいだと思う. 「while ループのあと」では「NULL ポインタ経由のアクセス」はしてないからね. まあ, だからといって期待した動作はしないはずだけど.

あと remove_data でリスト構造をもろにぶち壊してくれる.

ついでにいうとノードの構造体は
typedef struct node_t {
data_t data; //データ
struct node_t *nextnode; //後ろのノードへのポインタ
}node_t;
と書いてもいい (他の方法もあり) んだけど, あんまりやる人はいない気がする.
    • good
    • 0

No1の者です



No4の方の言う通りadd_data()関数の指摘した部分は勘違いだったようです。
また、リスト構造を勉強されているということで、パフォーマンスや、データ構造の話をするのはすこし場違いでした。お騒がせしました。
    • good
    • 0

add_data()は指摘されているとおり、ヌルポアクセスで吹っ飛びます。


NULL->nextnodeの参照なので。

>if(node==NULL)
>puts("データは見つかりませんでした。"); return;

nodeの内容に関わらず、ここから先には進みません。
必ずreturnします。
    • good
    • 0

No1の者です。

習性があります。

メモリアクセスエラーではなくif ( node == NULL )で早期リターンしているのでノードの操作関数が失敗します。
    • good
    • 0

まず、どこがどう動作しないのかを明確にしてください。

正確な回答ができません。
読んでいて気付いたことを挙げていきます。

main()関数内でnodeの領域が確保されていないので、ノードの操作すべてがメモリアクセスエラーで失敗します。

add_data()関数でwhileループをした後pはNULLを指しますので、NULLポインタへの代入でエラーになります。

make_node()関数でmallocを何度も呼び出すのはパフォーマンス的に良いとは言えません。学籍番号と氏名というデータであれば、配列を使ったほうが適切です。

remove_data()関数以降は見ていませんが、main()が動けばデバックできると思います。頑張ってください。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!