2016-10-18 9 views
0

나는 들소를 배우고 문제를 만난다. {1, 2, 3}과 같은 정수 세트를 허용하도록 RE를 설계하려고합니다. 다음은 제 코드의 일부입니다. 간단한 계산이 세트 코드가 올바르게 작동 - I 입력 "{2} {1}"때들소에서 메모리를 어떻게 관리합니까?

printf("given {, str_to_out before %s \n", str_to_out); 
str_to_out[0] = '{'; 
printf("given {, str_to_out after %s \n", str_to_out); 

문제이다. 다음과 같이 두 장이 찍혔습니다.

given {, str_to_out before 
given {, str_to_out after {1} 

무엇이 문제입니까? 메모리 관리에 문제가있어 이해할 수 없기 때문에 생각합니다. 도와 주신 모든 분들께 감사드립니다 !! 다른 코드는 다음과 같습니다. "MinusPoly ($$, $ 1, $ 3)"함수에서 시작하여 "Format()"-> "Expand()"순서로 프로세스가 시작됩니다. 문제는에 일어나는 "확장()"

%{ 
#define YYSTYPE char * 
#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define MAXL 5000 
int yyerror(const char* s); 
int yylex(void); 
void MinusPoly(char *a,const char *p1, const char *p2); 
void Format(char* str); 
void AppendIntToStr(char* str, int num); 
void Expand(char* str); 
void RmRedunInt(char *str_to_out); 
void StrToIntList(char *str, int list[], int *count); 
int IsExist(int target, int list[], int length); 
void IntListToStr(char *str, int list[], int length); 
void RmWs(char* str); 
%} 
%token NUM 
%token LB RB POLY BRACE SET INTERSECT UNION MAX MIN 
%left '-' '+' 
%left '*' '/' DOTM 
%right '^' 
%% 
/* grammar rules and actions follow in {}*/ 

input: input line 
    | line 
    ; 

line: '\n' 
     | expr '\n' {printf("res %s\n",$1);} 
    ; 

expr: expr '-' expr_md {MinusPoly($$,$1,$3);} 
    | expr '+' expr_md {} 
    | expr_md {$$=$1;} 
    ; 

expr_md: expr_md '*' expr_hi {printf("multiply \n");} 
    | expr_md '/' expr_hi  {} 
    | expr_hi {$$=$1;} 
    ; 

expr_hi: LB expr RB {$$ = $2;} 
    | SET {printf("set %s\n",$1);} 
    ; 

%% 
#include<ctype.h> 
int main(void){ 
return yyparse(); 
} 
int yyerror(const char* s) { return 0; } 

void MinusPoly(char *a,const char *p1, const char *p2){ 
    int l1 = strlen(p1), l2 = strlen(p2); 
    int i; 
    char s, np1[MAXL],np2[MAXL]; 
    strcpy(np1,p1); 
    strcpy(np2,p2); 
    Format(np1); 
    Format(np2); 
    printf("np1 %s\n",np1); 
    printf("np2 %s\n",np2); 
    return; 
} 

void Format(char* str){ 
    char temp[MAXL]; 
    int i, j ,len; 
    strcpy(temp,str); 
    RmWs(temp); 
    Expand(temp); 
    len = strlen(temp); 
    printf("str is %s\n",temp); 
    for(i=0; i < len; i ++){ 
     str[i] = temp[i]; 
    } 
    str[i] = '\0'; 
    return; 
} 

void Expand(char* str){ 
    int i,j, len, outlen = 0, num1, num2,len1 = 0, len2 = 0,curr_num = 0; 
    char temp_sbl; 
    char str_to_out[MAXL], str_range[10], str_num[10]; 
    strcpy(str_to_out,""); 
    len = strlen(str); 
    printf("input str is %s, length %d\n",str,len); 
    if(len <= 2) 
     return; 
    for(i = 0 ;i < len; i ++){ 
     temp_sbl = str[i]; 
     if(temp_sbl == '{'){ 
printf("given {, str_to_out before %s \n", str_to_out); 
      str_to_out[0] = '{'; 
printf("given {, str_to_out after %s \n", str_to_out); 
      outlen++; 
      continue; 
     } 
     if(temp_sbl == '-'){ 
      num1 = curr_num; 
      num2 = 0; 
      curr_num = 0; 
      for(j = i + 1; j <len; j ++){ 
       if(!isdigit(str[j])){ 
        break; 
       } 
       num2 = num2 * 10 + str[j] - '0'; 
      } 
      i = j; 
      if(num1 <= num2){ 
       for(j = num1; j <=num2; j++){ 
        AppendIntToStr(str_to_out,j); 
        outlen = strlen(str_to_out); 
        if(j<num2){ 
         str_to_out[outlen] = ','; 
         outlen++; 
        } 
       } 
      } 
      else{ 
       for(j = num2; j <=num1; j++){ 
        AppendIntToStr(str_to_out,j); 
        outlen = strlen(str_to_out); 
        if(j<num1){ 
         str_to_out[outlen] = ','; 
         outlen++; 
        } 
       }    
      } 
      str_to_out[outlen] = str[i]; 
      outlen++; 
      continue; 
     } 
     if(temp_sbl == ',' || temp_sbl == '}'){ 
      AppendIntToStr(str_to_out,curr_num); 
      outlen = strlen(str_to_out); 
      str_to_out[outlen] = temp_sbl; 
      outlen++; 
      curr_num = 0; 
      continue; 
     } 
     curr_num = curr_num * 10 + str[i] - '0'; 

    } 
    strcpy(str,""); 
    RmRedunInt(str_to_out); 
    strcpy(str,str_to_out); 
    return; 
} 

void IntListToStr(char *str, int list[], int length){ 
    int i,j, len = 0; 
    char str_num[50]; 
    str[0] = '{'; 
    len = 1; 
    for(i = 0 ; i < length; i ++){ 
     strcpy(str_num,""); 
     sprintf(str_num,"%d",list[i]); 
     strcat(str,str_num); 
     len = strlen(str); 
     if(i < length - 1) 
      str[len] = ','; 
     else 
      str[len] = '}'; 
     len++; 
    } 
    return; 
} 

int IsExist(int target, int list[], int length){ 
    if(length==0) 
     return 0; 
    int i; 
    for(i=0;i<length;i++) 
     if(list[i]==target) 
      return i+1; 
    return 0; 
} 

void StrToIntList(char *str, int list[], int *count){ 
    int i, j , tempcount = 0, temp_ls[1000], len = strlen(str); 
    int curr_num = 0; 
    for(i = 0 ; i < len ; i ++){ 
     if(str[i] == '{') 
      continue; 
     if(str[i] == ',' || str[i] == '}'){ 
      list[tempcount] = curr_num; 
      tempcount++; 
      curr_num = 0; 
      continue; 
     } 
     curr_num = curr_num * 10 + str[i] - '0'; 
    } 
    *count = tempcount; 
    return; 
} 

void RmRedunInt(char *str_to_out){ 
    int i,j ,len; 
    int ls_num[1000],count = 0, temp_ls[1000], tempcount = 0; 
    char str_temp[MAXL]; 
    strcpy(str_temp,""); 
    StrToIntList(str_to_out,temp_ls,&tempcount); 
    for(i = 0; i < tempcount; i ++){ 
     if(IsExist(temp_ls[i],ls_num,count)) 
      continue; 
     ls_num[count] = temp_ls[i]; 
     count++; 
    } 
    IntListToStr(str_temp,ls_num,count); 
    strcpy(str_to_out,""); 
    strcpy(str_to_out,str_temp); 
    return; 
} 



void AppendIntToStr(char* str, int num){ 
    char str_num[50]; 
    strcpy(str_num,""); 
    sprintf(str_num,"%d",num); 
    strcat(str,str_num); 
    return; 
} 

답변

0

내가 관찰 :

  • 매개 변수로 $$을 통과 MinusPoly에 대한 귀하의 전화가 이상하다, 그러나 $$ 규칙의 반환 값 .

  • expr 규칙의 반환 값을 절대로 지정하지 마십시오. expr_md '/' expr_hi과 같은 규칙은 다음과 같은 일부 처리가 필요합니다. {$$=$1/$3;}

  • 다른 규칙에서도이 실수를 저지른 것입니다.

이 문제를 먼저 해결하는 것이 좋습니다. bison의 "메모리 관리"에 관해서 : 그것은 C 프로그램으로 실행되며 자체 메모리 관리 기능이 없습니다. 주의해야 할 유일한 사항은 규칙을 왼쪽 - 재귀 적으로 만드는 것입니다 (그렇지 않으면 스택이 부족할 수 있습니다).

+0

감사합니다. 필자가 다른 작은 프로그램을 시작하고 들소를 사용하지 않고이 모든 기능을 넣으므로 아마도 아마도 들소의 문제가 아닐 것입니다. 문제도 발생합니다. "str_to_out"문자열이 "Expand()"함수가 종료 될 때 해제되지 않는 것 같습니다. 무엇이 문제입니까 ... – pfc

+0

자동 변수이기 때문에 해제됩니다. 그러나 나는'str_to_out'을'\ 0'으로 끝내지 않는다는 것을 알 수 있습니다. 예를 들어 그렇게해야합니다. AppendIntToStr를 호출하기 전에. 자동 변수는 0으로 초기화되지 않습니다. 또한 디버거를 사용하여 진행 상황을 확인하는 것이 좋습니다. –

+0

질문이 하나 더 있습니다. $$을 매개 변수로 전달하기 때문에 MinusPoly에 대한 내 호출은 문자열이라고했습니다. 그 이유는이 "$$ = MinusPoly ($ 1, $ 3)"을 시도했지만, 돌아 왔을 때 로컬 포인터를 반환 할 수 없다고보고합니다. 그것을 고칠 방법이 있습니까? 고맙습니다! – pfc