CSP-大模拟:Markdown渲染器

原题链接:https://www.acwing.com/problem/content/description/3292/

# include <iostream>
# include <vector>
# define BLANK 0 //空行
# define PARA 1	//文本
# define PROJ 2 //项目
# define PROJ_NEXT 3 
using namespace std;

const int N = 10 + 20 * 1024 * 1024;
char str[N];
vector<string> strs;
int w, ans = -1; 
int cur = -1, pre = -1; // 存上一个处理的行的类型

// 判断空行
bool is_blank(string& s) {
    for (auto c: s)
        if (c != ' ') return false;
    return true;
}

// 判断str的类型
int get_type(string& str) {
    if (is_blank(str)) return BLANK;
    if (str.size() >= 2 && str[0] == '*' && str[1] == ' ') return PROJ;
    if ((pre == PROJ || pre == PROJ_NEXT) && str.size() >= 2 && str[0] == ' ' && str[1] == ' ') return PROJ_NEXT;
    // 前三种都不是的话,就是文本了
    return PARA;
}

// 统计行数 传入一个string,w。返回这个string占的行数
int wc(string& s, int w) {
    int res = 0;
    for (int i = 0; i < s.size(); i ++ ) {
        // 开头的空格自动删除
        if (s[i] == ' ') continue;
        // 统计一行
        int j = i + 1;
        while (j < s.size() && j - i + 1 <= w) j ++ ;
        res ++ ;
        i = j - 1;
    }
    return max(res, 1);
}

// 去掉str前面和后边的连续空格
string trim(string s)
{
    int i = 0, j = s.size() - 1;
    while (i <= j && s[i] == ' ') i ++ ;
    while (i <= j && s[j] == ' ') j -- ;
    if (i > j) return "";
    return s.substr(i, j - i + 1);
}

// 连行成段
void fix_para(int& i) {
    // 与之前的PARA或PROJ隔开
    ans ++;
    pre = PARA;
    string obj = trim(strs[i++]);
    while (i < strs.size()) {
        int t = get_type(strs[i]);
        if (t != PARA) break;
        pre = PARA;
        // 行与行合并中间+空格
        obj += " " + trim(strs[i]);
        i ++;
    }
    // cout << obj << endl;
    ans += wc(obj, w);
}

// 处理一个 ·
void fix_proj(int& i) {
    if(pre != PROJ && pre != PROJ_NEXT) ans ++; // 若之前是项目则无需换行
    pre = PROJ;
    //在渲染一个项目前,先把这个项目的各个文本行首的两个空格字符或星号空格字符去掉。
    string obj = trim(strs[i ++].substr(2));
    while (i < strs.size()) {
        int t = get_type(strs[i]);
        if (t != PROJ_NEXT) break;
        pre = t;
        obj += ' ' + trim(strs[i].substr(2));
        i ++;
    }
    // cout << obj << endl;
    // w发生变化
    ans += wc(obj, w - 3);
}


int main()
{
    scanf("%d", &w);
    getchar(); // 处理w之后的回车。
    
    while (fgets(str, N, stdin)) 
    {
        strs.push_back(str);// 把每一行存到str中,然后放入strs结构体
        if (strs.back().back() == '\n') strs.back().pop_back();  // 删除回车
    }
    
    int i = 0;

    // 遍历每一行的字符串
    while (i < strs.size()) {
        cur = get_type(strs[i]);
        // printf("i=%d, cur=%d\n", i, cur);
        if (cur == BLANK) i ++, pre = BLANK;
        else if (cur == PARA) fix_para(i);
        else if (cur == PROJ) fix_proj(i);
        // printf("ans=%d\n",ans);
    }

    printf("%d", ans); 
    
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值