L3-019 代码排版 (30')

题目链接:

L3-019 代码排版

 

题目分析:

即将一行字符串处理为满足一系列要求的格式进行输出

具体要求如下:

须考虑{{{{{}}}}

  • 默认程序起始没有缩进;每一级缩进是 2 个空格;
  • 每行开头除了规定的缩进空格外,不输出多余的空格;  如文件末尾可能有多余空格
  • 顺序执行的程序体是以分号“;”结尾的,遇到分号就换行; 
  • 在一对大括号“{”和“}”中的程序体输出时,两端的大括号单独占一行,内部程序体每行加一级缩进
  • 若出现if-else、while、for结构,按照规定格式输出;   空格处理   结构嵌套

 关于结构嵌套,采取的处理方式仍旧是边分析字符串边处理,循环结构+一定的标记变量

感觉用递归处理可能更加简洁且正统,后续可能会补上递归版本

 

参考(参考以下博客的测试用例):

团体程序设计天梯赛L3-019 代码编排(23分)

感谢该博主的测试用例(十分给力)(在其代码末位置),帮我找到了其中一个测试点未通过的原因

在此引用几个较为典型的(用例的输出就不附了,可以直接判断或利用下面code):

注:字符串末尾未加换行

1
int main() {if (3>2) { printf("Y"); } return 0;}
2
int main(){if (3>2) {if (4>3) { if (5>3) {int i=3;}   }}}
3
int main() {if (3>2) while (3>2) {if (3>2) printf("Y"); if (3>2) printf("Y"); } return 0;}
4
int main() {  if (3>2) if (4>3) if (6>-2) printf("Y\n");    else if (3>2) printf("Y\n");
else printf("N\n");    return 0; }
5 (末尾有空格)
int main(){}      
6
int main() { {int i=2;} if (3>2) if (4>3) else 5>3; }
7
int main() { {int i=2;} { {i=3; {}} {} } }
8
int main() {{{{}}}}
9
int main()  {    if           (3>2)        i++;    else    j--;    for (i=1;i<=5;i++)              j++;      while          (3>2)    i-;        }    
10
int main()  {    if           (3>2)   {     i++;   }  else   {   j--;  }  for (i=1;i<=5;i++)   {           j++;    }  while          (3>2)   {  i-;   }     }

 

AC_Code:

代码较为杂乱之后使用递归或参考编译原理中的相关方式可能会好些

已经添加了较多的注释,但是由于该题目属于繁琐处理型,并未有统一的处理方式或思路(比如添加各种标志判断等)

因此关于代码问题欢迎留言讨论。

#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
#include <iostream>
#define MAX_N 500
using namespace std;

//L3-019 代码排版 (30 分)

//else及{} 特殊处理,其他的for、while、if可归为一种  均是for/while/if + () + { }
//采用边处理边输出的方式

//判断语句块类型
int judge_other(string dat, int i){
    int is;
    if(dat.find("if", i) == i && (dat[i+2]==' ' || dat[i+2]=='('))
        is = 2;
    else if(dat.find("while", i) == i && (dat[i+5]==' ' || dat[i+5]=='('))
        is = 5;
    else if(dat.find("for", i) == i && (dat[i+3]==' ' || dat[i+3]=='('))
        is = 3;
    else if(dat.find("else", i) == i && dat[i+4]==' ')
        is = 4;
    else if(dat.find("{", i) == i)
        is = 1;
    else
        is = 0;   //普通语句
    return is;
}

//print space
void print_space(int space){
    for(int z=0; z<space; z++) printf(" ");
}

//跳过多余空格
void ignore_space(string dat, int &i){
    while(dat[i]==' ') i++;
}

int main(){
    string dat;
    bool flag;
    getline(cin, dat);
    int i=0, j=0, m, idx, k, tmp, space=0, debt=0;  //space 记录缩进

    //处理main函数 开端部分
    ignore_space(dat, i);  //去除多余空格
    //从初始字符打印至)
    idx = dat.find(')', 0);
    for(j=i; j<=idx; j++) printf("%c", dat[j]);
    printf("\n{\n");
    
    //跳过字符串中的{, 因为上边已经直接打印
    space += 2;
    i = idx+1;
    ignore_space(dat, i);
    i++;

    while(i < dat.length()){
        ignore_space(dat, i);
        if((tmp = judge_other(dat, i))){
            print_space(space);
            //处理{} 括号语句块  尤如{{{{}}}}
            if(tmp == 1){
                printf("{\n");
                i++;
                space += 2;
                continue;
            }
            //else特殊处理,其他的for、while、if可归为一种  均是for/while/if + () + { }
            if(tmp == 4){
                for(j=0; j<4; j++) printf("%c", dat[i+j]);
                k = i+3;
            }
            else{
                for(j=0; j<tmp; j++) printf("%c", dat[i+j]);
                printf(" ");
                i += tmp;
                ignore_space(dat, i);
                //因以 ) 作为处理标志,因此考虑 if(条件) 条件中也有()的情况
                k = i;
                int t=0;
                while(true){
                    if(dat[k] == '('){
                        t++;
                    }
                    else if(dat[k] == ')'){
                        t--;
                        if(!t) break;
                    }
                    k++;
                }
                for(j=i; j<=k; j++) printf("%c", dat[j]);
            }
            //找 { 
            //此处分两种情况:一、源代码中没有{},语句块仅有一条语句; 二、源代码中本身有{}
            m = k+1;
            ignore_space(dat, m);
            if(dat[m] != '{'){
                printf(" {\n");
                flag = false;    //flag 与debt 共同作用为处理上述情况一,因为要考虑何时应该输出 }(即配对的右大括号)
                debt++;
                i = m;
            }else{
                printf(" {\n");
                flag = true;
                i = m+1;
            }
            space += 2;
        }
        else if(dat[i] == '}'){
            space -= 2;
            print_space(space);
            printf("}\n");
            if(space == 0) break;   //字符串处理完毕——此处用意为考虑 可能在程序的最后有空格

            i++;

            //下边几行代码即为判断上述情况一,是否应该输出 } 
            ignore_space(dat, i);
            while(debt && judge_other(dat, i)!=4){  
                space -= 2;
                print_space(space);
                printf("}\n");
                debt--;
            }
        }
        else{
            //普通语句
            idx = dat.find(';', i);
            print_space(space);
            for(j=i; j<=idx; j++) printf("%c", dat[j]);
            printf("\n");
            i = idx+1;
            if(debt && !flag){
                space -= 2;
                print_space(space);
                printf("}\n");
                debt--;

                //下边几行代码同为判断上述情况一,是否应该输出 } 
                ignore_space(dat, i);
                while(debt && judge_other(dat, i)!=4){
                    space -= 2;
                    debt--;
                    print_space(space);
                    printf("}\n");
                }
            }
        }
    }
    return 0;
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值