극초보의 linked list 질문입니다.

germanister의 이미지

책 정보(id, name)을 추가(add)하고 삭제(remove)하고 검색(search)하고 제거(remove)하는 초보적인 프로그램을 짜보고 있는데요....

처음으로 linked list를 사용해 보았는데...인터넷에서 소스 보고 많이 많이 참고를 해가면서 첨으로 짜본건데...이상하게...3개 이상 add하면 에러나구...list도 마지막꺼는 name이 제대로 안나오구...이상하네요

사흘동안 시간날때마다 코드를 뚫어져라 보고 있는데...무엇이 문제인지...
전혀 감이 안오네요. 사실 linked list 자체도 잘 모르는 상태라...

도움 부탁드립니다.

===============================================

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

#define TRUE ( 1 )
#define FALSE ( 0 )

#define NAME_SIZ ( 10 )

#define ADD ( 1 )
#define RENT ( 2 )
#define RETURN ( 3 )
#define DISCARD ( 4 )
#define LIST ( 5 )
#define QUIT ( 6 )

#define RENTED ( 100 )
#define RETURNED ( 200 )
#define DISCARDED ( 300 )

typedef unsigned int bool;
typedef struct record BOOK;
struct record
{
char name[ NAME_SIZ ];
int id,
status;
BOOK *prev;
BOOK *next;
};

BOOK *book_head = NULL;
BOOK *book_tail = NULL;

void display_menu();
int get_menu_number();
void add_a_book();
void get_book_name( char book_name[ NAME_SIZ ] );
void get_book_id( int *book_id );
void list_all_books();
void print_a_book( BOOK *temp );

int main()
{
int menu = 0;

do
{
menu = get_menu_number();

switch( menu )
{
case ADD: add_a_book();
break;

case RENT: // borrow_a_book();
break;

case RETURN: // return_a_book();
break;

case DISCARD: //discard_a_book();
break;

case LIST: list_all_books();
break;

default: break;
}
}
while
( menu != QUIT );

return( 0 );
}

void display_menu()
{
printf( "\n" );
printf( "--------------------\n" );
printf( " a : Add a book \n" );
printf( " e : rEnt a book \n" );
printf( " r : Return a book \n" );
printf( " d : Discard a book \n" );
printf( " l : List books \n" );
printf( "--------------------\n" );
}

int get_menu_number()
{
char str[ BUFSIZ + 1 ],
dummy = ' ',
menu = ' ';
int menu_num = 0;
bool input_success = FALSE;

memset( str, 0x0000, sizeof( str ) );

do
{
display_menu();
printf( "Select? (q:quit) " );
gets( str );
if ( sscanf( str, "%c%c", &menu, &dummy ) == 1 )
if ( menu == 'a' || menu == 'r' || menu == 'e' ||
menu == 'd' || menu == 'l' || menu == 'q'
)
input_success = TRUE;
else
printf( "\nWrong menu.\n" );
else
printf( "\nWrong input.\n" );
}
while
( !input_success );

if ( menu == 'a' )
menu_num = ADD;
if ( menu == 'e' )
menu_num = RENT;
if ( menu == 'r' )
menu_num = RETURN;
if ( menu == 'd' )
menu_num = DISCARD;
if ( menu == 'l' )
menu_num = LIST;
if ( menu == 'q' )
menu_num = QUIT;

return( menu_num );
}

void add_a_book()
{
char book_name[ NAME_SIZ ];
int book_id = 0;
BOOK *book;

if( ( book = (BOOK *)malloc( sizeof( book ) ) ) == NULL )
{
fprintf( stderr,
"\nMemory allocation error!\n" );
}
else
printf( "\n%x\n", book );

memset( book_name, 0x0000, sizeof( book_name ) );
memset( book, 0x0000, sizeof( book ) );

get_book_name( book_name );
get_book_id( &book_id );

if ( book_head == NULL )
{
printf( "This is the first book.\n" );
book_head = book;
book_tail = book;
book->prev = NULL;
book->next = NULL;
}
else
{
book->prev = book_tail;
book_tail = book;
book->next = NULL;
}

strcpy( book->name, book_name );
book->id = book_id;
book->status = RETURNED;
}

void get_book_name( char book_name[ NAME_SIZ ] )
{
printf( "\nEnter book name : " );
gets( book_name );
}

void get_book_id( int *book_id )
{
char str[ BUFSIZ + 1 ],
dummy = ' ';
bool input_success = FALSE;

do
{
printf( "\nEnter book ID : " );
gets( str );
if ( sscanf( str, "%d%c", book_id, &dummy ) == 1 )
input_success = TRUE;
}
while
( !input_success );
}

void list_all_books()
{
BOOK *temp = book_head;

while( temp )
{
print_a_book( temp );
temp = temp->next;
}
}

void print_a_book( BOOK *temp )
{
printf( "\n" );
printf( "BOOK TITLE : %s\n", temp->name );
printf( "BOOK ID : %d\n", temp->id );
printf( "BOOK STATUS : %d\n", temp->status );
}

notfound의 이미지

add 함수만 봐서 다른데도 문제가 있는지는 잘 모르겠네요

BOOK *book

if( ( book = (BOOK *)malloc( sizeof( book ) ) ) == NULL ) ...

이부분...

sizeof(book) 은 포인터로서 4바이트가 됩니다.

Sometime, it is better for you to restart than recover.

ddt의 이미지

germanister wrote:

void add_a_book()
{
<생략>
	if ( book_head == NULL )
	{
<생략>
	}
	else
	{
		book->prev = book_tail;
		book_tail = book;
		book->next = NULL;
	}
}


book_head가 null아 아닐때(else 문에서) 이전 book_tail의 next포인터가 현재 추가하려는 book을 가리켜야 합니다.
else
{
     book_tail->next = book;
     book->prev = book_tail;
     book_tail = book;
     book->next = NULL;
}
germanister의 이미지

대단히 감사합니다! 역시...kldp에는 훌륭한 분들이 많은 것 같네요!!!
sizeof( *book)으로 malloc 시키니까 원하던 실행 결과가 나오네요..^^
정말 감사합니다..ㅜ.ㅡ

그런데 한 가지만 더 질문 드리고 싶은데...

book_head가 NULL 이 아닌 경우에
book_tail.next가 지금 만들어진 book을 가르켜야 한다고 하셨는데...
이미 그 바로 뒷 부분에서 book_tail = book 이 되므로...
book_tail.next = book 이 무용지물이 되지 않을까요?

(음음...우둔한 질문일지라도...이해해주시길.....죄송합니다...(__) )

ddt의 이미지

germanister wrote:

book_head가 NULL 이 아닌 경우에
book_tail.next가 지금 만들어진 book을 가르켜야 한다고 하셨는데...
이미 그 바로 뒷 부분에서 book_tail = book 이 되므로...
book_tail.next = book 이 무용지물이 되지 않을까요?

1. book1을 추가한다.
2. head가 없어서 book1이 head,tail
3. book2를 추가한다
4. head가 있어서 book2->prev에 book1를 넣는다
5. book_tail은 book2를 가르킨다
6. book2->next는 null

book1,book2의 상황
book1->prev는 null
book1->next는 null << error
book2->prev는 book1
book2->next는 null

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.