第七章数组
*****2016年1月24日09:29:58
*韩–
*主要内容:数组是类型相同数据的集合
1、数组概述
2、一维数组的声明、初始化、使用
3、数组的运算、函数作为函数参数的用法
4、字符数组、字符串,以及字符串处理函数
5、多维数组的声明与使用、存储结构、初始化方法
6、冒泡排序、矩阵运算、分治与二分查找、
逆波兰表达式的生成,以及基于栈值的逆波兰表达式求值
//7-1数组概述
数组是确定个数的类型相同数据的集合,数组属于构造类型,他是相同数据类型数据的集合
数组的特点:{
1、数组中的元素按顺序在内存中连续存放
2、数组内各个元素的数据类型相同
3、数组由数组名和下标构成,数组名是数组的首地址
4、下标由小到大,地址由低到高
}
//7-2一维数组
可用于表示一个线性数据队列
先声明、初始化,然后使用{
声明:{
形式:
[存储类型说明符][类型修饰符] 类型说明符 数组名[常量表达式]={初值表};
//存储类型说明符:extern(修饰成外部数组)、static(修饰成静态数组)
//类型修饰符:const(常量数组)、volatile可变数组
///可变数组:指元素之值可以被其他程序修改,如中断服务程序
//数组名是一个标识符,是一个地址常量,元素的首地址,内存的起始地址
///数组名具有非左值特性,因此不能对数组名进行赋值操作
//[]:下标操作符,系统提供的预定义函数
数组声明举例:{
///几种声明形式:
# define SIZE 10 //
int arry[5]; //声明一个数组
double d[5],e[SIZE]; //同时声明两个数组
char name[SIZE*5]; //常量表达式
///C99之后的标准中合法(visulC++ 6.0中非法):
unsigned int size = 10;
char str[size],buffer[2*size];
///带类型修饰符的声明:
static int y[10];
extern double s[2]; //一个外部函数的引用性说明
}
}
初始化:{
int y[5] = {1,2,3,4,5}; //初值表初始化,该处数组所有的值
double d[] = {1.2,2.3,21.3};//初值表中的初值个数决定数组长度
int a[5] = {5,3,2}; //部分初始化只能省略最右边连续初值
///error:
int b[6] = {1,,3,,5,}; //
/** 具有局部作用域的初值,如果不初始化,元素默认是随机的。
对于外部数组和静态数组其默认值为为0**/
}
使用:注意下标越界
}
存储结构:{
//数组中的元素从数组名标明的起始地址按顺序在内存中连续存放
//不同类型的数组由与元素的类型不同,每个元素在内存中占有的字节数也不同
//下标加1,数组元素地址加 1*一个数组元素类型所占的的字节数
}
数组运算:{
//只支持数组元素间的运算以及数组元素下标的运算
}
一维数组作为函数调用:{
//在c语言中参数的传递分为两类:参数传值、参数传址
//数组作为函数参数时可用参数名或者数组元素的地址作为实参
//在被调用函数中,将形参声明为形式数组(即在方括号表示的下标操作符中不给出下表的数组)
冒泡排序:{
# include <stdio.h>
void bubble(int a[],int len)
///(int a[],int len)形参中的int a[]其实就等于int *a;即形参中的数组便是指针
{
int i,j,temp;
for(i=0;i<len-1;i++)//论len-1的重要性,防止非法访问
for(j=0;j<len-1-i;j++)
if(a[j]>a[j+1])
{
temp = a[j],
a[j] = a[j+1],
a[j+1] = temp;//逗号表达式
}
for(i=0;i<len;i++)
printf("%d\t",a[i]);
}
int main(void)
{
int x[] = {12,23,44,21,3,44,45};
bubble(x,sizeof(x)/sizeof(int));
return 0;
}
}
数组与指针:{
四种等价的函数原型(在形参中出现):{
int fun(int *a,int b);
int fun(int *,int);
int fun(int a[],int b);
int fun(int [],int);
}
数组变量是特殊的指针:{
/*************形参中的数组*******************/
# include <stdio.h>
void fun(int *a,int len)
{
printf("fun sizeof(a) = %d\n",sizeof(a));
a[0] = 1000;
*(a+1) = 2000;
}
int main()
{
int a[5] = {1,2,3,4,5};
printf("main sizeof(a) = %d\t",sizeof(a));
fun(a,sizeof(a)/sizeof(int));
printf("run_fun:a[0] = %d\n",a[0]);
printf("run_fun:*a = %d\t*(a+1) = %d\n",*a,*(a+1));
///对数组名同样可以当作指针操作
return 0;
}
/***************输出结果***********************
main sizeof(a) = 20 fun sizeof(a) = 4
run_fun:a[0] = 1000
run_fun:*a = 1000 *(a+1) = 2000
**********************************************/
总结:{
1、方括号运算符对指针数组都可以用[]
2、数组变量是const的指针变量,不能被赋值
int a[] <==> int * const a;
}
}
}
}
//7-3多维数组
数组的引入是为了能够通过使用下标来访问数组中指定的元素,通过循环和下标就可以实现数组元素的快捷调用
而有时一个下标并不能满足应用需求,需要多个下标,于是引入多维数组{
声明与使用:
声明形式:
///类型说明 数组名[常量表达式1][常量表达式2]…[常量表达式n] = {初值表};
///类型说明:存储类型说明符 类型修饰符 数据类型
使用:注意下标越界
存储结构:按行存储,连续存放
初始化:按行存储,连续存放,用大括号分隔增强可读性
}
//7-4字符数组
简单介绍:{
字符数组是数组元素的数据类型都是char或wchar_t的一维数组
///即:字符数组是C语言用来存放字符串(字符序列)的工具,并在末尾放一个“\0”作为字符串的终结
///因此:字符串长度 = 字符串的存储长度 - 1;
}
字符数组的初始化:{
char str[] = "this is a C program!";//数组长度自动为21
///也可以这样,但不方便:
char str[30] = "this is a C program!";//总不能每次都要数一下字符串有多么长吧
char str[30] = {'t','h','i','s',' ',……,'a','m','!','\0'}//太麻烦啦!!!!
}
常用的字符串处理函数:{
1、求给定字符串的长度
int strlen(char s[])
{
int j = 0;
while(s[i] != '\0')
j++;
return j;
}
2、将一个字符串复制到另一个字符串
void stpcpy(char s1[],char s2[])
{
int j = 0;
while(s1[j] = s2[j++]);
}
3、比较两个字符串
int strcmp(char s1[],char s2[])
{
int j = 0;
while(s1[j]==s2[j]&&s1[j]!=0)
j++;
return s1[j]-s2[j];
}
4、判断是否为原字符串的子串
int strstr(char s1[],char s2[])
{
int j=0,k;
while(s1[j] != '\0')
{
if(s1[j] == s2[0])
{
k=1;//
while(s1[j+k]==s2[k] && s2[k]!='\0')
k++;
if(k == strlen(s2))
return j;
}
j++;
}
return -1;
}
5、删除字符串首尾空白字符
int strdel(char s[])
{
int i=0,j=0;
int l = strlen(s)-1; //由于'\0'和s[0]的存在
while(s[i]=='\n'||s[i]=='\t'||s[i]==' ')
i++;
while(s[len-j]=='\n'||s[len-j]=='\t'||s[len-j]==' ')
j++;
s[len-j] = '\0';
strcpy(s,s+i);
return strlen(s);//返回删掉之后的字符串的长度
}
6、删除字符串中的所有某个给定字符
void del_ch(char s[],char ch)
{
int i=0,k=0;
while(s[i] != '\0')
{
if(ch != s[i])
s[k++] = s[i];
i++;
}
s[k] = '\0';
}
7、令一个字符串反转
void reverse(char s[])
{
int j,k,temp;
for(j=0,k=strlen(s)-1;j<k;j++,k--)
temp=s[j],s[j]=s[k],s[k]=temp;
}
8、将两个字符串连接
char * strcat(char t[],char s[])
{
int j=0,k=0;
while(t[j++] != '\0');
j--;
while((t[j++]=s[k++]));
return t;
}
}
数字串与数值之间转换的函数{
1、将十进制字符串转化成对应的整数
# define BASE 10
int atoi(char s[])
{
int j, sum = 0;
for(j=0;s[j]!='\0';j++)
num = num*BASE + s[j] - '\0';
return num;
}
2、将一个基数为BASE的整数转换成数字串
void itoa(int n,char s[])
{
int sign, j=0;
if( (sign=n)<0 )
n = -n;
while(n>0)
{
s[j++] = n%BASE + '0';
n/=BASE;
}
if(sign<0)
s[j++] = '-';
s[j] = '\0';
reverse(s);
}
}
二维字符数组{
初始化:
char s[2][5] = {"one","two"};
使用:
某一行的首地址为:
数组名[该行下标] //即:&数组名[该行下标][0]
}
//7-5数组的应用
矩阵乘法运算{
# include <stdio.h>
# define L 3
# define M 4
# define N 5
void mul_matrix(int a[][M],int b[][N],int result[][N],int l,int m,int n)
{
int i,j,k,sum = 0;
for(i=0;i<l;i++)
for(j=0;j<n;j++)
{
for(k=0;k<m;k++)
sum += a[i][k]*b[k][j];
result[i][j] = sum;
}
}
int main()
{
int a[L][M] = {{1,2,3,4},{1,2,3,4},{1,2,3,4}};
int b[M][N] = {{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5}};
int c[L][N];
int i,j;
mul_matrix(a,b,c,L,M,N);
for(i=0;i<L;i++)
{
for(j=0;j<N;j++)
printf("%5d",c[i][j]);
printf("\n");
}
return 0;
}
}
基于分治策略的二分查找函数{
# include <stdio.h>
int Binary_Search(int a[],int search_aim,int num)
{
int front = 0,back = num-1,middle;
while(front <= back)
{
middle = (front + back)/2;
if(search_aim < a[middle])
back = middle-1;
else if(search_aim > a[middle])
front = middle+1;
else
return middle;
}
return -1;
}
int main()
{
int aim = 9;
int index;
int a[] = {1,2,3,4,5,6,7,8,9,12,23};//必须是按升序排列
index = Binary_Search( a, aim, sizeof(a)/sizeof(int));
if(index != -1)
printf("find %d,and the address is %d\n",aim,index+1);
else
printf("not find!!!\n");
return 0;
}
}
逆波兰表达式的生成{
}
利用值栈对逆波兰表达式进行求值{
}