递归解析器帮助

时间:2011-02-28 03:44:24

标签: c++

我应该写这个接受01及以上的c ++。例如:01010101但不是0,1,10,011,110。有人可以帮我弄清楚我需要做些什么来解决这个问题。对不起,伙计们代码不能正常工作。我按了ctrl + k并发布了代码,但一切都没有到位。

我试图做的是当一些人输入1而不是打印无效时。如果输入0则打印无效,如果输入10打印无效,如果输入01打印有效,如果输入0101打印有效。所以0总是必须先来,然后一直跟着1.另一个例子:0101010101打印有效

谢谢Seth :)。我删除了链接

[来自seth.arnold:我删除了注释掉的代码并缩进代码以遵循某种逻辑模式。如果您愿意,可以随意将其替换为代码,将每行缩进四个空格以正确格式化。]

#include <iostream>
#include<stdlib.h>  // for the exit(1) function
using namespace std;

char text[300];
char ToBeChecked;

char lexical(); //identify the characters
void SProd();
void BProd();


int main(){
    cout<<"Enter some strings only 1 and 0 (max. 300 characters"<<endl;
    cin>>text;

    ToBeChecked = lexical(); //identify the character; find the first letter and give it to ToBeChecked
    SProd();

    if(ToBeChecked == '\0')
        cout<<"Valid"<<endl;
    else
        cout<<"Invalid"<<endl;

    cin.get();
    return 0;
}

char lexical(){
    static int index = -1;   //a memory box named index with a value of -1; is static so it won't change.
                             //is -1 because -1 to 1 is 0; everything move on to next one
    index++; //update index
    return text[index]; //return the value of index
}

void SProd(){
    if(ToBeChecked != '0' ) {
        cout<<"Invalid"<<endl;
        exit(1);
    }
    else{
        BProd();
        ToBeChecked = lexical();
    }
}

void BProd(){
    if(ToBeChecked != '1')
    {
        cout<<"Invalid"<<endl;
        exit(1);
    }
    else
        SProd();

    ToBeChecked = lexical();
}

2 个答案:

答案 0 :(得分:3)

使用c ++第6-7章查看Bjorn Stroustroup的“编程原理和实践”一书。

