CCF CSP 201509-3.模板生成系统

问题描述

  成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同的数据记录,但是页面的基本结构是相同的。例如,对于展示用户信息的页面,当用户为 Tom 时,网页的源代码是
img

  而当用户为 Jerry 时,网页的源代码是
img

  这样的例子在包含动态内容的网站中还有很多。为了简化生成网页的工作,成成觉得他需要引入一套模板生成系统。
  模板是包含特殊标记的文本。成成用到的模板只包含一种特殊标记,格式为 {{ VAR }},其中 VAR 是一个变量。该标记在模板生成时会被变量 VAR 的值所替代。例如,如果变量 name = “Tom”,则 {{ name }} 会生成 Tom。具体的规则如下:
  ·变量名由大小写字母、数字和下划线 (_) 构成,且第一个字符不是数字,长度不超过 16 个字符。
  ·变量名是大小写敏感的,Name 和 name 是两个不同的变量。
  ·变量的值是字符串。
  ·如果标记中的变量没有定义,则生成空串,相当于把标记从模板中删除。
  ·模板不递归生成。也就是说,如果变量的值中包含形如 {{ VAR }} 的内容,不再做进一步的替换。

输入格式

  输入的第一行包含两个整数 m, n,分别表示模板的行数和模板生成时给出的变量个数。
  接下来 m 行,每行是一个字符串,表示模板。
  接下来 n 行,每行表示一个变量和它的值,中间用一个空格分隔。值是字符串,用双引号 (“) 括起来,内容可包含除双引号以外的任意可打印 ASCII 字符(ASCII 码范围 32, 33, 35-126)。

输出格式

  输出包含若干行,表示模板生成的结果。

样例输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
11 2
<!DOCTYPE html>
<html>
<head>
<title>User {{ name }}</title>
</head>
<body>
<h1>{{ name }}</h1>
<p>Email: <a href="mailto:{{ email }}">{{ email }}</a></p>
<p>Address: {{ address }}</p>
</body>
</html>
name "David Beckham"
email "david@beckham.com"

样例输出

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<title>User David Beckham</title>
</head>
<body>
<h1>David Beckham</h1>
<p>Email: <a href="mailto:david@beckham.com">david@beckham.com</a></p>
<p>Address: </p>
</body>
</html>

评测用例规模与约定

  0 ≤ m ≤ 100
  0 ≤ n ≤ 100
  输入的模板每行长度不超过 80 个字符(不包含换行符)。
  输入保证模板中所有以{{ 开始的子串都是合法的标记,开始是两个左大括号和一个空格,然后是变量名,结尾是一个空格和两个右大括号。
  输入中所有变量的值字符串长度不超过 100 个字符(不包括双引号)。
  保证输入的所有变量的名字各不相同。


分析:

本题可以采用正则表达式或者子串查找两种方式求解。这里主要采用子串查找来求解。

  • C++版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <map>
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;

int main() {
int m, n;
cin >> m >> n;
// 吸收末尾的换行符
getchar();

// 存储模板内容
string tpl;
string line;
for (int i = 0; i < m; i++) {
getline(cin, line);
tpl += line + '\n';
}

// 使用map存储变量名和变量的值
map<string, string> dict;
string key, value, str;
while (n--) {
getline(cin, str);
int index = str.find(' ');
key = str.substr(0, index);
// 去掉首尾的双引号
dict[key] = str.substr(index + 2, str.size() - (index + 2) - 1);
}

for (int i = 0; i < tpl.size();) {
// 从第i个位置开始,向后寻找子串第一次出现的位置,若未找到该子串,则返回string::npos
int start = tpl.find("{{ ", i);
if (start == string::npos) {
break;
}
int end = tpl.find(" }}", start + 3);
if (end == string::npos) {
break;
}
// 获取变量名
key = tpl.substr(start + 3, end - start - 3);
// 若变量为定义,则生成空串
value = dict.count(key) ? dict[key] : "";
// 替换模板变量
tpl = tpl.replace(start, end - start + 3, value);
// 因为模板不递归生成,故跳过替换后的那段字符串
i = start + value.size();
}
cout << tpl << endl;
return 0;
}
  • Java版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {

public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 保存输入的数据
String[] sArr = scan.nextLine().split(" ");
int m = Integer.parseInt(sArr[0]);
int n = Integer.parseInt(sArr[1]);

StringBuilder sb = new StringBuilder();
for (int i = 0; i < m; i++) {
sb.append(scan.nextLine()).append("\n");
}

Map<String, String> map = new HashMap<>();
for (int i = 0; i < n; i++) {
String line = scan.nextLine();
int index = line.indexOf(' ');
String key = line.substring(0, index);
// 去掉首尾的双引号
String value = line.substring(index + 2, line.length() - 1);
map.put(key, value);
}
scan.close();

for (int i = 0; i < sb.length();) {
// 从第i个位置开始,向后寻找子串第一次出现的位置
int start = sb.indexOf("{{ ", i);
if (start == -1) {
break;
}
int end = sb.indexOf(" }}", start + 3);
if (end == -1) {
break;
}
// 获取变量名
String key = sb.substring(start + 3, end);
// 若变量为定义,则生成空串
String value = map.containsKey(key) ? map.get(key) : "";
// 替换模板变量
sb.replace(start, end + 3, value);
// 因为模板不递归生成,故跳过替换后的那段字符串
i = start + value.length();
}
System.out.println(sb.toString());

/*//正则表达式的解法,得分为90,显示运行错误
// 使用正则表达式替换模板变量
Pattern p = Pattern.compile("\\{\\{ \\D\\w{0,15} \\}\\}");
Matcher matcher = p.matcher(sb);
StringBuffer sbuff = new StringBuffer();
while (matcher.find()) {
String var = matcher.group();
String key = var.substring(3, var.length() - 3);
matcher.appendReplacement(sbuff, map.containsKey(key) ? map.get(key) : "");
}
matcher.appendTail(sbuff);
System.out.println(sbuff.toString());*/
}
}

----------本文结束感谢您的阅读----------
坚持原创技术分享,您的支持将鼓励我继续创作!