题目链接:
题目分析:
即将一行字符串处理为满足一系列要求的格式进行输出
具体要求如下:
须考虑{{{{{}}}}
- 默认程序起始没有缩进;每一级缩进是 2 个空格;
- 每行开头除了规定的缩进空格外,不输出多余的空格; 如文件末尾可能有多余空格
- 顺序执行的程序体是以分号“;”结尾的,遇到分号就换行;
- 在一对大括号“{”和“}”中的程序体输出时,两端的大括号单独占一行,内部程序体每行加一级缩进
- 若出现if-else、while、for结构,按照规定格式输出; 空格处理 结构嵌套
关于结构嵌套,采取的处理方式仍旧是边分析字符串边处理,循环结构+一定的标记变量
感觉用递归处理可能更加简洁且正统,后续可能会补上递归版本
参考(参考以下博客的测试用例):
感谢该博主的测试用例(十分给力)(在其代码末位置),帮我找到了其中一个测试点未通过的原因
在此引用几个较为典型的(用例的输出就不附了,可以直接判断或利用下面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;
}