编辑:所以看起来问题是getNum应该转换为float的字符串实际上不是包含令牌的所有字符的字符串。相反,它包含紧跟在令牌之后的字符,通常是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);
}
以下是了解上述功能中所发生情况所需的一些其他信息。这些是有关组织输入数据的一些struct文件的详细信息。
为了存储和查找令牌,使用了三种类型的结构。 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;
答案 0 :(得分: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;
}
我还会为列和长度使用无符号值,只是为了避免负数组指示的可能性。
答案 1 :(得分: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
。我可能会考虑更改类似的内容:
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;