C++ 实现可以同时包含字符或小数的广义表
以下是一个简单的 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 方法来解析输入字符串。如果解析成功,则遍历节点树并打印每个值节点的值。最后,程序释放节点树的所有内存。
原文地址: https://www.cveoy.top/t/topic/oUH9 著作权归作者所有。请勿转载和采集!