以下是一个简单的 C++ 程序,可以实现同时包含字符和小数的广义表:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class Node {
public:
    virtual ~Node() {}
};

class ValueNode : public Node {
public:
    virtual ~ValueNode() {}
};

class IntNode : public ValueNode {
public:
    IntNode(int v) : value(v) {}
    int getValue() const { return value; }
private:
    int value;
};

class FloatNode : public ValueNode {
public:
    FloatNode(float v) : value(v) {}
    float getValue() const { return value; }
private:
    float value;
};

class StringNode : public ValueNode {
public:
    StringNode(const string& v) : value(v) {}
    const string& getValue() const { return value; }
private:
    string value;
};

class ListNode : public Node {
public:
    ListNode() {}
    ~ListNode() {
        for (auto it = children.begin(); it != children.end(); ++it) {
            delete *it;
        }
    }
    void addChild(Node* child) { children.push_back(child); }
    const vector<Node*>& getChildren() const { return children; }
private:
    vector<Node*> children;
};

class Parser {
public:
    Parser(const string& s) : str(s), pos(0) {}
    Node* parse() {
        return parseList();
    }
private:
    Node* parseList() {
        if (pos >= str.size()) {
            return nullptr;
        }
        auto node = new ListNode();
        pos++; // skip the opening parenthesis
        while (pos < str.size() && str[pos] != ')') {
            if (str[pos] == '(') {
                auto child = parseList();
                if (child != nullptr) {
                    node->addChild(child);
                }
            }
            else if (isdigit(str[pos])) {
                auto child = parseNumber();
                if (child != nullptr) {
                    node->addChild(child);
                }
            }
            else if (str[pos] == ' ') {
                auto child = parseString();
                if (child != nullptr) {
                    node->addChild(child);
                }
            }
            else {
                pos++; // skip the current character
            }
        }
        pos++; // skip the closing parenthesis
        return node;
    }
    ValueNode* parseNumber() {
        int start = pos;
        bool isFloat = false;
        while (pos < str.size() && (isdigit(str[pos]) || str[pos] == '.')) {
            if (str[pos] == '.') {
                isFloat = true;
            }
            pos++;
        }
        if (isFloat) {
            return new FloatNode(stof(str.substr(start, pos - start)));
        }
        else {
            return new IntNode(stoi(str.substr(start, pos - start)));
        }
    }
    StringNode* parseString() {
        int start = pos + 1; // skip the opening quote
        pos++;
        while (pos < str.size() && str[pos] != ' ') {
            pos++;
        }
        if (pos < str.size()) {
            pos++; // skip the closing quote
            return new StringNode(str.substr(start, pos - start - 1));
        }
        else {
            return nullptr;
        }
    }
    string str;
    int pos;
};

int main() {
    string input = '(1 2.3 'hello' (4.5 6.7) 8)';
    Parser parser(input);
    auto root = parser.parse();
    if (root != nullptr) {
        auto listNode = dynamic_cast<ListNode*>(root);
        if (listNode != nullptr) {
            for (auto child : listNode->getChildren()) {
                auto valueNode = dynamic_cast<ValueNode*>(child);
                if (valueNode != nullptr) {
                    if (auto intNode = dynamic_cast<IntNode*>(valueNode)) {
                        cout << 'IntNode: ' << intNode->getValue() << endl;
                    }
                    else if (auto floatNode = dynamic_cast<FloatNode*>(valueNode)) {
                        cout << 'FloatNode: ' << floatNode->getValue() << endl;
                    }
                    else if (auto stringNode = dynamic_cast<StringNode*>(valueNode)) {
                        cout << 'StringNode: ' << stringNode->getValue() << endl;
                    }
                }
            }
        }
        delete root;
    }
    return 0;
}

该程序使用了基于类的对象模型来表示广义表的节点,其中有 4 种类型的节点:

  • Node:表示所有节点的基类。
  • ValueNode:表示包含值的节点的基类。
  • IntNode:表示整数值的节点。
  • FloatNode:表示浮点数值的节点。
  • StringNode:表示字符串值的节点。

此外,还有一个 ListNode 类,表示列表节点。它包含一个子节点的向量,可以存储任意类型的子节点。在 Parser 类中,使用递归下降分析法来解析广义表字符串,并构建相应的节点树。在 main 函数中,程序首先创建一个 Parser 对象,然后调用 parse 方法来解析输入字符串。如果解析成功,则遍历节点树并打印每个值节点的值。最后,程序释放节点树的所有内存。

C++ 实现可以同时包含字符或小数的广义表

原文地址: https://www.cveoy.top/t/topic/oUH9 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录