从零开始学编程---第一步-C语言(二十六)

时间:2014-03-09 00:41    点击:

大家还记得指针数组吧,它就有点类似于二维数组
先看
char a[]="aaa" b[]="bbbb" c[]="hello world";
char *p[3]={a,b,c};

这里是一个有3个元素的指针数组,数组名是p,注意不是*p
它有3个元素,p[0],p[1],p[2],分别指向,a,b,c3个数组
这和二维数组的行数组是一样的
数组名p是数组p[0]的地址,p[0]又是a[0]的地址,p相当于指针的指针,这点和二维数组名是一样的,但p是个实实在在的指针类型,可以用二级指针(之后将介绍)来指向,而二维数组名却不能
指针数组不能用数组指针来指向,数组指针指向的是多少长度的数组,二维数组满足这一条件,它的所有数组(列数组)都是同一长度,所以数组指针可以指向二维数组
而指针数组里的元素(也就是数组),它们的长度并不是绝对相等
比如上面a,b,c3个数组并不是同一长度
还有指针数组并非一定要指向数组,指向变量也是可以的
比如
int a,b,c;
int *p={&a,&b,&c}

所以说,指针数组和二维数组不能划等号,只能说,指针数组在元素都指向数组且数组长度都一致的时候,才像二维数组

现在继续,还是二维数组
做个关于矩阵的题目
什么是矩阵
这就是一个矩阵
1 2 3 
4 5 6
(并不是需要数字按顺序)
这其实就是一个2行3列的二维数组
把这个矩阵定义为二维数组a
这里又一个矩阵
1 2 3 4
5 6 7 8
9 10 11 12
定义为一个3行4列的二维数组b
现在要做什么呢?
我们把这两个矩阵相乘,得到一个新的矩阵
怎么相乘
a矩阵的行乘以b矩阵的列,然后相加
也就是 矩阵a 的第一行乘以矩阵b的第一列
1 2 3 去乘以 1 5 9
1*1+2*5+3*9=38
以此类推
会得到结果
38 44 50 56 
83 98 113 128
这便是一个新的矩阵c

现在开始做
先定义3个二维数组
a[2][3],b[3][4] c[2][4]
代码如下
#include <stdio.h>
main()
{
int a[2][3],b[3][4],c[2][4];
int i,j,k;

//输入矩阵a的所有元素
for(i=0;i<2;i++)

printf("请输入矩阵a第%d行的3个元素:",i+1);
for(j=0;j<3;j++)
scanf("%d",&a[i][j]);

}

//输入矩阵b的所有元素
for(i=0;i<3;i++)

printf("请输入矩阵b第%d行的4个元素:",i+1);
for(j=0;j<4;j++)
scanf("%d",&b[i][j]);

}

//矩阵a乘以矩阵b得到矩阵c的结果
for(i=0;i<2;i++)
for(j=0;j<4;j++)

c[i][j]=0;
for(k=0;k<3;k++)
c[i][j]+=a[i][k]*b[k][j];


}

//输出矩阵c
for(i=0;i<2;i++)
{
for(j=0;j<4;j++)

printf("%d",c[i][j]);
putchar(' ');

}
putchar('\n');
}


}

需要理解的也就这3句
c[i][j]=0;
for(k=0;k<3;k++)
c[i][j]+=a[i][k]*b[k][j];

先把c数组的每个循环到的元素初始化为0
然后a数组第一行元素乘以b数组第一列元素,得到的结果累加
便得到c数组的各个元素
c[i][j]也可写为*(c[i]+j),其他也一样

现在到学二维数组的尾声了
先看代码
#include <stdio.h>
main()
{
int a[2][3]={1,2,3,4,5,6};
int (*p)[3]=a;
int i,j;

puts("请输入行:");
scanf("%d",&i);
puts("请输入列:");
scanf("%d",&j);

printf("a[%d][%d]=%d",i,j,*(*(p+i)+j));


}

这段代码用了指针,最后的*(*(p+i)+j)等于p[i][j]
这段代码的功能很简单,相信不用我说了
这里多讲一下
存储器单元是连续编址的,也就是说,存储单元是按一维线性排列的
二维数组的元素其实也可作为一维数组下标访问
也就是只有一行,即0行
上面的二维数组元素可以为a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5],
不去看0,这就相当于个一维数组,可以运行上面的代码试试
好了,二维数组暂告一段落

现在开始介绍指针指向字符串

在C语言中,可以用两种方法访问字符串
第一种我们很熟悉
char a[]="hello";
printf("%s",a);

第2中便是指针来访问字符串
char *a="hello";
printf("%s",a);

一个是数组,一个是指针
一个所有元素是变量,一个所有元素是常量