你必须写出语法,你需要知道如何:

  1. 区分规则与令牌
  2. 一个又一个规则(排序)
  3. 表达替代模式(更改)
  4. 表达重复模式 (重复)
  5. 识别要开始的语法规则 与
  6. 例如 - 你必须有一个令牌类:

        class Token {
    public:
        char kind;        // what kind of token
        double value;     // for numbers: a value 
        Token(char ch)    // make a Token from a char
            :kind(ch), value(0) { }    
        Token(char ch, double val)     // make a Token from a char and a double
            :kind(ch), value(val) { }
    };
    

    然后令牌流类:

    class Token_stream {
    public: 
        Token_stream();   // make a Token_stream that reads from cin
        Token get();      // get a Token (get() is defined elsewhere)
        void putback(Token t);    // put a Token back
    private:
        bool full;        // is there a Token in the buffer?
        Token buffer;     // here is where we keep a Token put back using putback()
    };
    

    识别令牌流的默认构造函数:

    Token_stream::Token_stream()
    :full(false), buffer(0)    // no Token in buffer
    {
    }
    

    然后创建一个putback()函数,如果你感兴趣的话,你将需要将你从iostream中读取的字符放回去,并且将调用专门提取该特定字符的函数:

    void Token_stream::putback(Token t)
    {
        if (full) throw std::runtime_error("putback() into a full buffer");
        buffer = t;       // copy t to buffer
        full = true;      // buffer is now full
    }
    

    然后在Token :: get()中,您必须制定对您来说重要的规则以及您想要包含的内容,省略或抛出错误:

    Token Token_stream::get()
    {
        if (full) {       // do we already have a Token ready?
            // remove token from buffer
            full=false;
            return buffer;
        } 
    
        char ch;
        cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)
    
        switch (ch) {
        case '=':    // for "print"
        case 'x':    // for "quit"
        case '(': case ')': case '{': case '}': case '+': case '-': case '*': case '/': case '!':
            return Token(ch);        // let each character represent itself
            break;
        case '.':
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '9':
            {    
                cin.putback(ch);         // put digit back into the input stream
                double val;
                cin >> val;              // read a floating-point number
                return Token('8',val);   // let '8' represent "a number"
            }
            break;
        default:
            throw std::runtime_error("Bad token");
    
        }
    }
    

    在这个版本的Token_stream :: get()中,我们对数字,数学运算符和括号感兴趣。因此,您必须更改该case语句以获得“1”或“0”,并忽略其他所有内容,或者抛出,这取决于您,我不知道您需要做什么。

    然后创建一个语法函数,你必须建立一个函数的层次结构,如果你想要或者在另一个之前处理示例1个字符,它们会相互调用。但如果您只需要按顺序阅读,则只能有1个功能。无论如何,我包含3个使用计算器示例的函数,其中有+, - ,*,/,(,),{,}。如您所见,此示例需要确定它是什么,以便在另一个之前调用正确的函数,例如 - 在订阅之前进行乘法。

    primary()函数处理数字和括号:

        // deal with numbers and parentheses
    double primary()
    {
        Token t = ts.get();
    
    
        switch (t.kind) {
        case '(':    // handle '(' expression ')'
            {
                double d = expression();
                t = ts.get();
                if (t.kind != ')') throw std::runtime_error("')' expected");
                return d;
                break;
            }
        case '{':
            {
                double d = expression();
                t=ts.get();
                if (t.kind != '}') throw std::runtime_error("'}' expected");
                return d;
                break;
            }
        case '8':            // we use '8' to represent a number
            return t.value;  // return the number's value
            break;
        default:
            throw std::runtime_error("primary expected");
        }
    }
    

    term()函数处理乘法和除法:

    // deal with *, /, and %
    double term()
    {
        double left = primary();
        Token t = ts.get();        // get the next token from token stream
    
        while(true) {
            switch (t.kind) {
            case '*':
                left *= primary();
                t = ts.get();
                break;
            case '/':
               {    
                    double d = primary();
                    if (d == 0) throw std::runtime_error("divide by zero");
                    left /= d; 
                    t = ts.get();
                    break;
                }
            default: 
                ts.putback(t);     // put t back into the token stream
                return left;
            }
        }
    }
    

    expression()处理加法和减法:

    double expression()
    {
        double left = term();      // read and evaluate a Term
        Token t = ts.get();        // get the next token from token stream
    
        while(true) {    
            switch(t.kind) {
            case '+':
                left += term();    // evaluate Term and add
                t = ts.get();
                break;
            case '-':
                left -= term();    // evaluate Term and subtract
                t = ts.get();
                break;
            default: 
                ts.putback(t);     // put t back into the token stream
                return left;       // finally: no more + or -: return the answer
    
            }
        }
    }
    

    最后我们的呼叫功能:

    int callDrill_01(void)
    try
    {
        std::cout << "Welcome to simple calculator." << std::endl;
        std::cout << "Please enter expressions using floating-point numbers." << std::endl;
        std::cout << "The arithmetic operators available are: + - * / ( ) { } = e(x)it." << std::endl;
    
        double val = 0;
        while (cin) {
            Token t = ts.get();
    
            if (t.kind == 'x') break; // 'q' for quit
            if (t.kind == '=') {       // ';' for "print now"
                cout << "=" << val << '\n';
            }else{
                ts.putback(t);
            }
            val = expression();
        }
        keep_window_open();
    }
    catch (exception& e) {
        cerr << "error: " << e.what() << '\n'; 
        keep_window_open();
        return 1;
    }
    catch (...) {
        cerr << "Oops: unknown exception!\n"; 
        keep_window_open();
        return 2;
    }
    

    这可以让您了解如何创建递归解析器。你的脑袋可能正在旋转。我建议你找到我提到过的那本书并阅读这些章节。它将在未来帮助你。

答案 1 :(得分:0)

#include <iostream>
//#include<stdlib.h>  // for the exit(1) function
using namespace std;

char text[300];
char ToBeChecked;

char lexical(); //identify the characters
void SProd();
void BProd();


int main(){
    cout<<"Enter some strings (max. 300 characters"<<endl;
    cin>>text;

    ToBeChecked = lexical(); //identify the character; find the first letter and give it to ToBeChecked
    SProd();

    if(ToBeChecked == '\0')
        cout<<"Valid"<<endl;
        else
        cout<<"Invalid"<<endl;
    cin.get();
    return 0;
}

char lexical(){
    static int index = -1;   //a memory box named index with a value of -1; is static so it won't change.
                            //is -1 because -1 to 1 is 0; everything move on to next one
    index++; //update index
    return text[index]; //return the value of index
}

void SProd(){
    if(ToBeChecked != 'a' ) {
       BProd();
       ToBeChecked = lexical();
      }
}

void BProd(){
    if(ToBeChecked == 'b'){
        ToBeChecked = lexical();
        SProd();
    }
}