写在前面
这里利用优快云记录C++代码,方便自己查看
本文参考书籍《C++程序设计》第二版 杨长兴
这一篇是关于数组与指针
文章目录
一维数组
数列找最大值
题目:
已知数列
{
f
1
=
1
,
f
2
=
0
,
f
3
=
1
f
n
=
f
n
−
1
−
2
f
n
−
2
+
f
n
−
3
 
(
n
>
3
)
\left\{\begin{matrix} &f_{1}=1,f_{2}=0,f_{3}=1\\ &f_{n}=f_{n-1}-2f_{n-2}+f_{n-3}\: (n>3) \end{matrix}\right.
{f1=1,f2=0,f3=1fn=fn−1−2fn−2+fn−3(n>3)
编程实现:(1)按每行5个元素的格式输出
f
1
∼
f
20
f_{1}\sim f_{20}
f1∼f20
(2)输出
f
1
∼
f
20
f_{1}\sim f_{20}
f1∼f20中最大元素、最小元素、以及它们的下标。
重点
- 注意设置换行的条件,利用取余或者取整,也可以调位置
- 在找最大元素和最小元素时可以只保留下标,然后利用下标取值
#include<iostream>
#include<iomanip>
using namespace std;
void main()
{
int f[21]={0,1,0,1};//f[0]本题中没有用到可以随意赋一个值
//先求各个元素的值
for(int i=4;i<=20;i++)
{
f[i]=f[i-1]-2*f[i-2]+f[i-3];
}
//每行5个输出
cout<<"按每行5个输出f1-f20:"<<endl;
for(int j=1;j<=20;j++)
{
cout<<setw(6)<<f[j];//这里setw(6)是控制输出数据的宽度
if(j%5==0)//注意这里的换行的条件
{cout<<endl;}
}
//找最大值和最小值及下标,用max记录最大值下标,用min记录最小值下标
int max=1,min=1;
for(i=2;i<=20;i++)
{
if(f[i]>f[max])//注意这里的max是可以变的,注意
{max=i;}
if(f[i]<f[min])
{min=i;}
}
cout<<"最大值下标"<<max<<"最大值"<<f[max]<<endl;
cout<<"最小值下标"<<min<<"最小值"<<f[min]<<endl;
}
键盘输入数据(选择排序法)
从键盘上输入十个数,将这些数字按照从小到大的顺序输出。
分析:
- 可以定义数组,将输入的数字依次存放在数组中。注意定义数组的长度的时候绝对不能将数组的长度设为变量,不要耍小心思。
- 这里是对这一列数进行排序,可以选用“选择排序法”或者“冒泡排序法”。注意这里的排序是需要改变位置的,与之前的找最大值、最小值是有差别的。
- 选择排序法:(比较推荐用这个)如果有N个数需要进行排列,首先将第一个数作为最小的数;在N个数中找最小值的下标,如果与初始设定的下标不一致则将这个最小值与第一个位置的数调换位置;下一轮中不考虑第一个值,将第二个数作为最小的数,在N-1个数中找最小值的下标,如果下标与最初设定不一致则将那个最小数与第二个数进行交换。。。。重点是一遍一遍地找最小值的下标,然后将它对应的最小值与这一轮第一个数字交换,每一轮的数据量减少一个若有N个数排列最多进行N-1次交换。
#include<iostream>
using namespace std;
void main()
{
int jp[10];
//输入10个数并记录于数组中
cout<<"请输入10个数:"<<endl;
for(int i=0;i<10;i++)
{
cin>>jp[i];
}
//选择排序法
for(i=0;i<9;i++)//最多调换N-1次
{
int k=i;
for(int j=i+1;j<10;j++)
{
if(jp[j]<jp[k])//注意这里的jp[j]<jp[k],k是变的
{k=j;}
}
if(k!=i)//只有不一致时才会调换位置
{int t=jp[i];
jp[i]=jp[k];
jp[k]=t;}
}
//按顺序输出
for(i=0;i<10;i++)
{
cout<<jp[i]<<'\t';
}
}
二维数组
找出给定矩阵中的最大元素
现需要从键盘输入一个3*4的矩阵,并找出矩阵中的最大元素和对应元素的行下标、列下标。
#include<iostream>
#include<iomanip>
#define M 3
#define N 4
using namespace std;
void main()
{
int A[M][N];
//输入矩阵的元素,注意数组是按行赋值的,第一行左→右,第二行左→右...
cout<<"请输入"<<M*N<<"个数"<<endl;
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
cin>>A[i][j];
}
}
//按3*4的矩阵形式输出
for(i=0;i<M;i++)
{
cout<<endl;
for(int j=0;j<N;j++)
{
cout<<setw(4)<<A[i][j];
}
}
cout<<endl;
//找最大值的下标用col记录列坐标,row记录行坐标
int col=0,row=0;
for(i=0;i<M;i++)
{
for(int j=1;j<N;j++)
{
if(A[i][j]>A[row][col])
{
row=i;
col=j;
}
}
}
cout<<"最大值的行下标"<<row<<'\t'<<"列下标"<<col<<endl;
cout<<"最大值为"<<A[row][col]<<endl;
}
结果展示
范德蒙德矩阵
定义数组时,最好先将数组的长度声明为常量N,之后用N来代替,方便整体修改
定义一个N*N阶的范德蒙德矩阵,要求倒数第二行的元素由键盘输入。
[
a
3
a
2
a
1
1
b
3
b
2
b
1
1
c
3
c
2
c
1
1
d
3
d
2
d
1
1
]
\begin{bmatrix} a^{3} &a^{2} &a^{1} &1 \\ b^{3}&b^{2} &b^{1} &1 \\ c^{3} &c^{2} &c^{1} &1 \\ d^{3} &d^{2} &d^{1} &1 \end{bmatrix}
⎣⎢⎢⎡a3b3c3d3a2b2c2d2a1b1c1d11111⎦⎥⎥⎤
第一种做法(找列的关系)
#include<iostream>
#include<iomanip>
#define N 4
using namespace std;
void main()
{
//构造二维数组,并填数字
int fande[N][N];
//先填最后一列1
for(int i=0;i<N;i++)
{
fande[i][N-1]=1;
}
//再填第二列,然后
cout<<"请输入"<<N<<"个数"<<endl;
for(i=0;i<N;i++)
{
cin>>fande[i][N-2];
}
//按照每列等于后一列乘以倒数第二列赋值
for(int j=N-3;j>=0;j--)//注意是一列一列之间的关系
{
for(int i=0;i<N;i++)
{
fande[i][j]=fande[i][j+1]*fande[i][N-2];//注意这里是j+1啊
}
}
//将矩阵按照正式矩阵的形式输出
for(i=0;i<N;i++)
{
cout<<endl;
for(int j=0;j<N;j++)
{
cout<<setw(6)<<fande[i][j];
}
}
cout<<endl;
}
运行结果显示
第二种做法(找元素的关系)
#include<iostream>
#include<iomanip>
#include<cmath>
#define N 5
using namespace std;
void main()
{
int fande[N][N];
cout<<"请输入"<<N<<"个数"<<endl;
//输入倒数第二列的数字
for(int i=0;i<N;i++)
{
cin>>fande[i][N-2];
fande[i][N-1]=1;
}
for(i=0;i<N;i++)
{
for(int j=0;j<N-2;j++)
{
fande[i][j]=pow(fande[i][N-2],N-1-j);//利用指数函数
}
}
//按照矩阵输出
for(i=0;i<N;i++)
{
cout<<endl;
for(int j=0;j<N;j++)
{
cout<<setw(6)<<fande[i][j];
}
}
cout<<endl;
}
数组作为函数的参数
一维数组作为参数(冒泡法排序)
定义排序函数,将任意数组的前k个数据进行排序,这里采用冒泡法排序。
冒泡法排序:若N个数据进行排序最多进行N-1轮冒泡;每一轮依次比较临近的两个数,若前面的数较大就进行交换,这一轮中比较很多次,可以交换很多次;不同于“选择排序法”,选择排序法是每轮最终交换一次。
注意:代入数组作为实参时,只需要写数组名不用带大括号[]
#include<iostream>
using namespace std;
void sort(int x[],int k);
void main()
{
int chu[]={5,1,6,7,3,44,1,7,3,7};
sort(chu,6);
}
void sort(int x[],int k)
{
int shuchu=k;
for(int j=0;j<k;j++,k--)//这里k--是冒泡法最后的值不参与后一轮比较
{
int ret=0;
for(int i=0;i<k-1;i++)
{
if(x[i]>x[i+1])
{
int t=x[i];
x[i]=x[i+1];
x[i+1]=t;
ret=1;
}
}
if(ret==0)
{break;}
}
cout<<"输出排序后前k个值"<<endl;
for(int i=0;i<shuchu;i++)//重要,注意输出个数不能用k,因为循环改变了k
{
cout<<x[i]<<'\t';
}
cout<<endl;
}
运行结果显示
二维数据作为参数(矩阵求行和)
#include<iostream>
#define M 3
#define N 4
using namespace std;
void sum_row(int x[M][N],int y[]);
void main()
{
int chu[M][N];
int rowv[M];
cout<<"请输入"<<M*N<<"个数"<<endl;
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
cin>>chu[i][j];
}
}
//先输出完整矩阵
for(i=0;i<M;i++)
{
cout<<endl;
for(int j=0;j<N;j++)
{
cout<<chu[i][j]<<'\t';
}
}
cout<<endl;
//求行和
sum_row(chu,rowv);
}
//这里编写函数传数组的参数M,N,首先M,N必须是define声明的常量,绝对不能定义为变量
//其次,这里传每一维的长度,必须把参数放到方括号里面
void sum_row(int x[M][N],int y[])//注意M,N的位置
{
for(int i=0;i<M;i++)
{
y[i]=0;
for(int j=0;j<N;j++)
{
y[i]+=x[i][j];
}
}
for(i=0;i<M;i++)
{
cout<<y[i]<<'\t';
}
cout<<endl;
}
运行结果图
补充sizeof()函数的用法
#include<iostream>
using namespace std;
void main()
{
int a=6;
cout<<"sizeof(a)的值为"<<sizeof(a)<<endl;
cout<<"sizeof(int)的值为"<<sizeof(int)<<endl;
cout<<"sizeof(char)的值为"<<sizeof(char)<<endl;
cout<<"sizeof(float)的值为"<<sizeof(float)<<endl;
cout<<"sizeof(double)的值为"<<sizeof(double)<<endl;
}
运行结果如图
指针的用法
指针作为函数参数
利用指针作为参数时,主张不变地址,只变内容
利用指针作为参数的好处是,可以实时改变主调函数中的变量值,而普通变量作为参数时,运行函数,形参发生改变,但是实参本身并不会发生变化。
#include<iostream>
using namespace std;
void swap(int *p,int *q)//函数中定义指针参数
{
int t=*p;//注意这里是传到变量t
*p=*q;
*q=t;
}
int main()
{
int a,b;
cout<<"依次输入a,b"<<endl;
cin>>a>>b;
swap(&a,&b);//引用时,用地址、地址表达式、指针变量
cout<<"交换后a,b依次为:"<<endl;
cout<<a<<'\t'<<b<<endl;
return 0;
}
运行结果图
字符串的简单应用
删除字符串中给定字符
编写函数 void del_ch(char *p,char ch)删除p所指的字符串中的ch字符
若p所知的字符串为"changsha",ch值为"a",则调用该函数之后,p所指的字符串为"chngsh".
注意这里要求在调用函数之后原字符串发生改变而不是重新建立一个新的字符串,那么就要在定义函数时,利用指针变量作为参数。
#include<iostream>
using namespace std;
void del_ch(char *p,char ch);
void main()
{
char x[50];
cout<<"请输入字符串"<<endl;
for(int i=0;i<8;i++)
{
cin>>x[i];
}
x[8]='\0';
cout<<"键盘输入字符串"<<x<<endl;
del_ch(x,'a');
cout<<"剔除之后"<<x<<endl;
}
void del_ch(char *p,char ch)//这里代入时第一个参数给字符串名,即字符串地址
{
char *q=p;//注意给指针赋值,右边必须是地址
for(;*p!='\0';p++)
{
if(*p!=ch)//一个一个复制,需要删除的不复制
{
*q=*p;
q++;//只有复制一次,q的地址才会变
}
}
*q='\0';//随然最后指针变量p,q都不是只想字符串首端,但是字符串字母的地址不变
}//这里最终的结果只是,p,q指针变量指向别的地方了
结果显示
删除字符串中的数字
对于C++中数字字符有
数字字符-“0”=该数字。例如:“3”-“0”就是整数型3.
#include<iostream>
using namespace std;
void del_num(char *p);
void main()
{
char x[50];
cout<<"请输入字符串"<<endl;
for(int i=0;i<8;i++)
{
cin>>x[i];
}
x[8]='\0';
cout<<"键盘输入字符串"<<x<<endl;
del_num(x);
cout<<"剔除之后"<<x<<endl;
}
void del_num(char *p)
{
char *q=p;
for(;*p!='\0';p++)
{
int t=*p-'0';//注意这里利用数字字符的特点
if(t<0||t>9)
{
*q=*p;
q++;
}
}
*q='\0';//注意,最后一定要给结束符号
}
结果显示
字符串中插入其他字符串
编写函数void insert_ch(char *p,int n,char *q)在p所指字符串的第n字节位置插入q所指字符串。
关键分析:
- 这里往第一个字符串中插入第二个字符串,并且要求原来的位置,原来存放第一字符串的数组存放着最后的结果。
- 思路为:首先,原地复制第一字符串在插入位置之前的内容;下一步,将第一字符串的后一部分(不含‘\0’)复制到新数组me[]暂时存着,给me[]中手动添加‘\0’;下一步,将第二字符串全部接着复制到第一字符串上半部后面;下一步,将新数组的内容全部复制到第二字符串后面(不含‘\0’);最后手动添加‘\0’。
- 超级重要的内容
函数体里面首先应该将指针变量*h所指位置初始为p
引用函数时,形参指针变量*p的位置需要赋值(地址,地址表达式,指针变量,数组名)
在循环中*p才是取值,p这个是地址,不要犯蠢
第一字符串定义时要长一点,至少能够装得下第一字符串和第二字符串以及‘\0’
#include<iostream>
#include<cmath>
using namespace std;
void insert_ch(char *p,int n,char *q);
void main()
{
char x[100];
char y[5];
cout<<"请输入第一串字符串"<<endl;
for(int i=0;i<8;i++)
{
cin>>x[i];
}
x[8]='\0';
cout<<"请输入第二串字符串"<<endl;
for(int k=0;k<5;k++)
{
cin>>y[k];
}
y[5]='\0';
cout<<"键盘输入字符串依次为"<<x<<'\t'<<y<<endl;
insert_ch(x,4,y);
cout<<"插入之后"<<x<<endl;//直接输出数组
}
void insert_ch(char *p,int n,char *q)
{
char *h=p;
char me[100];
char *mezhi=me;//这里最好用一个指针指着新的数组,方便最后复制'\0'
//第一串前一半复制
for(int j=1;j<n;p++)
{
*h=*p;
h++;
j++;
}
//第一串后一半放到数组里面
for(;*p!='\0';p++)//注意这里是*p!='\0',不要犯蠢,*p才是取值
{
*mezhi=*p;
mezhi++;
}
*mezhi='\0';
cout<<me<<endl;
//接着整体复制第二串
for(;*q!='\0';q++)//注意这里是*q!='\0',注意注意是*q取值
{
*h=*q;
h++;
}
//最后将存放到数组中的字符串复制过去
for(int t=0;me[t]!='\0';t++)
{
*h=me[t];
h++;
}
*h='\0';
}