其实指针字符串是一个指针指向一个常量字符串的首地址
char *p; 这是定义了一个字符指针
“hello” 这是一个字面量常量的字符串,在内存里也是一个一个字符存储的,后面也有'\0',有存储空间和地址,和数组字符串构造一样,只不过没有常量数组名,每个元素也没有常量名,它就是个数组,只不过没有数组名而已,它是不可更改的
p="hello"; 这就是把'h'的地址存储到指针变量p中
一般是在一开始定义的时候就给初始化
如:char *p="hello" 这相当于一个字符串变量一样(C语言是没有字符串变量的)

这跟下面类似
char a[6]="hello";
char *p=a;
看,是不是最后就是 p="hello"
只不过原来的char *p="hello" 连定义数组都给省去了
也难怪,其实数组名就相当于一个指针(常量指针),两个同样都是一个指针指向一个字符串的首地址(字符串就是数组,凡是在“”内的任何元素都为字符串,皆为数组)
访问字符串就是访问一个数组,所以只需要字符串的首地址就可以了
如打印和输入,都只需要字符串的首地址,而不需要其他元素的地址
printf("%s",p);scanf("%s",p)
只有字符串才能通过首地址一次读取所有元素
字符数组,数值数组这些通过首地址只能依次读取所有元素

char name{}="hello";
char *name="hello";
两者的区别在哪呢?
一个是变量数组,一个是常量数组
一个是常量指针,一个是变量指针 

char name{}="hello";
假如我要改name的内容怎么做呢?
绝对不是一个个元素修改
而需要用strcpy()函数,貌似我前面已经说过了
如果要把name的内容改为world,这样就可以了
char name[]="hello";
strcpy(name,"world");

但是注意你要修改的内容不能超过6个字符(6个字符已经是数组越界了,很危险的做法)
因为char name[]="hello"; []的下标实际上从你初始化之后就是6了
可见,用数组的字符串要修改内容还得考虑数组的长度,这点很麻烦

而char *name="hello";
要修改内容只需要指针指向另一个字符串的首地址就OK了
如char *name="world"
当然,你可以指向任意长度的字符串,不用再考虑长度了,这点很爽吧
那么以前指向的字符串比如hello还在不在?
答案是还在的,它还留在内存中,随着程序结束而结束
看下面的程序清楚了
#include <stdio.h>
main()
{
char *p="hehe";
printf("%d",p);
//后三句代码是得到地址之后才加上去的
p="haha";
char *a=(char *)4337592; //强制转换类型
printf("%s",a);

}

首先用十进制打印指针p的内容,也就是地址,我这里显示的是4337592,每个电脑会不一样
然后p重新指向“haha ”,再定义一个指针a指向原来的"hehe"的首地址(指针指向地址需要强制转换类型,还没有介绍),然后在打印a就可以打印之前p指向的字符串“hehe”。



一个指向字符串的指针(简称字符串指针)虽然可以直接修改(就是指向其他的字符串)字符串的内容,但也是在代码上修改
如char *name="hello";
name =“world”;

如果要手动修改怎么弄?
这样?
char *name="hello"
gets(name);

那就大大的错了

char name[10];
gets(name);
这样是对的,因为name的地址是固定不变的


char *name="hello"
gets(name);

gets()函数并不知道传入的是个指针变量,因为name的地址随时可能改变,会有可能会改写其他的数据区域

怎么手动让指针变量指向别的字符串?
这就需要让指针先指向一个数组名,因为数组名的地址是固定的
我们定义一个字符数组 a[50]
这样就可以手动修改字符串指针的指向了
#include <stdio.h>
main()
{
char *p="helo";
char a[50];
p=a;
gets(p);
puts(p);
}

但借助数组才能手动赋值这种字符串指针并不算真正意义上的字符串变量
C语言也本来就没有字符串变量,字符串也都是靠字符数组来实现的
指针字符串一般只用于直接初始化的字符串
比如我要定义一个包含5个同学名字的数组
一般情况下就是定义个二维数组

char name[5][20]={"aa","bb","cc","dd","ee"};
而有了指针字符串就可以这样了
只需要定义一个指针数组
char *name[5]={"aa","bb","cc","dd","ee"};

用一维数组总比二维数组简单多吧

记住,指针字符串它不是变量,别想着是把一个字符串存到一个指针里

看下面的代码应该更清楚
#include <stdio.h>
main()
{
char *p="hello world";
p=p+6;
puts(p);

}
指针p在这个数组往后移动5个地址(自己从0开始),数组第6个地址的内容是w,则指向这个地址
最后打印world




 

来源:幻想编程//所属分类:站长原创/更新时间:2014-03-09 00:41
顶一下
(7)
100%
踩一下
(0)
0%
上一篇:从零开始学编程---第一步-C语言(二十五)
下一篇:从零开始学编程---第一步-C语言(二十七)
相关内容