Sweety

Practice makes perfect

导航

蓝桥杯---画表格(find、gets、substr)

Posted on 2015-03-30 22:04  蓝空  阅读(226)  评论(0编辑  收藏  举报


画表格

在图形环境中很容易做出漂亮的表格。但在控制台环境中就比较困难了。有的时候可以用一些符号大略地模拟:(word文档中可能不整齐,拷贝到记事本中看)
+-------+------+
|abc    |xyz=tt|
+-------+------+
|hellomm|t2    |
+-------+------+

本题目要求设计一个程序,把用户输入的内容用这种“准表格”的方式展现出来。具体的要求是:
用户输入的第一行是一个整数,表示接下来有多少行信息。接下来的每行由若干单元组成。单元间用逗号分开。
程序输出:用表格方式重新展现的输入内容。
例如:

用户输入:
3
cat,dog,good-luck
1,2,5
do not use,,that
则程序输出:(word文档中可能不整齐,拷贝到记事本中看)
+----------+---+---------+
|cat       |dog|good-luck|
+----------+---+---------+
|1         |2  |5        |
+----------+---+---------+
|do not use|   |that     |
+----------+---+---------+
从中不难看出:
两个连续的逗号表示中间有一个内容为空的单元
列的数目由最大的单元数的那行决定
列的宽度由同列的最宽的单元决定
单元格中的信息左对齐

可以假设:用户输入的最大行数为30,可能的最多列数为40。

感觉这道题挺坑的,因为一般的时候就用printf中的一些函数,谁会用cout啊,但是今天就摊上事了,并且是摊上大事了,因为好像printf不能填充除了0以外的字符,所以只能是重操旧业,用了我的”母语“,但是越是娘家语言,也是不会用看,用了三四个小时被坑在这里面,最终把这个cout的输出格式有了一点研究,成功了。。。

注意这里面的gets、find、substr这几个函数的使用 。。。

#include <iostream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main (){
  string str[35][45],tempstr;
  int n,list,a[45]={0},strrow=0,strlist=0,strle[45]={0};
  char ch[100];
  cin>>n;
  getchar();//注意收取回车 
  for(int i=0;i<n;i++){
  	gets(ch);
    tempstr=ch;
   int now=0,xx = tempstr.find(',');  
   while(xx!=-1){
   	str[strrow][strlist++]=tempstr.substr(now,xx-now);
   	if(xx-now>strle[strlist-1]) 
	   strle[strlist-1]=xx-now;
   	now=xx+1;
   	xx=tempstr.find(',',now);
   }
   str[strrow][strlist++]=tempstr.substr(now);
   if(tempstr.length()-now>strle[strlist-1]) 
	   strle[strlist-1]=tempstr.length()-now;
   list=strlist;
   strrow++;
   strlist=0;	
  }
  for(int i=0;i<strrow;i++){
  	
  	 cout<<'+'<<setiosflags(ios::right)<<setfill('-');
  	 for(int j=0;j<list;j++)
       cout<<setw(strle[j]+1)<<'+';
       
       
	 cout<<endl<<'|'<<setiosflags(ios::left)<<setfill(' ');
     for(int j=0;j<list;j++)
       cout<<setw(strle[j])<<str[i][j]<<'|';
       
    cout<<endl;
  }
  cout<<'+'<<right<<setfill('-');//输出最后一行--------+------ 
  	 for(int j=0;j<list;j++)
       cout<<setw(strle[j]+1)<<'+';
return 0;
}
运行结果不正确,恩,是的,这个代码确实是有问题的,就是因为字符的左右对齐这个函数出了问题。

下面的代码修改了这个错误,错误详情查看http://blog.csdn.net/u014665013/article/details/44781973

