2015-08-31 22 views
3

我正在使用3個文件進行分類:speller.c是主文件,dictionary.c包含函數&全局根trie指針,dictionary.h聲明瞭字典的函數。 在dictionary.c中的函數加載完成後,全局根指針值丟失時出現問題。全局指針值丟失。 2 c文件

speller.c

int main(int argc, char* argv[]) 
{ 
    // load dictionary 
    char* dictionary = TMPDICT; 

    bool loaded = load(dictionary); 

    // abort if dictionary not loaded 
    if (!loaded) 
    { 
     printf("Could not load %s.\n", dictionary); 
     return 1; 
    } 

    //next I need to call check function, but root value is missing here 

} 

dictionary.c

typedef struct TrieNode 
    { 
     struct TrieNode **children; 
     bool is_word; 
    } TrieNode; 
struct TrieNode * root; 


struct TrieNode *create_trienode(char c, struct TrieNode *parent); 
bool load(const char* dictionary) 
    { 

     FILE * file = fopen(dictionary, "r"); 
     if (file == NULL) 
     { 
      printf("trie: No such file(dictionary)\n"); 
      return 1; 
     } 

     struct TrieNode *root = create_trienode(' ', NULL); 
     struct TrieNode *ptr = root; 
     int character; 
     int converted; 
     int buffer; 

     //This handles if file does not end with a newline 
     character = fgetc(file); 
     buffer = fgetc(file); 

     while(character != EOF) 
     { 
      character = tolower(character); 
      if (character == 10) // if newline, start new word read 
      { 

      } 
      else 
      if(isalpha(character)) 
      { 
       converted = character - 'a'; 
       if(ptr->children[converted] == NULL) 
       { 
        ptr->children[converted] = create_trienode(character, ptr); 
       } 
      ptr = ptr->children[converted]; 
      } 


     if (character == SLASHNUM) //if backslash 
     { 
      if(ptr->children[SLASH_TMP] == NULL) 
      { 
       ptr->children[SLASH_TMP] = create_trienode(character, ptr); 
      } 
      ptr = ptr->children[SLASH_TMP]; 
     } 

     if(ptr != root && (!(character == SLASHNUM || isalpha(character)) || buffer == EOF)) 
     { 
      ptr->is_word = true; 
      ptr = root; 
      word_count++; 
     } 

      character = buffer; 
      buffer = fgetc(file); 
     } 

     return true; 
    } 


struct TrieNode *create_trienode(char c, struct TrieNode *parent) 
{ 
    struct TrieNode *node = malloc(sizeof(struct TrieNode)); 
    node->children = malloc(ALPHABET_SIZE * sizeof(struct TrieNode*)); 
    node->is_word=false; 

    for (int i = 0; i < ALPHABET_SIZE; i++) 
    { 
     node->children[i] = NULL; 
    } 

    return node; 
} 

GDB

Breakpoint 1, load (dictionary=0x80489c4 "tmpDict") at dictionary.c:100 
100  character = fgetc(file); 
(gdb) info locals 
file = 0x804b008 
root = 0x804b170 
ptr = 0x804b170 
character = 1267019363 
converted = 262929407 
buffer = 1266804984 
(gdb) c 
Continuing. 

Breakpoint 2, main (argc=1, argv=0xbffff0d4) at speller.c:40 
$1 = (struct TrieNode *) 0x0 
(gdb) 

我怎樣才能讓根speller.c可見?另外在任務說,我不能改變speller.c

回答

1

你的代碼定義root兩次,以load()定義本地陰影全局定義。

此行

struct TrieNode *root = create_trienode(' ', NULL); 

限定root本地和的create_trienode()結果賦給的root這個本地定義。

從這個局部定義root開始,全局定義的root被本地鏡像遮蔽,不能再被訪問。

要解決這一變化是:

struct TrieNode *root = create_trienode(' ', NULL); 
    struct TrieNode *ptr = root; 

struct TrieNode *ptr= create_trienode(' ', NULL); 
    root = ptr; 
+0

好吧,那是怎麼回事? – alk

+1

這個答案__is__正確。爲什麼是downvote? (從我身邊+1) –

5

一般情況下,你需要聲明rootexterndictionary.h文件,包括在speller.c這個頭文件。

這樣,root將提供給翻譯單位spleller.c。接下來,您可以使用內部的root speller.c,就像任何其他本地變量(在該文件本身中定義)一樣。


問題這裏 [作爲正確的Mr. alk在下面的評論指出]是load()函數內部實際陰影的當地root變量

struct TrieNode *root = create_trienode(' ', NULL); 

定義全球root

struct TrieNode * root;` 

因此,全球root永遠不會更新。

相關,從C11標準,章§6.2.1(重點礦山

[...]如果標識符指定在相同的名稱 空間兩個不同的實體,該範圍可能會重疊。如果是這樣,一個實體(內部範圍)的範圍將嚴格在其他實體(外部範圍)的範圍之前結束 。 在內部範圍內, 標識符指定在內部範圍內聲明的實體;在外部 範圍內聲明的實體在內部範圍內隱藏(並且不可見)。

+0

最後1+引用標準。 – alk