零基础学C++之进阶篇一
零基础学C++之进阶篇一
数组、指针、引用
数组是有序数据的集合,可以减少对同样类型变量的声明;指针是可以操作内存数据的变量;引用是变量的名别;数组的首地址可以看作是指针,通过指针可以操作数组,指针和引用在函数的参数传递时可以互相替代。指针是一把双刃剑,既能提升程序的效率,也能给程序带来意想不到的灾难。
一维数组
一维数组的声明
在程序设计中,将同一数据类型的数据按一定形式有序的组织起来,这些有序数据的集合称为数组。一个数组有一个统一的数组名,可以通过数组名和下标来唯一确定数组中的元素。
一维数组的声明形式如下:
数据类型 数组名[常量表达式]
常量表达式表示元素的个数,即数组的长度,定义数组的常量表达式不能是变量,数组的大小不能动态定义。
一维数组的引用
数组引用的一般形式如下:
数组名[下标]
数组元素的下标起始值为0,不是1。
一维数组的初始化
数组元素初始化的方式有两种,一种是对单个元素逐一赋值,另一种是使用聚合方式赋值。
(1)单一数组元素赋值
a[0]=0就是对单一数组元素赋值,也可以通过变量控制下标的方式进行赋值。
(2)聚合方法赋值
数组不仅可以逐一对数组元素赋值,还可以通过大括号进行多个元素赋值。
int a[12]={1,2,3,4,5,6,7,8,9,10,11,12};
int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
int a[12]={1,2,3,4,5,6,7};
二维数组
二维数组的声明
二维数组声明的一般形式为:
数据类型 数组名[常量表达式1][常量表达式2]
一维数组描述的是一个线性序列,二维数组则描述的是一个矩阵,常量表达式1代表行数,常量表达式2代表列数。
二维数组的引用
二维数组元素的引用形式为:
数组名[下标][下标]
二维数组的初始化
二维数组元素初始化和一维数组相同,也分为单个元素逐一赋值和使用聚合方法赋值。如:
a[0][1]=12;
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
实例01 交换二维数组的行和列
#include <iostream>
#include <iomanip>
using namespace std;
void fun(int array[3][3])
{
for(int i=0;i<3;i++)
{
for(int j=0; j<3;j++)
{
t=array[i][j];
array[i][j]=array[j][i];
array[j][i]=t;
}
}
}
void main()
{
int array[3][3]={{1,2,3},{4,5,6},{7,8,9}};
cout << "convert front" << endl;
for(int i =0; i < 3;i++)
{
for(int j=0;j<3;j++)
{
cout << setw(7) << array[i][i];
}
cout << endl;
}
fun(array);
cout << "convert front" << endl;
for(int i =0; i < 3;i++)
{
for(int j=0;j<3;j++)
{
cout << setw(7) << array[i][i];
}
cout << endl;
}
}
字符数组
用来存放字符数据的数组是字符数组,字符数组中的一个元素存放一个字符,字符数组具有数组的共同属性。字符数组赋值的方式与数组赋值相同,但聚合方式只能在数组声明的时候使用,字符数组不能给字符数组赋值;字符数组常作为字符串使用,作为字符串要有字符串结束符"\0"。
(1)字符串处理函数
- strcat()函数
字符串连接函数strcat格式如下:
strcat(字符数组名1,字符数组名2)
把字符数组2中的字符串连接到字符数组1中字符串的后面,并删去字符串1后的字符串结束标志“\0”。
实例02 字符串的连接操作
#include <iostream>
#include <string>
using namespace std;
void main()
{
char str1[30],str2[20];
cout << "please input string1:" <<endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
strcat(str1,str2);
cout << "Now the string1 is: " << endl;
puts(str1);
}
- strcpy()函数
字符串复制函数strcpy()格式:
strcpy(字符数组1,字符数组2);
说明:
①字符数组1应有足够的长度,否则不能全部装入所复制的字符串。
②字符数组1必须写成数组名形式,字符数组2可以是字符数组名,也可以是一个字符串常量。
实例03 字符串的复制操作
#include <iostream>
#include <string>
using namespace std;
void main()
{
char str1[30],str2[20];
cout << "please input string1:" <<endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
strcpy(str1,str2);
cout << "Now the string1 is: " << endl;
puts(str1);
}
- strcmp()函数
字符串比较函数strcmp()格式如下:
strcmp(字符数组名1,字符数组名2);
按照ASCII码顺序比较两个数组中的字符串,并由函数返回比较结果:
字符串1=字符串2,返回0;
字符串1>字符串2,返回正数;
字符串1<字符串2,返回负数;
实例04 字符串的比较操作
#include <iostream>
#include <string>
using namespace std;
void main()
{
char str1[30],str2[20];
cout << "please input string1:" <<endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
int res=strcmp(str1,str2);
if(res == 0)
{
cout << "str1 = str2" << endl;
}else if(res > 0)
{
cout << "str1 > str2" << endl;
}else
{
cout << "str1 < str2" << endl;
}
}
- strlen()函数
获取字符串长度函数strlen()格式如下:
strlen(字符数组名)
获取字符串的实际长度(不含字符串结束标志“\0”),函数返回值为字符串的实际长度。
实例05 获取字符串长度
#include <iostream>
#include <string>
using namespace std;
void main()
{
char str1[30],str2[20];
cout << "please input string1:" <<endl;
gets(str1);
cout << "please input string2:" << endl;
gets(str2);
cout << "The length of string1 is:" << strlen(str1) << endl;
cout << "The length of string2 is:" << strlen(str2) << endl;
}
指针
变量与指针
指针是一种数据类型,它是一个专门用来存放地址的变量,变量的指针主要指变量在内存中的地址。
声明指针的一般形式如下:
数据类型标识符 *指针变量名
指针可以在声明的时候赋值,也可以后期赋值。如:
int i = 100;
int *p = &i;
或者
int *p;
p=&i;
指针变量名是p,而不是p;p=&i的意思是取变量i的地址赋给指针变量p;指针变量不可以直接赋值,也不能把p当变量使用。
指针运算符和取地址运算符
“”和“&”是两个运算符,“”是取值运算符,“&”是取地址运算符。
实例06 输出指针对应的数值
#include <iostream>
using namespace std;
void main()
{
int a=100;
int *p=&a;
cout << "a=" << a <<endl;
cout << "*p=" << *p << endl;
}
指针运算
指针变量存储的是地址值,对指针做运算就等于对地址做运算。
实例07 输出指针运算的地址值
#include <iostream>
using namespace std;
void main()
{
int a =100;
int *p=&a;
pringf("address :%d\n",p);
p++;
pringf("address :%d\n",p);
p--;
pringf("address :%d\n",p);
p--;
pringf("address :%d\n",p);
}
指向空的指针和空类型指针
指针可以指向任何数据类型的数据,包括空类型(void),定义如下:
void *p;
空类型指针可以接受任何类型的数据,当使用它时,可以将其强制转化为所对应的数据类型。
实例08 空类型指针的使用
#include <iostream>
using namespace std;
void main()
{
int *p=NULL;
int i=4;
p=&i;
float f=3.33f;
void *pV=NULL;
cout << "依次赋值给空指针" << endl;
pV=p;
cout << "pV = p -------" << *(int *)pV << endl;
cout << "pV = p -------转为float类型指针" << *(float *)pV << endl;
pV = &f;
cout << "pV = &f -------" << *(float *)pV << endl;
cout << "pV = &f -------转为int类型指针" << *(int *)pV << endl;
}
指向常量的指针和指针常量
同其他数据类型一样,指针也有常量,使用const关键字形式如下:
int i = 9;
int * const p = &i;
*p = 3;
将关键字const放在标识符前,表示这个数据本身是常量,而数据类型是int*,即整型指针。与其他常量一样,指针常量必须初始化。无法改变它的内存指向,但可以改变它指向内存的内容。
若将关键字const放到指针类型的前方,形式如下:
int i = 9;
int const* p=&i;
这是指向常量的指针,虽然其所指向的数据可以通过赋值语句进行修改,但是通过该指针修改内容的操作是不被允许的。
当const以如下形式使用时:
int i = 9;
int const* const p = &i;
该指针是一个指向常量的指针常量,既不可以改变它的内存指向,也不可以通过它修改指向内存的内容。
指针与数组
指针与一维数组
系统需要提供一定量连续的内存来存储数组中的各个元素,内存都有地址,指针变量就是存放地址的变量,如果把数组的地址赋给指针变量,就可以通过指针变量来引用数组。引用数组元素有两种方法:下标法和指针法。
- 下标法
int a[10]
int *p;
p=&a[0];
- 指针法
int a[10];
int *p;
p=a;
指针与二维数组
使用指针引用二维数组和引用一维数组相同,首先声明一个二维数组和一个指针变量:
int a[4][3];
int *p;
a[0]是二维数组第一个元素的地址,可以将改地址直接赋值给指针变量。
p=a[0];
或者
p=&a[0][0];
指针与字符数组
字符数组是一个一维数组,使用指针同样也可以引用字符数组,引用字符数组的指针为字符指针,字符指针就是指向字符型内存的指针变量,其一般的定义语句如下:
char *string=“hello world”;
实例09 通过指针偏移连接字符串
#include <iostream>
using namespace std;
void main()
{
char str1[50],str2[30],*p1,*p2;
p1=str1;
p2=str2;
cout << "please input string1:" << endl;
gets(str1);
cout << "please input string2: "<< endl;
gets(str2);
while(*p1!='\0')
p1++;
while(*p2!='\0')
*p1++=*p2++;
*p1='\0';
cout << "The new string is :" << endl;
puts(*p1);
}
指针在函数中的应用
传递地址
实例10 通过传递地址交换两个变量值
#include <iostream>
using namespace std;
void swap(int *a,int *b)
{
int tmp;
tmp=*a;
*a = *b;
*b=tmp;
}
void main()
{
int x,y;
int *p_x,*p_y;
cout << "input two number" << endl;
cin >> x;
cin >> y;
p_x=&x;
p_y=&y;
cout << "按指针传递参数交换" << endl;
swap(p_x,p_y);
cout << "x=" << x << endl;
cout << "y=" << y << endl;
}
指向函数的指针
指针变量也可以指向一个函数,一个函数在编译时被分配一个入口地址,这个函数入口地址就称为函数的指针,可以用一个指针变量指向函数,然后通过该指针变量调用此函数。
定义指针函数的一般形式为:
类型名 *函数名(参数列表);
例如,定义一个具有两个参数和一个返回值的函数的指针:
int sum(int x,int y);
int *a(int,int);
a=sum;
函数指针能指向返回值与参数列表的函数,当使用函数指针时形式如下:
int c,d;
(*a)(c,d);
实例11 使用指针函数计算平均值
#include <iostream>
#include <iomanip>
using namespace std;
int avg(int a,int b);
void main()
{
int ia,ib,iavg;
ia=10;
ib=30;
int (*pfun)(int,int);
pfun=avg;
iavg=(*pfun)(ia,ib);
cout << "avg:" << iavg << endl;
}
int avg(int a,int b)
{
return (a+b)/2;
}
从函数中返回指针
定义一个返回指针类型的函数形式如下:
int *function(param list)
{
int *p;
......;
return p;
}
指针数组
数组中的元素均为指针变量的数组称为指针数组,一维指针数组的定义形式如下:
类型名 *数组名[数组长度]
指针数组中的数组名也是一个指针变量,该指针变量未指向指针的指针。
p是一个指针数组,它的每一个元素是一个指针数据,指针数组p的第一个值是变量a的地址,指针数组中的元素可以使用指向指针的指针来引用,如:
int **p;
引用
引用概述
引用是一种隐式指针,它为对象建立一个别名,通过操作符&来实现。&是取地址操作符,通过它可以获得地址。
引用的形式如下:
数据类型 & 表达式;
引用的使用说明如下:
(1)一个C++引用被初始化后,无法使用它再去引用另一个对象,它不能被重新约束。
(2)引用变量知识其他对象的别名,对它的操作与原对象的操作具有相同作用。
(3)指针变量与引用有两点区别:一是指针是一种数据类型,二引用不是一个数据类型。二是指针变量和引用变量都用例指向其他变量,但指针变量使用的语法要复杂一些,而在定义了引用变量后,其使用方法和普通变量相同。
(4)引用应该初始化,否则会报错。
使用引用传递参数
实例12 通过引用交换两个变量值
#include <iostream>
using namespace std;
void swap(int &a,int &b)
{
int tmp;
tmp=a;
a = b;
b=tmp;
}
void main()
{
int x,y;
int *p_x,*p_y;
cout << "input two number" << endl;
cin >> x;
cin >> y;
cout << "按指针传递参数交换" << endl;
swap(x,y);
cout << "x=" << x << endl;
cout << "y=" << y << endl;
}
数组作为函数参数
实例13 获取命令参数
#include <iostream>
using namespace std;
void main(int argc,char *argv[])
{
cout << "The list of parameter:" << endl;
while(argv>1)
{
++argv;
cout << *argv << endl;
--argc;
}
}