2010-03-11 4 views
0

큐를 사용하여 일부 입력을 구문 분석하여 접두사 수학 표현식을 괄호가있는 중위 수학 표현식으로 바꾸려고합니다. 예 : +++ 12 20 3 4 (((12 + 20) +3) +4)로 바뀝니다. 대부분의 경우 하나의 특정 사항을 제외하고는 알고리즘이 작동합니다. 숫자가 2 자리보다 길면 출력이 이상하게됩니다. 설명을 시도하는 대신 몇 가지 예를 들어 드리겠습니다.잘못된 데이터를주는 큐

Examples: +++12 200 3 4 becomes (((12+3)+3)+4) 
+++12 2000 3 4 becomes (((12+20004)+3)+4) 
+++12 20005 3 4 becomes (((12+20004)+3)+4) 
+++12 20005 3 45 becomes (((12+20004)+3)+45) 
+++12 20005 3 456 becomes (((12+20004)+3)+() 

더 많은 정보가 필요하면 충분할 것입니다.

Mac OSX 10.6.2의 XCode에서 GCC 4.2를 사용하고 있습니다. 당신이 어떤 주석 또는 정확히 어떤 물건을 알려 주시기 바랍니다 무엇을하는지 설명해야하는 경우

#include "EParse.h" 
#include <iostream> 
#include <iomanip> 


EParse::EParse(char* s) 
{ 
    this->s = s; 
    len = strlen(s); 
} 

void EParse::showParsed() 
{ 
    parse(s, 0, len, new std::queue< char* >(), new std::queue<char>()); 
} 

void EParse::parse(char* str, int beg, int len, std::queue< char* > *n, std::queue<char> *ex) 
{ 
    //ex is for mathematical expressions (+, -, etc.), n is for numbers 
    if(beg == len) 
    { 
     if(ex->size() > n->size()) 
     { 
      std::cout << "Malformed expression. Too many mathematical expressions to too few numbers." << std::endl; 
      std::cout << ex->size() << " mathematical expressions." << std::endl; 
      std::cout << n->size() << " number(s)." << std::endl; 
      return; 
     } 
     else 
     { 
      std::string *s = new std::string(); 
      output(n, ex, 0, s); 
      std::cout << s->c_str(); 
      return; 
     } 
    } 

    if(str[ beg ] == ' ' && beg != (len - 1)) 
     beg++; 
    if(num(str[ beg ])) 
    { 
     std::string *s = new std::string(); 
     getNum(s, str, beg, len); 
     //std::cout << s->c_str() << std::endl; 
     n->push(const_cast< char* >(s->c_str())); 
     delete s; 
     parse(str, beg, len, n, ex); 
    } 
    else if(mathexp(str[ beg ])) 
    { 
     ex->push(str[ beg ]); 
     parse(str, beg + 1, len, n, ex); 
    } 
} 

void EParse::getNum(std::string *s, char* str, int &beg, int len) 
{ 
    if(num(str[ beg ])) 
    { 
     char *t = new char[ 1 ]; 
     t[ 0 ] = str[ beg ]; 
     s->append(t); 
     beg += 1; 
     getNum(s, str, beg, len); 
    } 
} 

bool EParse::num(char c) 
{ 
    return c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || 
    c == '5' || c == '6' || c == '7' || c == '8' || c == '9'; 
} 

bool EParse::mathexp(char c) 
{ 
    return c == '+' || c == '*' || c == '/' || c == '%' || c == '-'; 
} 

void EParse::output(std::queue< char* > *n, std::queue<char> *ex, int beg, std::string *str) 
{ 
    if(ex->empty()) 
    { 
     return; 
    } 

    char *t = new char[1]; 
    t[ 0 ] = ex->front(); 
    ex->pop(); 
    if(beg == 0) 
    { 
     str->insert(0, "("); 
     str->append(n->front()); 
     beg += 1 + strlen(n->front()); 
     n->pop(); 
     str->append(t); 
     str->append(n->front()); 
     str->append(")"); 
     beg += 2 + strlen(n->front()); 
     n->pop(); 
    }  
    else 
    { 
     str->insert(0, "("); 
     str->insert(beg, t); 
     str->insert(beg + 1, n->front()); 
     beg += 1 + strlen(n->front()); 
     str->insert(beg, ")"); 
     n->pop(); 
     beg++; 
    } 

    //ex->pop(); 
    output(n, ex, beg + 1, str); 
    //std::cout << str << std::endl; 
} 

, 나는 꽤 자주 오늘 밤을 확인한다 : 여기

그리고

이 멋진 일을 수행하는 코드입니다 . 나는 당신의 문제에 대한 정확한 답을 가지고 있지 않지만

+0

사용중인 EParse 클래스의 몇 가지 예를 게시 할 수 있습니까? 즉 main() 함수 또는 이와 유사한 함수? – razlebe

+0

@sgreeve 게시물의 맨 위에 넣은 예제를 확인하십시오. 그것들은 수업을 사용하는 방법과 거의 같습니다. EParse e ("+++ 12 200 3 4"); e.showParsed(); 그게 내 주안이야. 모든 구문 분석은 클래스 내에서 출력되기 전에 클래스 내에서 수행됩니다. 부수적으로이 클래스는 순전히 재귀 적 메서드를 사용합니다. 나는 보통 그렇게하지 않을 것이지만 숙제를 위해 필요합니다. – Freezerburn

+0

감사합니다. showParsed()를 호출하는 모든 코드 행을 거치지 않고 게시 한 예제는 명확하지 않습니다. 더 명확하게 만들면 더 빨리 도움을받을 사람을 얻을 수 있습니다! – razlebe

답변

2

, 나는이 통지 않았다

std::string *s = new std::string(); 
getNum(s, str, beg, len); 
//std::cout << s->c_str() << std::endl; 
n->push(const_cast< char* >(s->c_str())); 
delete s; 

대기열에 s를 밀고하고 당신이 그것을 삭제하는이 문제. 그러면 큐가 더 이상 유효하지 않은 문자열 값을 참조하게되어 설명하는 오류가 발생할 수 있습니다. 당신이 밀어 데이터에 전체 std::string의 대신 포인터를 팝업 수있는 그런

std::queue<std::string> 

:

n->push(s); 

나는 당신의 대기열 유형을 변경하는 것이 좋습니다 것입니다, 당신을 위해 좀 더 쉽게 인생을 만들려면

루틴의 API를 char*에서 std::string&으로 변경해야하지만 char *처럼 문자열 값을 수정할 수 있습니다.

+0

Aaaah, 고마워, 그 트릭을 했어. 너무 많은 코드를 게시하여 죄송합니다. 날카로운 시력을 위해 – Freezerburn

+0

+1. – razlebe

0

덧붙여 위의 코드에서 메모리 관리를 다시 한 번 볼 수 있습니다. delete이없는 new 할당이 많아서 메모리가 누출됩니다.

+0

그래, 나는이 사실을 깨닫는다. 나는 그것이 한 번 실행 후 프로그램을 종료 한 이후로 작동하게 만드는 것에 대해 주로 걱정했습니다. 다음에 작동 할 때 메모리 정리를 추가해야합니다. 그래도 그것을 지적 주셔서 감사합니다. – Freezerburn