2013-05-07 7 views
7

शुनिंग-यार्ड एल्गोरिदम का उपयोग करके मेरी अभिव्यक्ति पार्सर है, यह एक स्थिति को छोड़कर उम्मीद के अनुसार अच्छी तरह से काम करता है, जब मैं 2 * 3 में यूनरी माइनस का उपयोग करता हूं तो यह काम नहीं करेगा (मुझे लगता है कि यह नहीं होना चाहिए ऐसा नहीं है क्योंकि मुझे इसे संभालने के लिए एल्गोरिदम में कुछ भी नहीं मिला) क्या कोई आसान तरीका है कि मैं इसे ठीक कर सकता हूं? '-' सादर Pedramशर्टिंग यार्ड एक्सप्रेशन पार्सर

#include <cctype> 
#include <iostream> 
#include <cstring> 
#include <cstdlib> 
#include <cmath> 
using namespace std; 
int olaviat (char c) { 
    /************* 
    **Operator precedence 
    *************/ 
    switch(c) { 
     case '-' : case '+' : 
      return 1 ; 
     case '*' : case '/' : 
      return 2 ; 
     case '^' : 
      return 3 ; 
     default : 
      return 0 ; 
    } 
} 
double eval(char *exp) { 
    /************* 
    **Convert to reverse polish 
    *************/ 
    char n [50] , o[50] ; 
    static int nl = 0 , ol = 0 ; 

    while (*exp) { 
      while(isspace(*exp)) *exp++ ; 
     if(*exp == '(') { 
      o[ol++] = *exp++ ; 
      } 
     else if (*exp == ')'){ 
      while(o[--ol]!='('){ 
        n[nl++] = o[ol]; 
        n[nl++] = ' '; 
        } 
        *exp++; 
     } 
     else if (isdigit(*exp)) { 
      while (isdigit(*exp)) { 
      n[nl++] = *exp++ ; 
      } 
     n[nl++] = ' ' ; 
     } 
     else if (strchr("+-*/^",*exp)){ 
      if(olaviat(*exp) > olaviat(o[ol-1])) { 
       o[ol++] = *exp++ ; 


      } 
      else { 
        if(olaviat(*exp) == olaviat(o[ol-1]) && olaviat(*exp)== 3) { 
         o[ol++] = *exp++ ; 
        }else{ 
       n[nl++] = o[ol-1] ; 
       n[nl++] = ' ' ; 
       o[--ol] = '\0' ; 

        } 
      } 
     } 

    } 

for (int k = ol-1 ; k >= 0 ; k --){ 
    n[nl++] = o[k]; 
    n[nl++] = ' ' ; 
} 
/*******************************/ 
cout << "Reverse Polish" << endl ; 
for (int i = 0 ; i < nl-1 ; i++){ 
     cout << n[i] ; 
    } 
cout << endl ; 
//n[nl+1] = '\0' ; 
/******************************* 
**Calculate Result 
*******************************/ 
    double temp[50]; 
    char *e ; 
    ol = 0; 
    int nol = 0 ; 
    e=n ; 
    int digitcount = 0; 
    while (*e) { 
      while (isspace(*e)) *e++; 
     if (isdigit(*e)) { 
      while (isdigit(*e)) { 
      o[ol++] =*e++ ; 
      digitcount++ ; 
      } 
     temp[nol++] = atof(o) ; 
     for (int i = 0 ; i < digitcount ; i++) 
      o[i]='\0' ; 
     ol=0; 
     digitcount = 0 ; 
     } 
     else if (strchr("+-*/^",*e)){ 
      // char opr ; 
      double tempAns = 0; 
      switch (*e) { 
       case '+' : 
        tempAns = temp[nol-2] + temp [nol-1] ; 
        break ; 
       case '-' : 
        tempAns = temp [nol-2] - temp [nol-1] ; 
        break; 
       case '*' : 
        tempAns = temp [nol-2] * temp [nol-1] ; 
        break; 
       case '/' : 
        tempAns = temp[nol-2]/temp[nol-1]; 
        break ; 
       case '^' : 
        tempAns = pow(temp[nol-2],temp [nol-1]); 
        break ; 
       default : 
       cout << "\n Unknown error" ; 
       continue; 
      } 
      *e++ ; 
      nol--; 
      temp[nol-1] = tempAns ; 
      temp[nol] = NULL ; 
     } 
     else { 
      break ; 
     } 
    } 
    double ans = temp[0]; 

    return ans ; 
} 

