【问题标题】:C/Lex char pointer printing value of other pointer as wellC/Lex char 指针也打印其他指针的值
【发布时间】:2020-06-03 20:44:58
【问题描述】:

我正在编写一个 lex 程序。我已经初始化了 3 个字符指针。然后,如果它们满足标准,我将它们定义为令牌。但是当我之后打印它们时,第一个打印所有 3 的值,最后两个的第二个和它自己的最后一个。为什么会这样?这是我的代码:

%{
    #include<stdio.h>
    #include<string.h>

    int for_cond = 0;
    char *cond1, *cond2, *cond3;
    char * for_body = "";
    //char * loop = "";
    %}
    VAR [a-zA-Z_]+[a-zA-Z0-9_]*
    %%
    for[ ]*\( {for_cond++;}
    int[ ]+{VAR}[ ]*\=[ ]*[0-9]+ {if(for_cond==1){cond1 = yytext;}else if(for_cond==4){for_body = strcat(for_body,yytext);}}
    ; {if(for_cond==1||for_cond==2){for_cond++;} else if(for_cond==4){for_body = strcat(for_body,yytext);}}
    {VAR}[ ]*(\<|\>|\<\=|\>\=|\=\=)[ ]*[0-9]+ {if(for_cond==2){cond2 = yytext;}else if(for_cond==4){for_body = strcat(for_body,yytext);}}
    {VAR}[ ]*((\+\+|\-\-)|((\+\=|\-\=|\*\=|\/\=)[ ]*({VAR}|[0-9]+))) {if(for_cond==3){cond3 = yytext;}else if(for_cond==4){for_body = strcat(for_body,yytext);}}
    %%
    int yywrap(void){}
    int main(){

        yylex();
        printf("cond1 = %s\ncond2 = %s\ncond3 = %s\n", cond1, cond2, cond3);

        return 0;
    }

示例输入:

for(int i=0;i<=2;i++)

预期输出:

cond1 = int i=0

cond2 = i<=2

cond3 = i++

我得到了什么:

cond1 = int i=0;i<=2;i++)

cond2 = i<=2;i++)

cond3 = i++)

为什么会这样?我该如何解决这个问题?

【问题讨论】:

  • 你能把代码分成多行,正常缩进,以便我们更容易阅读吗?

标签: c string pointers lex char-pointer


【解决方案1】:

yytext 指向词法分析器内部的临时数据结构,其生存期仅限于词法分析器操作。 (更准确地说,它的生命周期从词法分析器操作开始,并在词法扫描之前结束。)

换句话说,您不能将yytext 的值保存为指针。如果要保留字符串以供以后使用,则必须复制 yytext 指向的字符串的内容。如果你有strdup,你可以用它来创建一个字符串的副本(但是当你不再需要它时不要忘记free()这个副本。)如果你没有strdup,或者不管什么原因不想用,都可以自己动态分配空间:

char* theToken = malloc(yyleng + 1); strcpy(theToken, yytext);

还值得一提的是,鉴于for_body 指向长度为 0 (char * for_body = "";) 的不可变字符串,尝试向其添加文本是未定义行为:

strcat(for_body,yytext);

在许多平台上,该调用会出现段错误,因为for_body 的初始化使其指向只读内存。但是如果内存是可写的,它就不是for_body指向的数组的一部分,这意味着它是一些其他对象的一部分,其值将被strcat的调用破坏。

【讨论】:

  • 所以基本上我在做yytext的深拷贝,而我应该做浅拷贝,对吧?另外,如果我用来更新for_body 的方法不正确,那么正确的方法是什么?我想动态地继续向它添加文本,类似于我们如何使用 + 处理 C++ 字符串
  • 您根本没有复制yytext。你应该复制它。 C 没有字符串,也没有办法增长 C 数组。你所能做的就是分配一个更大的数组并复制。没有什么能阻止您将 C++ 与 Flex 结合使用。生成的代码可以编译为 C++ 并且可以正常工作。您可能会发现这是一个更舒适的解决方案。如果你想使用 C,你需要阅读动态分配。
  • 那么cond1 = yytext 究竟做了什么?将yytext指向的char数组的内存位置复制到cond1?
  • @ShantanuShinde:指针是原始值,所以是的;之后,cond1yytext 指向同一个地方。 (它位于 flex 内部缓冲区的中间。)没有字符被复制。这与std::str cond1 = yytext; 完全不同,后者会复制字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
  • 2018-09-11
  • 2021-11-26
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多