Thử viết chương trình parse XML đơn giản bằng C++
C++
30
TIL
635
White

Bùi Hồng Hà viết ngày 08/05/2016

Có đứa bạn đố viết một đoạn mã parse file XML đơn giản. Yêu cầu là phải lấy được tên tag với nội dung ra.

Today I Learn: Google thấy ra thuật toán đơn giản hồi xưa học (nhưng đã quên) trong môn trình biên dịch là Recursive Decent Parser nên viết thử.

Bỏ học lâu lắm rồi nên thuật toán mình viết có phải là Recursive Decent Parser không nữa. C++ cũng gần như quên hết sạch nên nhìn đoạn mã viết ra cứ lởm lởm (thiếu hẳn cả phần mã giải phóng bộ nhớ :)).

Dù sao thì nó cũng chạy được như yêu cầu.

Chia sẻ đoạn mã GIST dưới đây nhân tiện kipalog có tính năng embeded code.

(thời gian hoàn thành: 30 phút)

/*
* Compile: g++ sparse.cpp
* Run: ./a.out
*
* Test code:
*
* <tag1><tag11>aa</tag11><tag12>bb</tag12></tag><tag21>cc</tag21>
* <tag><tag1>fdfdf</tag1></tag>
* <tag><tag1>fdfdf<tag3>fdf</tag3></tag1></tag>
*
*/
#include <iostream>
#include <stack>
#include <vector>
#include <cstdio>
#define forall(c, it) \
for(typeof((c).begin()) it = (c).begin(); it != (c).end(); ++it)
using namespace std;
enum tag_t { ROOT, OTAG, ETAG, TEXT };
class Node
{
vector<Node*> nodes;
tag_t tag_;
string val_;
public:
Node(tag_t tag, string val)
: tag_(tag),
val_(val)
{
}
tag_t getTag() const { return tag_; }
string getVal() const { return val_; }
void addNode(Node *v)
{
nodes.push_back(v);
}
const vector<Node*>& getNodes() const { return nodes; }
};
tag_t type;
int ahead;
stack<int> tag;
string match_tag()
{
string tagname;
ahead = getchar();
if (ahead == '/') {
type = ETAG;
} else {
type = OTAG;
tagname.push_back(ahead);
}
ahead = getchar();
while(ahead != '>') {
tagname.push_back(ahead);
ahead = getchar();
}
ahead = getchar();
return tagname;
}
string match_text()
{
string text;
type = TEXT;
while (isalpha(ahead)) {
text.push_back(ahead);
ahead = getchar();
}
return text;
}
string token()
{
if (ahead == '<') {
return match_tag();
}
if (isalpha(ahead)) {
return match_text();
}
return "";
}
void traverse(Node *tree)
{
const vector<Node*> &t = tree->getNodes();
forall(t, it)
traverse(*it);
printf("type (OTAG, ETAG, TEXT): %d\n", tree->getTag());
printf("%s\n", tree->getVal().c_str());
}
int main(int argc, char **argv)
{
string t;
Node *tree = new Node(ROOT, "");
stack<Node*> current_root;
current_root.push(tree);
ahead = getchar();
while(1) {
t = token();
if (t.empty()) break;
//printf("type (OTAG, ETAG, TEXT): %d\n", type);
//printf("%s\n", t.c_str());
if (type == OTAG || type == TEXT) {
Node *v = new Node(type, t);
Node *rt = (Node*)current_root.top();
rt->addNode(v);
if (type == OTAG) current_root.push(v);
} else if (type == ETAG) {
current_root.pop();
Node *v = new Node(type, t);
Node *rt = (Node*)current_root.top();
rt->addNode(v);
}
}
traverse(tree);
return 0;
}
view raw sparser.cpp hosted with ❤ by GitHub

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Bùi Hồng Hà

59 bài viết.
297 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
80 8
Bài viết tổng hợp cơ chế hoạt động của https Chút ít về chữ ký điện tử Chữ ký điện tử là cơ chế bao gồm 3 thuật toán: Thuật toán chọn một khóa...
Bùi Hồng Hà viết hơn 3 năm trước
80 8
White
45 7
Giới thiệu Gần đây thấy bản thân chém gió rất nhiều về MapReduce, Hadoop v.v nhưng chưa thấy có bài viết nào tổng hợp + giải thích cụ thể về MapRe...
Bùi Hồng Hà viết gần 3 năm trước
45 7
White
37 0
Giới thiệu Google là một công ty dẫn đầu về phần mềm xử lý Big Data. Hầu hết các phần mềm xử lý dữ liệu như Hadoop đều có nguồn gốc ý tưởng từ Goo...
Bùi Hồng Hà viết gần 3 năm trước
37 0
Bài viết liên quan
Male avatar
0 0
Constructor của lớp cha luôn được gọi trước constructor của lớp con. class Foo { public: Foo() { cout << "Base class initializing" << endl; ...
baoquocphan viết hơn 1 năm trước
0 0
White
11 1
Chức năng pattern matching trong C++ thấy nói sẽ kill (Link). Cách viết C++ do vậy sẽ thay đổi tương đối. Tự nhiên tôi thấy phải nhìn lại visitor ...
cpplover viết hơn 3 năm trước
11 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
59 bài viết.
297 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!