2014-10-04 35 views
1

編輯:所以它看起來像問題是,getNum應該轉換爲浮動字符串實際上不是包含字符串的所有令牌的字符。相反,它包含緊跟在標記之後的字符,通常是NaN,所以atof將它轉換爲0.我不知道爲什麼會發生這種行爲。當我嘗試從字符的字符串,得到一個數字,該函數總是返回零

我工作的一臺掃描儀+解析器來計算數學表達式。我試圖實現一個獲取令牌(存儲爲字符串)的方法,該令牌是一個數字並將其轉換爲一個浮點數,但無論令牌是什麼,它總是返回0。

我得到了get_character功能的代碼,我不知道是正確的。我有一個小麻煩解析雖然這是怎麼回事呢,所以我不知道:

int get_character(location_t *loc) 
{ 
    int rtn; 
     if (loc->column >= loc->line->length) { 
     return 0; 
    } 
    rtn = loc->line->data[loc->column++]; 
    if (loc->column >= loc->line->length && loc->line->next) { 
     loc->line = loc->line->next; 
     loc->column = 0; 
    } 
    return rtn; 
} 

我在getNum使用它()函數假設它是正確的。它如下:

static float getNum(){ 
    char* tokenstr; 
    tokenstr = malloc(tok.length * sizeof(char)); 

    int j; 
    for(j = 0; j < tok.length; j++){ 
     tokenstr[j] = get_character(&loc); 
    } 
    match(T_LITERAL); /*match checks if the given token class is the same as the token 
         class of the token currently being parsed. It then moves the 
         parser to the next token.*/ 
    printf("%f\n", atof(tokenstr)); 
    return atof(tokenstr); 

} 

下面是一些額外的信息,需要了解上述功能正在發生什麼。這些是關於組織輸入數據的一些結構文件的細節。

爲了存儲和查找令牌,使用三種類型的結構的。一個line_t結構體,一個location_t結構體和一個token_t結構體。對於這些代碼被髮布,但概括地說:

  • 行包含字符數組(從該行的 輸入文件的輸入端),對於該行的長度的int,int型即所述 行號作爲識別形式,和一個指針到下一個 線路輸入的被讀取到存儲器中。

  • 位置包含一個指向特定行的指針,以及一個int,該行指定行的特定「列」。

  • 令牌包含用於令牌的長度的int,描述一個位置,其中標記開始,和令牌類描述什麼樣的令牌是解析器。

代碼爲這些結構:

typedef struct line { 
    char * data; 
    int line_num; 
    int length; /* number of non-NUL characters == index of trailing NUL */ 
    struct line * next; 
} line_t; 

typedef struct { 
    line_t *line; 
    int column; 
} location_t; 

typedef struct { 
    token_class tc; 
    location_t location; 
    int length;  /* length of token in characters (may span lines) */ 
} token_t; 
+2

此代碼的哪些部分是您已隔離測試的?你應該從簡單到複雜,在每一步都進行測試。否則,你至少應該給我們一個[最小完整的例子](http://stackoverflow.com/help/mcve)來查看,因爲問題可能在你沒有向我們展示的代碼中。 – Beta 2014-10-04 14:15:57

+0

我猜這是家庭作業,Bison/Flex或Yacc/Lex是不可能的;-) – 2014-10-04 14:45:37

回答

0

看來,預期的默認行爲是提取字符,然後前進到下一個之前回來。

但是,如果超過行長度(或者未將列表值初始化爲小於行長度),那麼該函數將會前進而不是

試試這個:

if (loc->column >= loc->line->length) { 
    loc->line = loc->line->next; 
    loc->column = 0; 
    return 0; 
} 

,並確保列位置正確初始化。

個人而言,我的功能改變到這樣的:

int get_character(location_t *loc) 
{ 
    int rtn = 0; 

    if (loc->column < loc->line->length) { 
     rtn = loc->line->data[loc->column++]; 
    } 

    if (loc->column >= loc->line->length && loc->line->next) { 
     loc->line = loc->line->next; 
     loc->column = 0; 
    } 

    return rtn; 
} 

我還使用無符號值的列和長度,只是爲了避免負陣列indicies的可能性。

0

我看到了許多潛在的問題與此代碼:

char* tokenstr; 
tokenstr = malloc(tok.length * sizeof(char)); 

int j; 
for(j = 0; j < tok.length; j++){ 
    tokenstr[j] = get_character(&loc); 
} 
match(T_LITERAL); /*match checks if the given token class is the same as the token 
        class of the token currently being parsed. It then moves the 
        parser to the next token.*/ 
printf("%f\n", atof(tokenstr)); 
return atof(tokenstr); 

你爲一個新的令牌字符串tokenstr創造空間,你複製它,但你不空後終止它,也沒有足夠的空間分配對於令牌加上字符串終止符\0。並且最後有一個內存泄漏,因爲tokenstr不是free ed。我可能會考慮更改類似於:

char* tokenstr; 
float floatVal; 

/* Make sure we have enough space including \0 to terminate string */ 
tokenstr = malloc((tok.length + 1) * sizeof(char)); 

int j; 
for(j = 0; j < tok.length; j++){ 
    tokenstr[j] = get_character(&loc); 
} 
/* add the end of string \0 character */ 
tokenstr[j] = '\0' 

match(T_LITERAL); /*match checks if the given token class is the same as the token 
        class of the token currently being parsed. It then moves the 
        parser to the next token.*/ 

floatVal = atof(tokenstr); 

/* Free up the `malloc`ed tokenstr as it is no longer needed */ 
free(tokenstr); 

printf("%f\n", floatVal); 
return floatVal; 
+1

對不起,我將持有者變量的名稱更改爲tokenstr,並忘記稍後在代碼中對其進行更改。我編輯OP。抱歉的混淆。 – 2014-10-04 17:05:13