int main() { 

char exp[100]; 
char c; 
start : 
    cin.get (exp , 99); 
    cout << "\n\tANS= " << eval(exp) ; 
    cout << endl ; 
    system("PAUSE"); 
    return 0; 
} 
+0

हालांकि यह एक अलग सवाल था, मैं http://stackoverflow.com/questions/16380234/handling-extra-operators-in-shunting-yard/16392115#16392115 – rici

उत्तर

6

ऊपर विकल्प सही है, लेकिन यह होगा - जब आप यह भी क्या करना है।। बहुत बोझिल और छोटी गाड़ी प्राप्त करें। 2*-(1+2)^-(2+5*-(2+4)) मामले पर विचार करें। जैसा कि आप देख सकते हैं कि आपको कई चीजों को ध्यान में रखना होगा। इसके अलावा जब भी आपको "* - (" उदाहरण के लिए आप जानते हैं कि आप इसे * (0- (...., जिसे एक बोझिल रिकर्सिव फ़ंक्शन में कोड किया जाएगा। सबसे अच्छा समाधान बहुत आसान है। ऑपरेटरों पर, ऑपरेटर को "-" मामलों में ध्यान दें, और यह पहले किसी अन्य ऑपरेटर द्वारा किया गया है, या इससे पहले बाएं कोष्ठक द्वारा, या जब यह इनपुट का पहला अक्षर होता है (इन मामलों का मतलब है कि यह बाइनरी के बजाय एक यूनरी माइनस है)। इस मामले में, आप इसे दूसरे चरित्र में बदलते हैं, 'यू' (यह मेरा मामला था) कहता है, और इसकी प्राथमिकता '^' के समान ही बनाते हैं।

इसके अलावा, इसे शाब्दिक संख्या के हिस्से के रूप में देखते हुए इसकी पकड़ है। एक मामला कल्पना कीजिए जैसे -2^4। वोल्फ्राम अल्फा में आपको -16, 16 नहीं मिलेगा।

और ढेर का उपयोग करने पर विचार करें। वे आपके जीवन को आसान बना देंगे।

मुझे बताएं कि मेरा क्या मतलब है।

: - 7 + (- 9 * 8) * 2^- - 9 5

प्रतिस्थापन मैं सुझाव बनाना, इसे इस तरह बन जाएगा

2 /: विचार करें आप इनपुट दिया जाता है

2/u 7 + (यू 9 * 8) * 2^यू 9 - 5

अब आप अपने ऑपरेटर पूर्वता स्विच बदला जाना चाहिए करने के लिए:

switch(c) 
{ 
     case '-' : case '+' : 
      return 1 ; 
     case '*' : case '/' : 
      return 2 ; 
     case '^' : case 'u': //note the 'u' operator we added 
      return 3 ; 
     default : 
      return 0 ; 
} 

और, ज़ाहिर है, आपको इस यूनरी ऑपरेटर का समर्थन करने के लिए परिवर्तन करने की आवश्यकता है।

+0

ग्रेट, धन्यवाद। मैं यह जोड़ना चाहता हूं कि पिछले ऑपरेटर की जांच करते समय, सुनिश्चित करें कि ऑपरेटर यूनरी नकारात्मक नहीं है। यह -1 -4 बनने से -1 -4 और त्रुटियों का उत्पादन करने से रोकता है। यह काम से 4 --- रोकता है (जो उचित व्यवहार है, क्योंकि --- 4 सही गणित वाक्यविन्यास नहीं है। - (- (- 4)) अभी भी काम करेगा)। –

1

एक विकल्प सामने एक 0 डाल करने के लिए करता है, तो पहले वर्ण है - (*/^ यह एक सरल पार्सर मैं केवल जरूरत है() + है)। (एक के बाद है

अच्छे लोगों को या तो एकल माइनस ऑपरेटर को लागू कर रहे हैं या नंबर शाब्दिक के हिस्से के रूप में यह इलाज

+0

+1 के उत्तर में एक समाधान की रूपरेखा तैयार करता हूं, आप अभिव्यक्ति में कहीं और दफन किए गए ''' और '+' को भी देखना होगा, उदाहरण के लिए '" 1 - (- 2) "' या '" 1 * -2 "'। [ब्रसर इस समस्या को ठीक करने के लिए खोज/प्रतिस्थापन का उपयोग करता है] (https://github.com/dtitov/bracer/blob/master/src/main/java/com/autsia/bracer/BracerParser.java)। – user7116

+0

मेरा मतलब है कि हर जगह यूनरी माइनस न केवल पहले अक्षर जैसे 2 * -5 2^-1, .... – PedramH

संबंधित मुद्दे