在我们做笔试题的时候,经常会遇到读入一个大小未知的数组的情况,比如一个经典的笔试题:求一个输入为N*N二维矩阵的90度旋转,但是题目并没告诉我们这个N是多大。有可能是3*3:
1 2 3
4 5 6
7 8 9
也可能是4*4:
11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44
那么为了我们的算法能够处理所有的N*N维矩阵,首先我们得能够读入这个输入的二维矩阵。整个过程分为三步:
1、选用vector来保存这个二维数组
首由于不知道N究竟是多大,那么如果用数组int num[N][N]来保存就会面临一个问题,不知道该分配一个多大的数组,当然也可以分配得很大,但是有可能浪费空间,分配不够,那更会错误。相信大家已经想到了,用vector来保存就好啦,vector有它自己的内存分配机制,调用者无须考虑分配多大空间
2、用getline来读入一行
cin和getline的区别在于:
cin是遇到空白/空格即认为是此次读取结束,getline是读完一行才认为是读取结束,但是getline只能把读入的内容保存为一个字符串
string str;
getline(cin,str);
int val;
cin>>val;
由于我们不知道N是多少,即不知道一行有多少个元素,所以不能用cin来读入数据,而要用getline
3、getline读入字符串转换为整数
由于getline会将其读入到这一行保存为一个字符串(包括读入到空格),因此,我们需要对这个字符串进行处理,以提取出元素个数以及将各个字符元素转换为整数,进而保存到vector中
//读入一行字符串,然后将字符串里的字符转换为数字并存到vector<int> mid里
vector<int> mid;
for(int i=0;i<str.size();i++){
string str2="";
//输入的数字之间以空格隔开
while(str[i]!=' '&&i<str.size()){
str2+=str[i];
i++;
}
//将字符串转化为整数
int num=stoi(str2);
mid.push_back(num);
//cout<<num<<" ";
}
4、至此,结束,完整代码如下:
//要求N*N数组,事先不知道数组大小N,从键盘读入
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main(){
vector<vector<int> >vec;
string str;
//一次只能读一行,可以用while读多行,但是如果用while一直读会造成一直要求输入,而不能读入N*N数组
getline(cin,str);
//统计有多少个数字,因为输入是按空格隔开的,比如1 2 3
int N=1;
for(int i=0;i<str.size();i++){
if(str[i]==' ')
N++;
}
//打印输出N,用来检查N是否正确
// cout<<N<<endl;
//读入一行字符串,然后将字符串里的字符转换为数字并存到vector<int> mid里
vector<int> mid;
for(int i=0;i<str.size();i++){
string str2="";
//输入的数字之间以空格隔开
while(str[i]!=' '&&i<str.size()){
str2+=str[i];
i++;
}
//将字符串转化为整数
int num=stoi(str2);
mid.push_back(num);
//cout<<num<<" ";
}
//通过打印输出mid来检查上面的操作是否正确
/* for(int i=0;i<mid.size();i++)
cout<<mid[i]<<" ";
cout<<endl;*/
vec.push_back(mid);
/* 方法一 读入剩余的几行
for(int i=1;i<N;i++){
getline(cin,str);
vector<int> mid2;
for(int i=0;i<str.size();i++){
string str2="";
while(str[i]!=' '&&i<str.size()){
str2+=str[i];
i++;
}
int num=stoi(str2);
mid2.push_back(num);
}
vec.push_back(mid2);
}*/
// 方法二 读入剩余的几行,想比于方法一种string与int的多次转换,方法二效率更高
for(int i=1;i<N;i++){
vector<int> tmp;
for(int j=0;j<N;j++){
int val;
//cin是遇到空白/空格即认为是此次读取结束,getline是读完一行才认为是读取结束,但是getline只能把读入的内容保存为一个字符串
cin>>val;
tmp.push_back(val);
}
vec.push_back(tmp);
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
cout<<vec[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
程序运行结果:
输入:
1 2 3
4 5 6
7 8 9
输出:
1 2 3
4 5 6
7 8 9
Program ended with exit code: 0