C / Lex Char указатель на значение печати другого указателя, а также - PullRequest
0 голосов
/ 19 февраля 2020

Я пишу программу 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++)

Почему это происходит? Как мне это исправить?

1 Ответ

1 голос
/ 19 февраля 2020

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.

...