2013-03-24 29 views
0

我寫了下面的代碼,它正確地打印根值,但不是ret值。這裏可能會打印一個內存地址(1707388)。我相信ret現在可以修改,結果將在主要中看到。任何幫助表示讚賞。指針和值

#include <stdlib.h> 

struct node{ 
int value; 
    int order; 
    struct node *left; 
    struct node *right; 
}; 

typedef struct node node_t; 

node_t array[10]; 

void createTree(node_t *p, int order){ 
    p->value = rand()%10; 
    p->order = order; 
    printf("%i", p->value); 
    printf(" "); 
    printf("%i\n", p->order); 
    if (!order){ 
     p->left = NULL; 
     p->right = NULL; 
     return; 
    } 
    order--; 
    createTree(&p->left, order); 
    createTree(&p->right, order); 
} 

void traverse(node_t *current, node_t *ret, int size){ 
    printf("%i\n", current->value); 
    if (current->value > size){ 
     ret = current; 
     traverse(&current->left, &ret, size); 
     traverse(&current->right, &ret, size); 
    } 
    return; 
} 

int main(void){ 
    node_t *root = &array[0]; 
    node_t *ret; 
    srand(time(NULL)); 
    createTree(root, 4); 
    int i = 3; 
    printf("%s", "root-value: "); 
    printf("%i\n", root->value); 
    traverse(root, ret, i); 
    printf("%s", "root-value: "); 
    printf("%i\n", root->value); 
    printf("%i\n", ret->value); 
    return 1; 
} 
+3

您不僅需要學習如何編寫代碼,還需要了解如何進行調試。 – Andrey 2013-03-24 15:37:10

+0

Andrey。很顯然你是對的,但爲什麼要說呢? – stian 2013-03-24 16:14:38

回答

3

你是按值傳遞ret

void traverse(node_t *current, node_t *ret, int size){ 

當函數改變ret,所做的更改不會傳播給調用者。

這意味着retmain()保持未初始化,您的代碼的行爲是未定義的。

爲了解決這個問題,使traverse要麼返回ret,或者把它作爲node_t**

4

此:

void createTree(node_t *p, int order) 

應該

void createTree(node_t **p, int order) 

否則要修改,而不是功能外一個本地node_t指針。你的樹也沒有正確地建造。

+0

並分配給函數中的'* ret'。 – 2014-03-03 01:59:41

2

代碼很少出現問題。

首先,您沒有正確地爲節點分配內存。在你的代碼中,你傳遞了錯誤的指針類型,而且還有指向未初始化區域的指針。

這裏,怎麼可以有不同的使用:

node_t *createTree(int order) 
{ 
    node_t *result = malloc(sizeof(*result)); 
    result->value = rand() % 10; 
    result->order = order; 
    if (order) 
    { 
     result->left = createTree(order - 1); 
     result->right = createTree(order - 1); 
    } 
    else 
    { 
     result->left = result->right = 0; 
    } 
    return result; 
} 

然後,你遍歷功能需要一些塊限制agains搜索失敗:

node_t *traverse(node_t *current, int size) 
{ 
    node_t *ret = NULL; 

    if (current->value > size) 
    { 
     // assuming current node fit - stops the search 
     ret = current; 
    } 

    if (!ret && current->left) 
    { 
     // try left node 
     ret = traverse(current->left, size); 
    } 
    if (!ret && current->right) 
    { 
     // try right node 
     ret = traverse(current->right, size); 
    } 
    return ret; 
} 

如果你需要(通常是你做的) ,這裏是一個destroyTree

void destroyTree(node_t *node) 
{ 
    if (!node) return; // we treat NULL as a valid pointer for simplicity 

    destroyTree(node->left); 
    destroyTree(node->right); 
    free(node); 
} 

這裏是一個使用示例:

node_t *root, *found; 

root = createTree(4); 
found = traverse(root, 3); 
if (found) 
{ 
    printf("Found!"); 
} 
destroyTree(root); 
+0

謝謝你valeri :)我相信我不需要使用malloc,因爲我靜態地爲我的數組在頂部留出內存,並將第一個索引的地址分配給我的指針。 – stian 2013-03-24 17:47:11

+0

@dexter沒有malloc或其等價物你的代碼將無法工作:)樹狀結構需要某種內存管理。分配靜態數組不夠。 – 2013-03-24 18:50:26

+0

瓦萊麗。這是爲什麼?我的意思是,在陣列中應該有足夠的內存(只要我不走出陣列)。 – stian 2013-03-24 18:59:36

1

traverse(node_t *current, node_t *ret, int size)ret是一個堆棧變量。換句話說,您通過值傳遞指針,而不是通過引用傳遞它

你有什麼,此刻做的是基本相同:

int f(int i) { 
    ... 
    i = <any value>; 
    ... 
} 

在這種情況下,你只修改一個值的副本。

在你的程序中,你也在修改指針的副本。在函數之外,指針保持不變。

如果要修改它,你需要一個指針傳遞給它:

​​

同爲createTree()