不知道为什么提交后总是失败, 本机编译通过。 总是使用用例失败。
#include <iostream>
#include <string>
#include <list>
using namespace std;
struct XMLAttribute {
string sName; // 名称
string sText; // 内容
XMLAttribute* pNext; // 弟属性
XMLAttribute* pPre; // 兄属性
};
struct XMLNode {
int nFloor; // 层数
int nNum; // 该层第几个节点
int nAttCount; // 属性个数
int nChildCount; // 孩子节点个数
string sName; // 名称
XMLAttribute* pAttList;
XMLNode* pParentNode; // 父节点指针
XMLNode* pChildNode; // 孩子节点指针
XMLNode* pPreBrother; // 兄节点指针
XMLNode* pNextBrother; // 弟节点指针
};
void addNodeAttribute(XMLNode* pNode, XMLAttribute* pAtt) {
//printf("%s%s", "addNodeAttribute start: ", pNode->sName.c_str());
XMLAttribute* pTempAtt = pNode->pAttList;
if (!pTempAtt) {
pNode->pAttList = pAtt;
} else {
while (pTempAtt->pNext) {
pTempAtt = pTempAtt->pNext;
}
pTempAtt->pNext = pAtt;
pAtt->pPre = pTempAtt;
}
pNode->nAttCount++;
//printf("%s%d", "addNodeAttribute end: ", pNode->nAttCount);
}
void addChildNode(XMLNode* pNode, XMLNode* pChildNode) {
//printf("%s%s %s", "addChildNode start: ", pNode->sName.c_str(), pChildNode->sName.c_str());
XMLNode* pTempNode = pNode->pChildNode;
if (!pTempNode) {
pNode->pChildNode = pChildNode;
pChildNode->nFloor = pNode->nFloor + 1;
pChildNode->nNum = 1;
} else {
while (pTempNode->pNextBrother) {
pTempNode = pTempNode->pNextBrother;
}
pTempNode->pNextBrother = pChildNode;
pChildNode->pPreBrother = pTempNode;
pChildNode->nFloor = pNode->nFloor + 1;
pChildNode->nNum = pTempNode->nNum + 1;
}
pChildNode->pParentNode = pNode;
pNode->nChildCount++;
//printf("%s%d", "addChildNode end: ", pNode->nChildCount);
}
void freeNodeAttributes(XMLNode* pNode) {
//printf("%s%s", "freeNodeAttributes start: ", pNode->sName.c_str());
XMLAttribute* pTempAtt = pNode->pAttList;
// 遍历删除
while (pTempAtt) {
XMLAttribute* pDelAtt = pTempAtt;
pTempAtt = pTempAtt->pNext;
//printf("%s%s %s", "free XMLAttribute: ", pDelAtt->sName.c_str(), pDelAtt->sText.c_str());
delete pDelAtt;
pNode->nAttCount--;
}
pNode->pAttList = NULL;
//printf("%s", "freeNodeAttributes end");
}
// 释放节点内存, 不释放兄弟节点, 只对兄弟节点做双向链接
void freeNode(XMLNode* pNode) {
// 首先处理兄弟节点链表, 脱离兄弟链表
if (pNode->pNextBrother) { // 存在弟节点
if (pNode->pPreBrother) { // 存在兄节点
pNode->pPreBrother->pNextBrother = pNode->pNextBrother;
pNode->pNextBrother->pPreBrother = pNode->pPreBrother;
} else if (pNode->pParentNode) { // 存在父节点
pNode->pParentNode->pChildNode = pNode->pNextBrother;
}
}
// 处理父节点
if (pNode->pParentNode) {
pNode->pParentNode->nChildCount--;
if (pNode->pParentNode->nChildCount == 0) {
pNode->pParentNode->pChildNode = NULL;
}
}
pNode->pParentNode = NULL;
// 通过栈遍历删除字节点
list<XMLNode*> pNodesList;
pNodesList.push_front(pNode);
while (pNodesList.size()) {
XMLNode* pTempNode = pNodesList.front();
//printf("%s%s%d", "cur node: ", pTempNode->sName.c_str(), pTempNode->nChildCount);
if (!pTempNode->pChildNode) { // 无子节点出栈操作并删除
// 父节点操作
if (pTempNode->pParentNode) {
pTempNode->pParentNode->nChildCount--;
if (pTempNode->pParentNode->nChildCount == 0) {
pTempNode->pParentNode->pChildNode = NULL;
}
}
pNodesList.pop_front(); // 从栈移除
freeNodeAttributes(pTempNode);
//printf("%s%s", "free node: ", pTempNode->sName.c_str());
delete pTempNode;
pTempNode = NULL;
}
if (pTempNode) {
// 子节点入栈
XMLNode* pChildNode = pTempNode->pChildNode;
while (pChildNode) {
pNodesList.push_front(pChildNode);
pChildNode = pChildNode->pNextBrother;
}
}
}
}
string trimLeft(string& str) {
string tempStr = str;
string::size_type nLeftPos = 0;
while (str.at(nLeftPos) == ' ' && nLeftPos < str.size()) {
nLeftPos++;
}
tempStr = str.substr(nLeftPos);
return tempStr;
}
string trimRight(string& str) {
string tempStr = str;
string::size_type nRightPos = str.size() - 1;
int nCount = 0;
while (str.at(nRightPos) == ' ' && nRightPos > 0) {
nRightPos--;
nCount++;
}
if (nCount) {
tempStr = str.substr(0, str.size() - nCount);
}
return tempStr;
}
string strTrim(string& str) {
string tempStr = str;
tempStr = trimLeft(tempStr);
tempStr = trimRight(tempStr);
return tempStr;
}
enum NodeStatus {
NodeError,
NodeStart,
NodeFinished,
AttFinished
};
NodeStatus parsingSubstringToNode(string str, XMLNode* pNode) {
NodeStatus status = NodeError;
//printf("%s%s", "parsingSubstringToNode start: ", str.c_str());
if (str.at(0) == '<' && str.at(str.size() - 1) == '>') {
if (str.at(1) == '/' && str.at(str.size() - 2) != '/') {
status = NodeFinished;
pNode->sName = str.substr(2, str.size() - 3);
pNode->sName = strTrim(pNode->sName);
//printf("%s", pNode->sName.c_str());
} else if (str.at(str.size() - 2) == '/') {
status = AttFinished;
str = str.substr(1, str.size() - 2);
//printf("%s%s", "Att: ", str.c_str());
string::size_type nLeftPos = 0;
string::size_type nRightPos = str.find("=");
// 查找属性
while (nRightPos != string::npos) {
//printf("%s", str.c_str());
XMLAttribute* pAtt = new XMLAttribute;
pAtt->pNext = NULL;
pAtt->pPre = NULL;
pAtt->sName = "";
pAtt->sText = "";
addNodeAttribute(pNode, pAtt);
pAtt->sName = str.substr(nLeftPos, nRightPos);
pAtt->sName = strTrim(pAtt->sName);
str = str.substr(nRightPos + 1);
nRightPos = str.find("\"");
if (nRightPos != string::npos) {
str = str.substr(nRightPos + 1);
nRightPos = str.find("\"");
if (nRightPos != string::npos) {
pAtt->sText = str.substr(nLeftPos, nRightPos);
pAtt->sText = strTrim(pAtt->sText);
str = str.substr(nRightPos + 1);
}
}
nRightPos = str.find("=");
}
} else {
status = NodeStart;
pNode->sName = str.substr(1, str.size() - 2);
}
}
//printf("%s", "parsingSubstringToNode end");
return status;
}
XMLNode* BuildTree(string& in) {
XMLNode* pRootNode = NULL;
list<XMLNode*> nodeList;
string xmlNodeLeft = "<";
string xmlNodeRight = ">";
in = strTrim(in);
while (in.size()) {
XMLNode* pNode = new XMLNode;
pNode->sName = "";
pNode->nAttCount = 0;
pNode->nChildCount = 0;
pNode->nFloor = 0;
pNode->nNum = 0;
pNode->pAttList = NULL;
pNode->pChildNode = NULL;
pNode->pNextBrother = NULL;
pNode->pParentNode = NULL;
pNode->pPreBrother = NULL;
string::size_type nLeftPos = 0;
string::size_type nRightPos = in.find(xmlNodeRight);
XMLNode* pTempNode = nodeList.front();
if (in.at(nLeftPos) == '<' && nRightPos != string::npos) {
string tempStr = in.substr(nLeftPos, nRightPos - nLeftPos + 1);
NodeStatus status = parsingSubstringToNode(tempStr, pNode);
switch (status) {
case NodeStart: {
if (nodeList.size() > 0) {
addChildNode(pTempNode, pNode);
} else {
pRootNode = pNode;
pRootNode->nFloor = 0;
}
nodeList.push_front(pNode);
break;
}
case NodeFinished: {
if (nodeList.size() > 0) {
if (pTempNode->sName != pNode->sName) {
freeNode(pRootNode);
pRootNode = NULL;
return pRootNode;
} else {
nodeList.pop_front();
//printf("%s%s", "NodeFinished: ", pNode->sName.c_str());
freeNode(pNode);
//printf("%s", "NodeFinished");
}
}
break;
}
case AttFinished: {
if (nodeList.size() == 0) {
freeNode(pRootNode);
pRootNode = NULL;
return pRootNode;
} else {
// 赋值当前节点的属性
pTempNode->nAttCount = pNode->nAttCount;
pTempNode->pAttList = pNode->pAttList;
pNode->nAttCount = 0;
pNode->pAttList = NULL;
freeNode(pNode);
}
break;
}
}
if (status == NodeError) {
freeNode(pRootNode);
pRootNode = NULL;
return pRootNode;
}
if (nRightPos + 1 < in.size()) {
in = in.substr(nRightPos + 1);
in = trimLeft(in);
} else {
in = "";
}
} else {
freeNode(pRootNode);
pRootNode = NULL;
return pRootNode;
}
}
return pRootNode;
}
string getTreeString(XMLNode* pNode) {
string str = "";
string sNewLine = "\r\n";
string sTab = "\t";
// 输出XML解析字符串
// 通过栈遍历
list<XMLNode*> pNodesList;
pNodesList.push_front(pNode);
while (pNodesList.size()) {
XMLNode* pTempNode = pNodesList.front();
pNodesList.pop_front();
// 输出节点名
for (int i = 0; i < pTempNode->nFloor; i++) {
str += sTab;
}
str += pTempNode->sName;
if (pTempNode->nFloor > 0) {
char sNum[10];
sprintf(sNum, "%d", pTempNode->nNum);
str += " " + string(sNum);
}
str += sNewLine;
// 输出属性
XMLAttribute* pTempAtt = pTempNode->pAttList;
while (pTempAtt) {
for (int i = 0; i < pTempNode->nFloor + 1; i++) {
str += sTab;
}
str += pTempAtt->sName + ":" + pTempAtt->sText + sNewLine;
pTempAtt = pTempAtt->pNext;
}
// 字节点入栈
XMLNode* pChildNode = pTempNode->pChildNode;
// 首先逆序
while (pChildNode && pChildNode->pNextBrother) {
pChildNode = pChildNode->pNextBrother;
}
while (pChildNode) {
pNodesList.push_front(pChildNode);
pChildNode = pChildNode->pPreBrother;
}
}
return str;
}
string ParsingXML(string str)
{
//printf("%s", "ParsingXML start");
string result = "";
string in = str;
string xmlVersionLeft = "<?";
string xmlVersionRight = "?>";
// 首先查找XML版本并移除
string::size_type nLeftPos = in.find(xmlVersionLeft);
string::size_type nRightPos = 0;
if (nLeftPos != string::npos) {
nRightPos = in.find(xmlVersionRight);
if (nRightPos == string::npos) {
result = "Invalid XML string.";
return result;
} else {
nRightPos += xmlVersionRight.size();
in = in.substr(nRightPos);
}
}
XMLNode* pRootNode = BuildTree(in);
result = getTreeString(pRootNode);
// 清理树
freeNode(pRootNode);
//printf("%s", "ParsingXML end");
return result;
}
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
string in = "<?xml version=\"1.0\" ?><Books><Book><Name = \"The C++ Programming Language\" Author=\"Bjarne Stroustrup\" /></Book><Book><Name = \"Effective C++\" Author = \"Scott Meyers\" /></Book></Books>";
string out = ParsingXML(in);
printf("%s", out);
return 0;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。