~cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int bool;
#define FALSE 0
#define TRUE 1
#define INPUT_BUFFUR 255
typedef struct StructReadBlock
{
char* name;
char* contents;
int nextBlockNumber;
bool isOneTable;
struct StructReadBlock** nextBlocks;
}SReadBlock;
const char DEBUG_TEXT[] = "<zeropage>\n <studies>\n <cpp>\n 이상규\n <participants>\n <name>김상섭</name>\n <name>김민경</name>\n <name>송수생</name>\n <name>조현태</name>\n </participants>\n </cpp>\n <java>\n 이선호\n <participants>\n <name>김민경</name>\n <name>송수생</name>\n <name>조현태</name>\n </participants>\n </java>\n <mfc>\n <participants/>\n </mfc>\n </studies>\n</zeropage>\n";
SReadBlock* CreateNewBlock(const char* name, const char* contents)
{
SReadBlock* newBlock = (SReadBlock*)malloc(sizeof(SReadBlock));
if (NULL == name)
newBlock->name = NULL;
else
{
newBlock->name = (char*)malloc(sizeof(char) * (strlen(name) + 1));
strcpy(newBlock->name, name);
}
if (NULL == contents)
newBlock->contents = NULL;
else
{
newBlock->contents = (char*)malloc(sizeof(char) * (strlen(contents) + 1));
strcpy(newBlock->contents, contents);
}
newBlock->nextBlockNumber = 0;
newBlock->nextBlocks = NULL;
newBlock->isOneTable = FALSE;
return newBlock;
}
void AddNewTail(SReadBlock* head, SReadBlock* tail)
{
if (NULL != head)
{
SReadBlock** newNextBlocks = (SReadBlock**)malloc(sizeof(SReadBlock*) * (head->nextBlockNumber + 1));
memcpy(newNextBlocks, head->nextBlocks, sizeof(SReadBlock*) * head->nextBlockNumber);
newNextBlocks[head->nextBlockNumber] = tail;
free(head->nextBlocks);
head->nextBlocks = newNextBlocks;
++head->nextBlockNumber;
}
}
const char* CreateTree(SReadBlock* headBlock, const char* readData)
{
SReadBlock* myPoint = NULL;
while(0 != *readData)
{
if ('<' == *readData)
{
++readData;
if ('/' == *readData)
{
readData = strchr(readData, '>');
++readData;
break;
}
else if (NULL == myPoint)
{
const char* nameEndPoint = strchr(readData, '>');
char* textBuffur = (char*)malloc(sizeof(char) * (nameEndPoint - readData + 1));
strncpy(textBuffur, readData, nameEndPoint - readData);
textBuffur[nameEndPoint - readData] = 0;
myPoint = CreateNewBlock(textBuffur, NULL);
AddNewTail(headBlock, myPoint);
free(textBuffur);
if ('/' == myPoint->name[strlen(myPoint->name) - 1])
{
myPoint->name[strlen(myPoint->name) - 1] = 0;
myPoint->isOneTable = TRUE;
return nameEndPoint + 1;
}
readData = CreateTree(myPoint, nameEndPoint + 1);
}
else
readData = CreateTree(myPoint, --readData);
}
else
{
if (' ' == *readData || '\n' == *readData)
{
while(' ' == *readData || '\n' == *readData)
++readData;
}
else
{
const char* contentsEndPoint = strchr(readData, '<');
char* textBuffur = (char*)malloc(sizeof(char) * (contentsEndPoint - readData + 1));
strncpy(textBuffur, readData, contentsEndPoint - readData);
textBuffur[contentsEndPoint - readData] = 0;
myPoint = CreateNewBlock(NULL, textBuffur);
AddNewTail(headBlock, myPoint);
free(textBuffur);
return contentsEndPoint;
}
}
}
return readData;
}
void ShowTree(SReadBlock* showBlock, int tabCount, bool* isLastContents)
{
int i = 0;
/* 일반 명령어의 출력 */
if (NULL != showBlock->name)
{
*isLastContents = FALSE;
printf("\n");
for (i = 0; i < tabCount; ++i)
printf("\t");
/* 단일 항목인가 아닌가. */
if (showBlock->isOneTable)
{
printf("<%s/>\n", showBlock->name);
}
else
{
printf("<%s>", showBlock->name);
for (i = 0; i < showBlock->nextBlockNumber; ++i)
ShowTree(showBlock->nextBlocks[i], tabCount + 1, isLastContents);
if (FALSE == *isLastContents)
{
printf("\n");
for (i = 0; i < tabCount; ++i)
printf("\t");
}
printf("</%s>", showBlock->name);
}
}
/* 내용의 출력 */
else if (NULL != showBlock->contents)
{
*isLastContents = TRUE;
printf("%s", showBlock->contents);
}
/* 단순한 연결의 경우 */
else
{
*isLastContents = FALSE;
for (i = 0; i < showBlock->nextBlockNumber; ++i)
ShowTree(showBlock->nextBlocks[i], tabCount, isLastContents);
}
}
void SuchAllSameNamePoint(const char* name, SReadBlock* suchBlock, SReadBlock*** suchedBlocks)
{
int i = 0;
SReadBlock** newBlocks = NULL;
for (i = 0; i < suchBlock->nextBlockNumber; ++i)
{
if (NULL != suchBlock->nextBlocks[i]->name && 0 == strcmp(suchBlock->nextBlocks[i]->name, name))
{
/* 새로 검색된 내용을 추가합니다. */
newBlocks = (SReadBlock**)malloc(sizeof(SReadBlock*) * ((int)(**suchedBlocks) + 2));
memcpy(newBlocks, *suchedBlocks, sizeof(SReadBlock*) * ((int)(**suchedBlocks) + 1));
*newBlocks = (SReadBlock*)(((int)**suchedBlocks) + 1);
newBlocks[(int)(*newBlocks)] = suchBlock->nextBlocks[i];
free(*suchedBlocks);
*suchedBlocks = newBlocks;
}
}
for (i = 0; i < suchBlock->nextBlockNumber; ++i)
{
SuchAllSameNamePoint(name, suchBlock->nextBlocks[i], suchedBlocks);
}
}
void printSuchPoints(const char* query, SReadBlock* suchBlock)
{
int i = 0;
bool isLastContents = FALSE;
const char* suchEndPoint = NULL;
char* textBuffur = NULL;
SReadBlock** suchedBlocks = NULL;
if (0 == *query)
{
ShowTree(suchBlock, 0, &isLastContents);
}
else if ('/' == *query)
{
/* 단어의 끝을 찾습니다. */
query = query + 1;
suchEndPoint = strchr(query + 1, '/');
if (NULL == suchEndPoint)
suchEndPoint = query + strlen(query);
if ('/' == *query)
{
query = query + 1;
suchedBlocks = (SReadBlock**)malloc(sizeof(SReadBlock*));
*suchedBlocks = (SReadBlock*)0;
textBuffur = (char*)malloc(sizeof(char) * (suchEndPoint - query + 1));
strncpy(textBuffur, query, suchEndPoint - query);
textBuffur[suchEndPoint - query] = 0;
SuchAllSameNamePoint(textBuffur, suchBlock, &suchedBlocks);
free(textBuffur);
for (i = 0; i < (int)(*suchedBlocks); ++i)
printSuchPoints(suchEndPoint, suchedBlocks[i + 1]);
}
else
{
for (i = 0; i < suchBlock->nextBlockNumber; ++i)
{
if (0 == strncmp(suchBlock->nextBlocks[i]->name, query, suchEndPoint - query - 1))
printSuchPoints(suchEndPoint, suchBlock->nextBlocks[i]);
}
}
}
}
void FreeMyMemorys(SReadBlock* suchBlock)
{
int i = 0;
for ( ; i < suchBlock->nextBlockNumber; ++i)
{
FreeMyMemorys(suchBlock->nextBlocks[i]);
free(suchBlock->nextBlocks[i]);
}
free(suchBlock->name);
free(suchBlock->contents);
}
void main()
{
const char* readData = DEBUG_TEXT;
SReadBlock* rootBlock = CreateNewBlock(NULL, NULL);
const char query[INPUT_BUFFUR];
bool isLastContents = FALSE;
printf("쿼리문을 입력하세요.\n>>");
scanf("%s", query);
CreateTree(rootBlock, readData);
if (NULL != strchr(query, '/'))
{
if (0 == strncmp((*(rootBlock->nextBlocks))->name, query, strchr(query, '/') - query - 1))
{
printSuchPoints(strchr(query, '/'), *(rootBlock->nextBlocks));
}
}
else
{
if (0 == strcmp(query, (*(rootBlock->nextBlocks))->name))
{
ShowTree(rootBlock, 0, &isLastContents);
}
}
FreeMyMemorys(rootBlock);
printf("\n");
system("PAUSE");
}