#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>typedef long long LL;
typedef struct Mark Mark;
// 用链表实现一个栈
struct Mark {
Mark* prev; // 上一个节点
char* type; // 节点名称
};
bool readln(char* str);
bool invoke();
void pushItem(char* name, int start, int end);
char* popItem();
int indexOfAny(const char* src, int start, int end, char* items);
char* indexOfInRange(char* src, int length, const char* that);
bool strEquals(char* src, int length, const char* that);
bool isSelfClosing(char* src, int start, int end);
char distId[1010] = {'i', 'd', '=', '"'}; // 目标 ID
char input[1001]; // 单行输入
char content[3001]; // 结果
bool hit = false; // 判断是否找到了 id 为指定字符串的标签
Mark* linkedList = NULL;
int main() {
readln(distId + 4);
int idLength = (int) strlen(distId);
distId[idLength] = '"';
distId[idLength + 1] = '\0';
if (!invoke()) printf("duo lao a cjmm");
else if (!hit) printf("duo lao a cjjj");
else {
bool isNotBlank = false;
for (int i = 0; content[i] != '\0'; ++i) {
switch (content[i]) {
case ' ': case '\t': case '\n':
break;
default:
isNotBlank = true;
goto skipFor;
}
}
skipFor:
if (!isNotBlank) printf("QAQ");
else {
int start = 0;
for (; content[start] != '\0'; ++start) {
if (content[start] != '\n') break;
}
printf("%s", content + start);
}
}
return 0;
}
bool invoke() {
bool skip = false;
char* contentStartFlag = NULL;
int contentStartIndex;
int contentLength = 0;
while (readln(input)) {
int length = (int) strlen(input);
int i = 0;
if (skip) {
LL endIndex = (LL) (strstr(input, "-->") - input);
if (endIndex < 0) continue;
i = (int) (endIndex + 3);
}
while (i != length) {
LL tmp = (LL) (strchr(input + i, '<') - input);
if (tmp < 0) break;
int startIndex = (int) tmp;
// 判断是否是注释
if (startIndex + 3 < length && input[startIndex + 1] == '!' && input[startIndex + 2] == '-' && input[startIndex + 3] == '-') {
LL endIndex = (LL) (strstr(input + i, "-->") - input);
if (endIndex < 0) { // endIndex < 0 表明注释不在一行内结束
skip = true;
break;
}
i = (int) (endIndex + 3); // 如果在一行内结束就跳过注释中的内容
continue;
}
int endIndex = (int) (strchr(input + startIndex + 1, '>') - input);
if (input[startIndex + 1] == '/') { // 如果是结束标记
char* oldName = popItem();
if (oldName == NULL) return false; // 没有开始标记,结构错误
bool isEquals = strEquals(input + startIndex + 2, endIndex - startIndex - 2, oldName);
bool isContent = oldName == contentStartFlag;
free(oldName);
if (!isEquals) return false; // 开始标记和结束标记不对应,结构错误
if (isContent) {
contentStartFlag = NULL;
int len = startIndex - contentStartIndex;
memcpy(content + contentLength, input + contentStartIndex, sizeof(char) * len);
contentLength += len;
}
} else { // 如果是开始标记
int nameEndIndex = indexOfAny(input, startIndex + 1, endIndex + 1, " >");
bool selfClosing = input[endIndex - 1] == '/' || isSelfClosing(input, startIndex + 1, nameEndIndex);
if (!selfClosing) pushItem(input, startIndex + 1, nameEndIndex);
char* idIndex = indexOfInRange(input + startIndex + 1, endIndex - startIndex - 1, distId);
if (idIndex != NULL) { // 如果找到了对应的 ID
hit = true;
if (!selfClosing) {
contentStartFlag = linkedList->type;
contentStartIndex = endIndex + 1;
}
}
}
i = endIndex + 1;
}
if (contentStartFlag != NULL) {
int len = length - contentStartIndex;
memcpy(content + contentLength, input + contentStartIndex, sizeof(char) * len);
contentLength += len;
contentStartIndex = 0;
content[contentLength++] = '\n';
}
}
content[contentLength] = '\0';
return !skip && linkedList == NULL;
}
/** 读取一行数据 */
bool readln(char* str) {
memset(str, 0, sizeof(char) * 1000);
char *flag = gets(str);
return flag != NULL;
}
// 在字符串的指定范围内查找 items 中字符最早出现的那一个的下标
int indexOfAny(const char* src, int start, int end, char* items) {
for (int i = start; i != end; ++i) {
char value = src[i];
char* dist = strchr(items, value);
if (dist != NULL) return i;
}
return -1;
}
// 推送一个节点到栈中
void pushItem(char* name, int start, int end) {
Mark* newItem = malloc(sizeof(Mark));
newItem->prev = linkedList;
int length = end - start;
newItem->type = malloc(sizeof(char) * (length + 1));
memcpy(newItem->type, name + start, sizeof(char) * length);
newItem->type[length] = '\0';
linkedList = newItem;
}
// 弹出栈顶元素
char* popItem() {
if (linkedList == NULL) return NULL;
Mark* oldItem = linkedList;
char* oldType = oldItem->type;
linkedList = oldItem->prev;
free(oldItem);
return oldType;
}
// 在指定范围内比较字符串是否相等
bool strEquals(char* src, int length, const char* that) {
char tmp = src[length];
src[length] = '\0';
bool result = strcmp(src, that) == 0;
src[length] = tmp;
return result;
}
// 在指定范围内查找字符串
char* indexOfInRange(char* src, int length, const char* that) {
char tmp = src[length];
src[length] = '\0';
char* result = strstr(src, that);
src[length] = tmp;
return result;
}
const char SELF_LIST[][11] = {"br", "hr", "img", "input", "link", "meta", "area"};
// 判断是否是自闭合标签
bool isSelfClosing(char* src, int start, int end) {
src = src + start;
int length = end - start;
for (int i = 0; i != 7; ++i) {
if (strEquals(src, length, SELF_LIST[i]))
return true;
}
return false;
}