2012-05-05 2 views
0

질문이 해결되었습니다.
링크드 목록 코드에 어떤 문제가 있습니까?

내가 뭘 잘못하고 있는지 설명하는 데 도움이되기를 바랍니다.

미리 감사드립니다.

코드 :
데이터를 입력하십시오 N1 :
데이터를 입력하십시오 :

요소의 수를 입력하십시오 : 여기

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

typedef struct node { 
    char *data; 
    struct node * previous; 
    struct node * next; 
} node, *nodePTR; 

/* Insert into list */ 
void insert(char * buf, nodePTR tail) { 
    nodePTR myNode; 
    myNode = (node *)malloc(sizeof(node)); 

    myNode->data = malloc(sizeof(char) * 10); 
    strcpy(myNode->data,buf); 
    myNode->next = NULL; 
    myNode->previous = tail; 
    tail->next = myNode; 
    //tail = tail->next; 
} 

void printlist(nodePTR head, int numElements) { 
    nodePTR tmpNode; 
    tmpNode = head; 

    printf("\n\n"); 

    while(tmpNode!=NULL) { 
     printf("Node data: %s\n", tmpNode->data); 
     tmpNode = tmpNode->next; 
    } 
} 

int main(void) { 
    /* Variables */ 
    int numElements; 
    int i; 
    char buf[10]; 

    nodePTR head, tail; 

    tail = (node *)malloc(sizeof(node)); 
    head = (node *)malloc(sizeof(node)); 

    tail->data = "EMPTY\0"; 
    tail->next = NULL; 
    tail->previous = NULL; 

    head = tail; 

    printf("Please enter the number of elements:\n"); 
    scanf("%d", &numElements); 

    /* Build the list */ 
    for(i = 0; i < numElements; i++) { 
     printf("Please enter the data:"); 
     scanf("%s", buf); 
     insert(buf, tail); 
     tail = tail->next; 
    } 

    printlist(head, numElements); 

    return 0; 
} 


내 출력 : n2
데이터를 입력하십시오 : n3

노드 데이터 : EMPTY
노드 데이터 :

+0

* 관련된 * 코드를 여기에 (링크가 아닌) 게시하고 어떤 디버깅 단계를 수행했는지, 어디서 멈췄는지 설명하십시오. –

+1

여기에 코드를 직접 게시하는 것이 좋습니다. 디버거를 통해 프로그램을 실행 해 보시기 바랍니다. 리눅스 시스템을 사용하고 있다면 GDB에 대해 익숙해 지길 권합니다 –

답변

0

N3 나는 보통 요소가 삽입 될 때까지 머리와 꼬리 NULL을 남겨보다는 사방에 빈 노드를 감지하려고 시도합니다. 내가 사용하는 매우 간단한 연결 목록의 예제가 포함되어 있습니다. 이 버전은 마이크로 컨트롤러에 대한 유의 그래서 malloc에 ​​/ (때로는 미리 할당 된 노드 풀에서) 목록 기능을 외부 메모리 무료 : 당신은 객체로 취급 할 때

는 코드에 특정
struct ListNodeStruct 
{ 
    struct ListNodeStruct* Next; 
    int Value; 
}; 
typedef struct ListNodeStruct ListNode; 

struct ListStruct 
{ 
    ListNode* Head; 
    ListNode* Tail; 
    int Count; 
}; 
typedef struct ListStruct List; 

List CreateList() 
//creates a new List 
{ 
    List R; 
    R.Head = NULL; 
    R.Tail = NULL; 
    R.Count = 0; 
    return(R); 
} 

void ListInsertFirst(List* L, ListNode* V) 
//insert the object at the start of the list 
{ 
    V->Next = L->Head; 
    L->Head = V; 
    if (L->Count == 0) 
    L->Tail = V; 
    L->Count ++; 
} 

