【CCCC】L3-019 代码排版 (30分),大模拟

简介: 【CCCC】L3-019 代码排版 (30分),大模拟

problem

L3-019 代码排版 (30分)
某编程大赛中设计有一个挑战环节,选手可以查看其他选手的代码,发现错误后,提交一组测试数据将对手挑落马下。为了减小被挑战的几率,有些选手会故意将代码写得很难看懂,比如把所有回车去掉,提交所有内容都在一行的程序,令挑战者望而生畏。

为了对付这种选手,现请你编写一个代码排版程序,将写成一行的程序重新排版。当然要写一个完美的排版程序可太难了,这里只简单地要求处理C语言里的for、while、if-else这三种特殊结构,而将其他所有句子都当成顺序执行的语句处理。输出的要求如下:

默认程序起始没有缩进;每一级缩进是 2 个空格;
每行开头除了规定的缩进空格外,不输出多余的空格;
顺序执行的程序体是以分号“;”结尾的,遇到分号就换行;
在一对大括号“{”和“}”中的程序体输出时,两端的大括号单独占一行,内部程序体每行加一级缩进,即:
{
程序体
}
for的格式为:
for (条件) {
程序体
}
while的格式为:
while (条件) {
程序体
}
if-else的格式为:
if (条件) {
程序体
}
else {
程序体
}
输入格式:
输入在一行中给出不超过 331 个字符的非空字符串,以回车结束。题目保证输入的是一个语法正确、可以正常编译运行的 main 函数模块。

输出格式:
按题面要求的格式,输出排版后的程序。

输入样例:
int main() {int n, i; scanf("%d", &n);if( n>0)n++;else if (n<0) n--; else while(n<10)n++; for(i=0; i<n; i++ ){ printf("n=%d\n", n);}return 0; }
输出样例:
int main()
{
int n, i;
scanf("%d", &n);
if ( n>0) {

n++;

}
else {

if (n<0) {
  n--;
}
else {
  while (n<10) {
    n++;
  }
}

}
for (i=0; i<n; i++ ) {

printf("n=%d\n", n);

}
return 0;
}

  • 给出一行代码,要求排版成整篇
  • 缩进2空格,花括号不换行,每行封号结尾

solution

  • 去掉main单独输出(括号内可能有空格,WA1),剩下的按照每行的内容可以简单分为3类,遇到花括号(增加或减少缩进),逻辑判断(for,while,if+()一类,else一类),普通语句(以封号;结尾)。
  • 处理逻辑判断的时候有2个坑点,第一个坑点是考虑条件()内可能也有(),第二个是单句前后要加上花括号。其他的缩进修改和普通语句都比较简单直接处理就可。
#include<bits/stdc++.h>
using namespace std;

//判断语句块类型
int judge(string dat, int i){
    //WA3:当前位置是if并且不是在字符串内
    if(dat.find("if", i)==i && (dat[i+2]==' '||dat[i+2]=='('))return 2;
    if(dat.find("for",i)==i && (dat[i+3]==' ' ||dat[i+3]=='('))return 3;
    if(dat.find("while",i)==i && (dat[i+5]==' '||dat[i+5]=='('))return 5;
    if(dat.find("else",i)==i && dat[i+4]==' ')return 4;
    return 0;//普通语句
}
//输出前删除多余空格, 并输出当前对应的空格
void erase_space(string dat,int &i){while(dat[i]==' ')i++;}
void print_space(int sp){for(int i=0;i<sp;i++)putchar(' ');}

int main(){
    string dat;  getline(cin,dat);
    
    //处理int main()  找i和)输出
    int l = dat.find('i',0), r = dat.find(')',0);
    cout<<dat.substr(l,r-l+1)<<"\n{\n";
    
    //处理其他,按照行分类
    int tmp, space = 2;//语句类型,空格数
    int flag, debt=0;//单句标记,层数(补全缺少的})
    for(int i = dat.find('{')+1,j=0,k; i < dat.size(); ){
        erase_space(dat,i);//删除每行前的空格
        if(dat[i]=='{' || dat[i]=='}'){
            if(dat[i]=='{'){
                print_space(space);
                printf("{\n");
                space += 2;
                i++;
                continue;
            }else{
                space -= 2;
                print_space(space);
                printf("}\n");
                i++;
                if(space==0)break;//main的}输完就结束了
                
                //【重复】单句特判
                erase_space(dat,i);
                while(debt && judge(dat,i)!=4){
                    space -= 2;
                    print_space(space);
                    printf("}\n");
                    debt--;
                }
            }
        }else if((tmp=judge(dat,i))){
            print_space(space);
            //处理for,while,if,+()或者else
            if(tmp==4){
                printf("else");
                k = i+3;
            }else{
                cout<<dat.substr(i,tmp)<<" ";
                i += tmp;
                erase_space(dat, i);
                //考虑if()中也有()条件的情况
                k = i; int t = 0;
                while(1){
                    if(dat[k]=='(')t++;
                    if(dat[k]==')')t--;
                    if(!t)break;
                    k++;
                }
                cout<<dat.substr(i,k-i+1);
            }
            //预处理{}的内容,考虑单句特判
            int m = k+1;
            erase_space(dat,m);
            if(dat[m] != '{'){//单句标记
                printf(" {\n");
                flag = 1;
                debt++;
                i = m;
            }else{
                printf(" {\n");
                flag = 0;
                i = m+1;
            }
            space += 2;
        }else{//普通语句
            int ed = dat.find(';', i);
            print_space(space);
            cout<<dat.substr(i,ed-i+1)<<"\n";
            i = ed+1;
            
            //这是单句内的语句
            if(flag && debt){
                space -= 2;
                print_space(space);
                printf("}\n");
                debt--;
                
                //【重复】单句特判
                erase_space(dat,i);
                while(debt && judge(dat,i)!=4){
                    space -= 2;
                    print_space(space);
                    printf("}\n");
                    debt--;
                }
            }
        }
    }
    return 0;
}
目录
相关文章
|
3月前
【Latex 格式】Markdown或者LaTeX在单个字母上加一横、一点、两点、三角
Markdown或者LaTeX在单个字母上加一横、一点、两点、三角
252 8
|
6月前
|
编解码 前端开发 容器
CSS常见的面试题以及答案 500字以上
【4月更文挑战第1天】 CSS常见的面试题以及答案 500字以上
34 0
|
移动开发
零基础VB教程060期:论print输出中换行与不换行的讲究
零基础VB教程060期:论print输出中换行与不换行的讲究
326 0
L1-039 古风排版 (20 分)
L1-039 古风排版 (20 分)
127 0
L1-039 古风排版 (20 分)
【CCCC】L2-029 特立独行的幸福 (25分),模拟题,set用法
【CCCC】L2-029 特立独行的幸福 (25分),模拟题,set用法
173 0
|
开发者
【CCCC】L3-012 水果忍者 (30分),枚举斜率
【CCCC】L3-012 水果忍者 (30分),枚举斜率
133 0
7-42 行编辑器 (10 分)
7-42 行编辑器 (10 分)
169 0
|
前端开发
一道有意思的 CSS 面试题,FizzBu​​zz ~
一道有意思的 CSS 面试题,FizzBu​​zz ~
140 0
一道有意思的 CSS 面试题,FizzBu​​zz ~
VB编程:利用数组统计文字段落数-31
VB编程:利用数组统计文字段落数-31
111 0
|
Python
ZZULIOJ-1033,五级制成绩(Python)
ZZULIOJ-1033,五级制成绩(Python)