#include <iostream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main (){
  string str[35][45],tempstr;
  int n,list,a[45]={0},strrow=0,strlist=0,strle[45]={0};
  char ch[100];
  cin>>n;
  getchar();//注意收取回车 
  for(int i=0;i<n;i++){
  	gets(ch);
    tempstr=ch;
   int now=0,xx = tempstr.find(',');  
   while(xx!=-1){
   	str[strrow][strlist++]=tempstr.substr(now,xx-now);
   	if(xx-now>strle[strlist-1]) 
	   strle[strlist-1]=xx-now;
   	now=xx+1;
   	xx=tempstr.find(',',now);
   }
   str[strrow][strlist++]=tempstr.substr(now);
   if(tempstr.length()-now>strle[strlist-1]) 
	   strle[strlist-1]=tempstr.length()-now;
   list=strlist;
   strrow++;
   strlist=0;	
  }
  for(int i=0;i<strrow;i++){
  	
  	 cout<<'+'<<setiosflags(ios::right)<<setfill('-');
  	 for(int j=0;j<list;j++)
       cout<<setw(strle[j]+1)<<'+';
       
       
	 cout<<endl<<'|'<<resetiosflags(ios::right)<<setiosflags(ios::left)<<setfill(' ');//这里用第一个re..()对对齐方式做了重置 
     for(int j=0;j<list;j++)
       cout<<setw(strle[j])<<str[i][j]<<'|';
       //为什么在这里不用加重置对齐方式现在还未知。 
    cout<<endl;
  }
  cout<<'+'<<right<<setfill('-');//输出最后一行--------+------ 
  	 for(int j=0;j<list;j++)
       cout<<setw(strle[j]+1)<<'+';
return 0;
}
一不小心,发现了一个更好的方法,并且更加容易记忆了...

#include <iostream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main (){
  string str[35][45],tempstr;
  int n,list,a[45]={0},strrow=0,strlist=0,strle[45]={0};
  char ch[100];
  cin>>n;
  getchar();//注意收取回车 
  for(int i=0;i<n;i++){
  	gets(ch);
    tempstr=ch;
   int now=0,xx = tempstr.find(',');  
   while(xx!=-1){
   	str[strrow][strlist++]=tempstr.substr(now,xx-now);
   	if(xx-now>strle[strlist-1]) 
	   strle[strlist-1]=xx-now;
   	now=xx+1;
   	xx=tempstr.find(',',now);
   }
   str[strrow][strlist++]=tempstr.substr(now);
   if(tempstr.length()-now>strle[strlist-1]) 
	   strle[strlist-1]=tempstr.length()-now;
   list=strlist;
   strrow++;
   strlist=0;	
  }
  for(int i=0;i<strrow;i++){
  	
  	 cout<<'+'<<right<<setfill('-');
  	 for(int j=0;j<list;j++)
       cout<<setw(strle[j]+1)<<'+';
       
       
	 cout<<endl<<'|'<<left<<setfill(' ');
     for(int j=0;j<list;j++)
       cout<<setw(strle[j])<<str[i][j]<<'|';
       
    cout<<endl;
  }
  cout<<'+'<<right<<setfill('-');//输出最后一行--------+------ 
  	 for(int j=0;j<list;j++)
       cout<<setw(strle[j]+1)<<'+';
return 0;
}

终结版的代码,因为我发现使用在一道题里使用两种对齐方式因为函数的特点,所以有点麻烦,所以以后尽量不用两种,比如下面的完美的解决了这个问题。

#include <iostream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main (){
  string str[35][45],tempstr;
  int n,list,a[45]={0},strrow=0,strlist=0,strle[45]={0};
  char ch[100];
  cin>>n;
  getchar();//注意收取回车 
  for(int i=0;i<n;i++){
  	gets(ch);
    tempstr=ch;
   int now=0,xx = tempstr.find(',');  
   while(xx!=-1){
   	str[strrow][strlist++]=tempstr.substr(now,xx-now);
   	if(xx-now>strle[strlist-1]) 
	   strle[strlist-1]=xx-now;
   	now=xx+1;
   	xx=tempstr.find(',',now);
   }
   str[strrow][strlist++]=tempstr.substr(now);
   if(tempstr.length()-now>strle[strlist-1]) 
	   strle[strlist-1]=tempstr.length()-now;
   list=strlist;
   strrow++;
   strlist=0;	
  }
  for(int i=0;i<strrow;i++){
  	 for(int j=0;j<list;j++)
       cout<<setfill('-')<<setw(strle[j]+1)<<setiosflags(ios::left)<<'+';
	 cout<<'+'<<endl<<'|';
     for(int j=0;j<list;j++)
       cout<<setw(strle[j])<<setfill(' ')<<str[i][j]<<'|';
     cout<<endl;
  }
  cout<<setfill('-');
  for(int j=0;j<list;j++)
    cout<<setw(strle[j]+1)<<'+';
   cout<<'+';
 return 0;
}