1 条题解
-
0
解题思路
程序的主要功能是解析并输出一个由 ASCII 字符构成的表格。输入的表格以特定的 ASCII 字符绘制,程序会处理这些输入,计算各列的宽度,最终输出格式规范、排版整齐的表格。
详细题解
1. 头文件与类型定义
#include<iostream> #include<stdio.h> #include<vector> #include<string> #include<sstream> #include<string.h> using namespace std; typedef basic_string<unsigned char> ustring;
- 引入了一系列标准库的头文件,这些头文件涵盖了输入输出、字符串处理、向量操作等功能。
- 定义了
ustring
类型,它本质上是basic_string<unsigned char>
的别名,用于处理无符号字符类型的字符串。
2. 表格边界字符数组
unsigned char ccc[]={ 179, 196, // '│' '─' 218, 194, 191, // '┌' '┬' '┐' 195, 197, 180, // '├' '┼' '┤' 192, 193, 217, // '└' '┴' '┘' };
- 该数组存储了用于绘制表格边界的 ASCII 字符的编码。借助这些字符,程序能够绘制出规范的表格边框。
3. 全局变量与辅助函数
int col; unsigned char line[300]; inline int ustrlen(unsigned char *s){ int len = 0; while(s[len]!=0) len++; return len; }
col
:用于记录表格的列数。line
:用于存储每行输入的字符。ustrlen
:这是一个内联函数,其作用是计算无符号字符数组的长度。
4. 表格数据结构
vector<vector<vector<unsigned char *> > > table;
table
是一个三维向量,其用途是存储表格中的数据。最外层向量代表行,中间层向量代表列,内层向量代表每个单元格可能包含的多行文本。
5. 去除首尾空格函数
unsigned char* trim(unsigned char* token){ int len; for(len=0;token[len]!=0;len++){} int l=0,r=len-1; while(l<len && token[l]==' ') l++; while(r>=0 && token[r]==' ') r--; if(l>r) { unsigned char *ret = (unsigned char *)malloc(1*sizeof(unsigned char)); ret[0] = 0; return ret; } unsigned char *ret = (unsigned char*)malloc((r-l+2)*sizeof(unsigned char)); for(int i=0;i<=r-l;i++) ret[i] = token[l+i]; ret[r-l+1] = 0; return ret; }
trim
函数的功能是去除无符号字符数组首尾的空格。若去除空格后数组为空,就返回一个空字符串;否则,返回去除空格后的新字符串。
6. 打印单元格函数
inline void print_cell(int i,int j,int k,int w){ if(table[i][j].size()>k){ cout<<" "; int len = ustrlen(table[i][j][k]); for(int l=0;l<len;l++) cout<<table[i][j][k][l]; w-=len+1; } for(int l=0;l<w;l++) cout<<" "; return; }
print_cell
函数用于打印表格中的单元格。若单元格存在数据,就先输出一个空格,接着输出单元格内容,最后用空格填充剩余的宽度。
7. 主函数流程
7.1 计算列数
while(cin>>std::noskipws>>c,c!=10){ if(c==194) col++; } col+=1;
- 读取输入的第一行,统计字符
194
(即┬
)的数量,进而确定表格的列数。
7.2 解析表格数据
vector<vector<unsigned char*> > row; while(cin>>std::noskipws>>c){ line[0] = c; int lc = 0; int sz = 1; while(cin>>std::noskipws>>c) { if(c==10) break; line[sz++] = c; } bool bad = false; for(int i=0;i<sz;i++) if(line[i]==196) { bad = true; break; } if(bad) { table.push_back(row); row.clear(); }else{ unsigned char token[300]; int t_sz=0; int cnt = 0; for(int i=1;i<sz;i++){ if(line[i]==179){ if(cnt==row.size()) row.push_back(vector<unsigned char*>()); token[t_sz] = 0; row[cnt].push_back(trim(token)); t_sz = 0; cnt++; }else token[t_sz++]=line[i]; } } }
- 逐行读取输入,若某行包含字符
196
(即─
),则表明这是表格的分隔行,将当前行的数据添加到table
中,并清空row
。 - 若不是分隔行,就按字符
179
(即│
)分割单元格,去除单元格内容的首尾空格后添加到row
中。
7.3 计算各列宽度
vector<int> width(col,0); for(int i=0;i<table.size();i++) for(int j=0;j<table[i].size();j++) for(int k=0;k<table[i][j].size();k++){ width[j]=max(width[j],ustrlen(table[i][j][k])+2); }
- 遍历表格中的所有单元格,计算每列所需的最大宽度,宽度计算时会考虑单元格内容长度加上两侧的空格。
7.4 输出表格
// 输出表头行 cout<<ccc[2]; for(int i=0;i<col;i++) { for(int j=0;j<width[i];j++) cout<<ccc[1]; if(i==col-1)cout<<ccc[4]<<endl; else cout<<ccc[3]; } for(int i=0;i<table.size();i++){ int ln = 0; for(int j=0;j<table[i].size();j++) ln = max(ln,(int)table[i][j].size()); for(int l=0;l<ln;l++){ cout<<ccc[0]; for(int j=0;j<table[i].size();j++){ print_cell(i,j,l,width[j]); cout<<ccc[0]; } cout<<endl; } if(i!=table.size()-1){ cout<<ccc[5]; for(int j=0;j<col;j++) { for(int k=0;k<width[j];k++) cout<<ccc[1]; if(j==col-1)cout<<ccc[7]<<endl; else cout<<ccc[6]; } } } // 输出表尾行 cout<<ccc[8]; for(int i=0;i<col;i++) { for(int j=0;j<width[i];j++) cout<<ccc[1]; if(i==col-1)cout<<ccc[10]; else cout<<ccc[9]; }
- 输出表头行,使用
ccc
数组中的字符绘制表格的上边框。 - 逐行输出表格内容,若单元格有多行文本,则逐行输出。
- 若不是最后一行,输出中间的分隔行。
- 输出表尾行,绘制表格的下边框。
复杂度分析
- 时间复杂度:,这里的 为行数, 为列数, 为每个单元格的平均行数。
- 空间复杂度:,主要用于存储表格数据。
#include<stdio.h> #include<vector> #include<string> #include<sstream> #include<string.h> using namespace std; typedef basic_string<unsigned char> ustring; //if contain '─' not a text line unsigned char ccc[]={ 179, 196, // '│' '─' 218, 194, 191, // '┌' '┬' '┐' 195, 197, 180, // '├' '┼' '┤' 192, 193, 217, // '└' '┴' '┘' }; int col; unsigned char line[300]; inline int ustrlen(unsigned char *s){ int len = 0; while(s[len]!=0) len++; return len; } vector<vector<vector<unsigned char *> > > table; unsigned char* trim(unsigned char* token){ int len; for(len=0;token[len]!=0;len++){} int l=0,r=len-1; while(l<len && token[l]==' ') l++; while(r>=0 && token[r]==' ') r--; if(l>r) { unsigned char *ret = (unsigned char *)malloc(1*sizeof(unsigned char)); ret[0] = 0; return ret; } unsigned char *ret = (unsigned char*)malloc((r-1+2)*sizeof(unsigned char)); for(int i=0;i<=r-1+1;i++) ret[i] = token[l+i]; ret[r-l+1] = 0; return ret; } inline void print_cell(int i,int j,int k,int w){ if(table[i][j].size()>k){ cout<<" "; int len = ustrlen(table[i][j][k]); for(int l=0;l<len;l++) cout<<table[i][j][k][l]; w-=len+1; } for(int l=0;l<w;l++) cout<<" "; return; } int main() { unsigned char c; col = 0; while(cin>>std::noskipws>>c,c!=10){ if(c==194) col++; } col+=1; vector<vector<unsigned char*> > row; while(cin>>std::noskipws>>c){ line[0] = c; int lc = 0; int sz = 1; while(cin>>std::noskipws>>c) { if(c==10) break; line[sz++] = c; } bool bad = false; for(int i=0;i<sz;i++) if(line[i]==196) { bad = true; break; } if(bad) { table.push_back(row); row.clear(); }else{ unsigned char token[300]; int t_sz=0; int cnt = 0; for(int i=1;i<sz;i++){ if(line[i]==179){ if(cnt==row.size()) row.push_back(vector<unsigned char*>()); token[t_sz] = 0; row[cnt].push_back(trim(token)); t_sz = 0; cnt++; }else token[t_sz++]=line[i]; } } } //calculate the width vector<int> width(col,0); //ustreln+2 for(int i=0;i<table.size();i++) for(int j=0;j<table[i].size();j++) for(int k=0;k<table[i][j].size();k++){ width[j]=max(width[j],ustrlen(table[i][j][k])+2); } //for(int i=0;i<col;i++) // cout<<width[i]<<endl; //begin to print //header line cout<<ccc[2]; for(int i=0;i<col;i++) { for(int j=0;j<width[i];j++) cout<<ccc[1]; if(i==col-1)cout<<ccc[4]<<endl; else cout<<ccc[3]; } for(int i=0;i<table.size();i++){ //how many line this row need int ln = 0; for(int j=0;j<table[i].size();j++) ln = max(ln,(int)table[i][j].size()); for(int l=0;l<ln;l++){ cout<<ccc[0]; for(int j=0;j<table[i].size();j++){ print_cell(i,j,l,width[j]); cout<<ccc[0]; } cout<<endl; } if(i!=table.size()-1){ //print middle line 5 6 7 cout<<ccc[5]; for(int j=0;j<col;j++) { for(int k=0;k<width[j];k++) cout<<ccc[1]; if(j==col-1)cout<<ccc[7]<<endl; else cout<<ccc[6]; } } } cout<<ccc[8]; for(int i=0;i<col;i++) { for(int j=0;j<width[i];j++) cout<<ccc[1]; if(i==col-1)cout<<ccc[10]; else cout<<ccc[9]; } return 0; }
- 1
信息
- ID
- 442
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 7
- 已通过
- 1
- 上传者