void ListInsertLast(List* L, ListNode* V) 
//insert the object at the end of the list 
{ 
    V->Next = NULL; 
    if (L->Tail) 
    L->Tail->Next = V; 
    else 
    L->Head = V; 
    L->Tail = V; 
    L->Count++; 
} 

ListNode* ListRemoveFirst(List* L) 
//remove the first object in the list (no memory is freed) 
{ 
    ListNode* R = L->Head; 

    if (L->Head == NULL) 
    return(R); 

    L->Head = L->Head->Next; 
    L->Count--; 
    if (L->Count == 0) 
    L->Tail = L->Head; 
    return(R); 
} 

, 몇 가지 문제를 피할 수 있습니다 인 기능을 제외한 블랙 박스는 내부에서을 볼 수 있습니다. 특히 주 기능의 시작과 줄 69는 목록 구성원을 직접 조작합니다. 나는 보통 객체를 초기화하는 함수를 가지고있다. 왜냐하면리스트를 사용할 때 여러 곳에서 다시해야하기 때문이다.

줄 54에서 문자열 리터럴에 대한 포인터를 구조에 푸시합니다. 이 포인터는 현재 스택 프레임에서만 유효합니다. 즉, 함수가이 포인터를 종료 할 때 더 이상 "EMPTY \ 0"을 포함하지 않습니다. malloc을 호출하여 거기에 저장해야하며 자유롭게하는 것을 잊지 마십시오. 또한 C는 자동으로 문자열 리터럴을 널 종료하므로 끝에 \ 0이 필요하지 않습니다.

마지막으로 인쇄 기능에서 제대로 반복되지 않을 수있는 이유는 헤드가 아닌 꼬리 부분에서 인쇄 반복기를 시작하기 때문입니다.

+0

내 게시물을 편집하여 버전에 관한 약간의 노트를 포함 시켰습니다. –

+0

나는 다음과 같은 것을 의미했다. char [] EmptyStr = "EMPTY"; tail-> data = (char *) malloc (strlen (EmptyStr) + 1); strcpy (tail-> data, EmptyStr); –

0

자, 문제는 모든 노드가 동일한 버퍼를 가리키고 있다고 생각합니다. 매번 버퍼를 복사해야합니다.

myNode->data = buf; 

데이터를 버퍼의 주소로 지정합니다. 그런 다음 나중에 버퍼를 업데이트하면 주소는 그대로 유지되지만 내용은 변경됩니다. 그래서 모든 것이 본질적으로 같은 문자열을 가리키고 있습니다. 버퍼의 내용을 새 배열로 복사하고 그 데이터를 가리켜 야합니다.

head = head->next; 

삽입이 돌보는해야합니다 당신이 추가 노드를 반복하는 경우

또한이 라인은 의심 보인다.

여기 코드가 작동 rejiggered있다 : I는 입력을 제거있어

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

typedef struct node { 
    char *data; 
    struct node * previous; 
    struct node * next; 
} node, *nodePTR; 

/* Insert into list */ 
void insert(char * buf, nodePTR head) { 
    nodePTR myNode; 
    myNode = (node *)malloc(sizeof(node)); 

    myNode->data = malloc(sizeof(char) * 10); 
    strcpy(myNode->data,buf); 
    myNode->next = head->next; 
    myNode->previous = head; 
    head->next = myNode; 
} 

void printlist(nodePTR head, int numElements) { 
    nodePTR tmpNode; 
    tmpNode = head; 

    printf("\n\n"); 

    while(tmpNode!=NULL) { 
     printf("Node data: %s\n", tmpNode->data); 
     tmpNode = tmpNode->next; 
    } 
} 

