doubly linked listの件について

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

doubly linked listの件について

#1

投稿記事 by toshi » 16年前

何度もお世話になっています。
最近C言語を勉強し始めました。
少しわからない所があるので、良ければ教えてください。
以下にソースコードを示します。
#include "stdafx.h"
#include "stdlib.h"

struct LIST
{
char *name;
struct LIST* next;
struct LIST* prev;
};
struct LIST head;

void addlist(void);
void deletelist(void);
void showlist(void);


int _tmain(int argc,_TCHAR* argv[/url])
{
char command;

head.next =&head;
head.prev = &head;

do
{
puts( "コマンドを入力して下さい" );
puts( "名前を追加:a" );
puts( "名前を削除:b" );
puts( "内容を表示:c" );
puts( "終了:q" );
scanf( "%s", &command );

switch( command )
{
case 'a':
addlist();
break;
case 'b':
deletelist();
break;
case 'c':
showlist();
break;
case 'q':
break;
default:
puts( "コマンドが正しくありません" );
break;
}

puts( "" );
fflush( stdin );

}while( command != 'q' );

return 0;
}

void addlist(void)
{

struct LIST *p, *newcell;
char *name;
name = (char*)malloc(sizeof(char));
puts( "追加する名前の値を入力して下さい" );
scanf( "%s", name );

p = head.next;
if( p != NULL )
{
while( p != &head )
{
p = p->next;
}
}

newcell = (struct LIST*)malloc( sizeof(struct LIST) );
if( newcell == NULL )
{
puts( "メモリ不足" );
return;
}

newcell->name = name;
newcell->next = p->next;
newcell->prev = p;
p->next->prev = newcell;
p->next = newcell;
}

void deletelist(void)
{
struct LIST *p;
char *name;
name = (char*)malloc(sizeof(char));

puts( "削除する名前の値を入力して下さい" );
scanf( "%s", name );

p = head.next;
if( p != NULL )
{
while(p != &head && name != p->name)
{
p = p->next;
}
}

if( p == &head )
{
puts( "指定された要素はリスト内に存在しません" );
}
else
{
p->prev->next = p->next;
p->next->prev = p->prev;
free(p);
}
}

void showlist(void)
{

struct LIST *p;

for( p=head.next; p!=&head; p=p->next )
{
printf( "%s\n", p->name );
}
}

コンパイルして試してみると、追加の方は上手くいくのですが、
削除を実行すると打った名前が消えません。
分かる方がいましたら教えていただけませんか?
どこを訂正すれば大丈夫なのかも教えていただければ、
ありがたいです。
多分内容も変な処がたくさんあるとは思いますが
よろしくお願いします。
僕はVisual Studioを使用しています。

御津凪

Re:doubly linked listの件について

#2

投稿記事 by 御津凪 » 16年前

現行ログに同名のタイトルがあるので混乱を招きやすいですよ。
あと、規約にある通り、プレタグでソースコードを囲まないと見づらいです。

質問の原因の前に、
name = (char*)malloc(sizeof(char));
puts( "追加する名前の値を入力して下さい" );
scanf( "%s", name );
これはダメです。
name には1文字分しか確保されず、メモリ破壊を引き起こします。(削除時の処理も同様)
(確保領域以外にデータを書き込んでいる)

削除できないのは、条件で、文字列の一致を確認していないためです。
name != p->name
これだと、ポインタを比較します。
リストに格納したポインタと、新しく確保した検索文字列のポインタと一致するはずがないので、
必ず不一致になります。

strcmp() 関数等で文字列の一致をチェックしてください。


あと、その他の点での指摘ですが、
p = head.next;   
 if( p != NULL )  
 {
  while( p != &head ) 
  {
   p = p->next;  
  }

 }
ここは、
p = &head;
で済むと思います。

それと、削除時に 名前を保持するために確保したメモリを解放してません。
(リストだけ解放してます)

もうひとつ。
この構造は双方向ループするので、 next, prev 共に NULL になりませんので、
(確認の意味では必要かと思いますが)チェックする必要はありません。

toshi

Re:doubly linked listの件について

#3

投稿記事 by toshi » 16年前

レスポンスありがとうございます。
言われてみれば、そのとおりだと思います。
自分でプログラムを組むと間違いだらけで・・・。
色々と回答していただきありがとうございました。

閉鎖

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