CSP202006-3 Markdown渲染器

CSP202006-3 Markdown渲染器

题目

题目可以在CSP官网中查看

算法思想

哈哈哈,又是一个模拟题。虽然题目看上去很长,但是只要耐下心来,一点一点将不同的内容类型区别开即可,很好理解题目的意思之后,还是可以感觉到难度不是很大的。

通过题目要求可以将输入分为三类:普通段落、项目列表项、项目列表嵌套项,这三类皆有特定的开头符号,可以根据特定的开头符号要求即可完成判断。

题目要求的整个处理过程很复杂,一遍遍历完成很容易想乱掉,所以可以把处理过程分成两部分:(1)预处理过程:这个过程中,把输入分成三类:普通段落、项目列表项、项目列表嵌套项,这个过程同时把相同段落/列表项的多行输入拼接起来,打上类别标记后存入vector管理。(2)渲染过程:这个过程中,遍历vector中存储的内容,因为预处理时已经把内容都划分好了,所以思路很清晰。段落和列表间隔时插入空行、段内/列表项内按终端每行容量处理换行即可。特别注意的就是:因为题目中没有给出输入的行数,需要自行处理。根据提示,我们用getline(cin,str)形式输入,通过检测文件末尾来跳出循环。

结果

在这里插入图片描述

完整代码

代码中含有较清晰的注释,按照上面两个部分:预处理过程、渲染过程一步一步即可完成该模拟题目,具体的代码如下:

#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int w;
struct Markdown
{
	int type;
	string s;
};
vector<Markdown>article;
bool isspace(string str)
{
	int i;
	for (i = 0; i < str.length(); i++)
		if (str[i] != ' ') return false;
	return true;
}
string stand(string str)
{
	int length = str.length();
	int pos1 = 0;
	int pos2 = length - 1;
	while (str[pos1] == ' ') pos1++;
	while (str[pos2] == ' ') pos2--;
	str = str.substr(pos1, pos2 - pos1 + 1);
	return str;
}
int main()
{
	ios::sync_with_stdio(false);
	cin >> w;
	string str;
	while (getline(cin, str))
	{
		if (!isspace(str)) break; //跳过刚开始的空行
	}
	//项目列表
	if (str.length() >= 2 && str.substr(0, 2) == "* ") //substr(0,2):截取str的前两位
	{
		article.push_back({ 1,stand(str.substr(2)) }); //substr(2):抛去str的前两位
	}
	//段落
	else
	{
		article.push_back({ 2,stand(str) });
	}
	bool check = false;
	while (getline(cin, str))
	{
		if (isspace(str))
		{
			check = true;
		}
		else
		{
			//上一行是空行,这一行非空,直接插入
			if (check)
			{
				check = false;
				//项目列表
				if (str.length() >= 2 && str.substr(0, 2) == "* ") //substr(0,2):截取str的前两位
				{
					article.push_back({ 1,stand(str.substr(2)) }); //substr(2):抛去str的前两位
				}
				//段落
				else
				{
					article.push_back({ 2,stand(str) });
				}
			}
			//上一行不是空行,判断是否是同一段或者同一项目列表
			else
			{
				Markdown& temp = article.back();
				//项目列表情况
				if (temp.type == 1 || temp.type == 3)
				{
					//项目列表项内容,直接相连
					if (str.length() >= 2 && str.substr(0, 2) == "  ")
						temp.s = temp.s + " " + stand(str.substr(2));
					//项目列表嵌套项
					else if (str.length() >= 2 && str.substr(0, 2) == "* ")
						article.push_back({ 3,stand(str.substr(2)) });
					//新的段落
					else
						article.push_back({ 2,stand(str) });
				}
				//段落情况
				else if (temp.type == 2)
				{
					//新开启项目列表项
					if (str.length() >= 2 && str.substr(0, 2) == "* ")
					{
						article.push_back({ 1,stand(str.substr(2)) });
					}
					//本段落内容,直接连接
					else
						temp.s = temp.s + " " + stand(str);
				}
			}
		}
	}
	long long ans = 0;
	int i;
	for (i = 0; i < article.size(); i++)
	{
		string &str = article[i].s;
		//新的段落或者新的项目列表,并且不是第一个,则空一行
		if (article[i].type != 3 && i > 0) ans++;
		//对项目列表进行处理
		if (article[i].type != 2)
		{
			//空项目
			if (str.size() == 0)
				ans++;
			//不是空项目
			else
			{
				for (int j = 0; j < str.length(); j = j + (w - 3))
				{
					//换行时,去掉前导空格
					while (j < str.length() && str[j] == ' ')
						j++;
					ans++;
				}
			}
		}
		//对段落进行处理
		else if(article[i].type == 2)
		{
			for (int j = 0; j < str.length(); j = j + w)
			{
				while (j < str.length() && str[j] == ' ')
					j++;
				ans++;
			}
		}
	}
	cout << ans << endl;
	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值