int main(void) { 
    /* Variables */ 
    int numElements; 
    int i; 
    char buf[10]; 

    nodePTR head, tail; 

    tail = (node *)malloc(sizeof(node)); 
    head = (node *)malloc(sizeof(node)); 

    tail->data = "EMPTY\0"; 
    tail->next = NULL; 
    tail->previous = NULL; 

    head = tail; 

    printf("Please enter the number of elements:\n"); 
    //scanf("%d", &numElements); 
    numElements=3; 

    /* Build the list */ 
    for(i = 0; i < numElements; i++) { 
     printf("Please enter the data:"); 
     buf[0] = 60 + i; 
     buf[1] = 0; 
     insert(buf, head); 
    } 

    printlist(head, numElements); 

    return 0; 
} 

그래서 나는 그것이 codepad 작업을 만들 수있는 프롬프트하지만 아이디어는 동일합니다. 또한 우연히 꼬리를 추적 할 수 없게 된 것 같습니다. TAIL

HEAD - - 1 - TAIL

HEAD - 2 - 1 - TAIL

...

HEAD : 그것은 시작 갈 것입니다 그래서이 바로 머리 뒤에 물건을 삽입합니다

여기서 2nd는 삽입 한 두 번째 요소입니다. 당신의

char * tmpBuf = buf; 

문제에 관해서는

는 tmpBuf은 버피와 같은 주소로 여전히 포인트 스택에와 있다는 것입니다. malloc을 사용하여 새 버퍼를 할당해야했습니다 (또는 주석에 메타포마다 새 집을 만들었습니다).

이 줄

myNode = (node *)malloc(sizeof(node)); 

사용하면 노드 구조체에 정의 된 것들에 대한 충분한 공간을 작성합니다. 어떤 경우에는 포인터이 다음 노드와 이전 노드의 문자 배열에 해당합니다. 그래서 여러분이 가질 수있는 것은 문자 배열의 주소입니다. 노드에 실제로 char 배열을위한 공간이 없습니다.

myNode->data = malloc(sizeof(char) * 10); 

이 malloc에 ​​실제로 10 개 문자의 배열을위한 공간을 만드는하고 노드 데이터 필드에 배열의 주소를 저장합니다. 이 두 번째 malloc이 없으면 실제 배열을위한 공간을 만들 수 없습니다. 데이터 구조를 처음 배울 때 데이터 유형으로 int를 사용하는 것이 좋습니다. 실제 데이터 구조의 작동에서 당신을 혼란시키지 않는 함정이 적습니다.

+0

내가 버퍼에 대해 말하고있는 것을 보았습니까? buf는 10 글자가 살 수있는 집 주소와 같습니다. 그래서 myNode-> data = buf; 집의 주소를 데이터에 저장합니다. 그리고 scanf ("% s", buf)를 호출하면; 당신은 집에 사는 사람을 변화시키고 있습니다. 따라서 모든 노드에는 여전히 동일한 집 주소가 있습니다. 당신이 거기에 살고있는 사람들을보기 위해 인쇄 목록에있는 집을 방문 할 때, 가장 최근의 거주자 만 찾을 것입니다. 대신 새로운 집에 삽입물과 포인트 데이터를 호출 할 때마다 새 집을 만들어야합니다. – Justin

+0

글쎄, 당신은 머리와 꼬리로 일이 이상해 지네. 당신은 둘 모두를위한 malloc 메모리를 사용하고, 그것들을 동일하게 할당하십시오. 나는 너 자신에게 조금 더 많은 노력을하고 아직 문제가 있다면 새로운 질문을 할 것이다. 다른 몇 가지 사항은 이러한 댓글 중 일부를 삭제하는 것이 좋습니다. 토론이 약간 어려워졌습니다. 그리고 앞으로는 코드를 너무 많이 수정하지 않도록하십시오.지금 내가 대답 한 질문은 그것이 현재 서있는 것처럼 정말로 문제가되지 않는다. 여기에서 좀 더 성공적으로 성공할 수 있도록 도와주는 몇 가지 팁이 있습니다. :) 제 공식적인 대답으로 당신에게 malloc 질문에 대답하려고했습니다. – Justin

관련 문제