C语言第五次课讲义.docx
《C语言第五次课讲义.docx》由会员分享,可在线阅读,更多相关《C语言第五次课讲义.docx(23页珍藏版)》请在冰豆网上搜索。
![C语言第五次课讲义.docx](https://file1.bdocx.com/fileroot1/2023-1/31/74f46185-976a-41e8-87b1-59b1a639cde1/74f46185-976a-41e8-87b1-59b1a639cde11.gif)
C语言第五次课讲义
第五次课安排
时间
课次
授课标题
上课时长
上午
第一课时
一维数组与指针
50
第二课时
二维数组与指针
50
第三课时
数组与函数
50
下午
第四课时
字符串与字符串数组
50
第五课时
字符串的输入和输出
50
第六课时
对字符串的操作
50
课后
布置习题作业
第十章选择题:
18到39,填空题:
1、2、5、6、7、8、9
第十二章选择题:
14、15、16、17、21;
填空题:
1、2、3、4、7、8
第八章选择题:
21到33,填空题:
1至13
第十二章数组与指针
本章考点
考点
考核几率
分值
指向数组元素的指针
100%
3~4
指向多维数组的指针(难点)
100%
3~4
二级指针及指针数组(难点)
90%
1~3
用数组名作为函数参数
90%
2~3
教学内容
一、一维数组与指针
1.一维数组首地址与数组元素地址
inta[5]={1,2,3,4,5};
(1)数组元素都可以看做一个变量,因此每个元素有一个地址。
例如:
数组a中元素地址分别为:
&a[0]、&a[1]、&a[2]、&a[3]、&a[4]
(2)C语言规定数组名代表数组在内存中的起始地址,即使用a表示数组a的首地址,a等价于&a[0]
(3)a是一个地址常量,它永远指向a数组的首地址。
因此不能对a进行重新赋值,例如:
a++或是a=&i是错误的,换句话说:
数组名不能出现在赋值号的左边
2.通过指针引用一维数组
(1)指针指向首地址
inta[5]={1,2,3,4,5},*p;
p=a;
指针指向了数组的首地址,即存储了数组中第一元素的地址&a[0],因此*p的值为a[0]的值1,依次类推:
p+i表示数组第i个元素的地址,*(p+i)表示第i个元素,p+3表示a[3]表示a[3]地址1012,*(a+3)表示a[3]为4
注意:
由于课本P169例1和例2没有具体输入数据,因此导致学员在理解该例题的时候容易混淆,为了避免此类事情发生,请各位老师不再讲解例1和例2,学员也不用去看,将下列例题讲解清楚即可!
(2)指针指向任意数组元素地址
inta[5]={1,2,3,4,5},*p;
p=&a[2];
重点讲解课本P170例3:
(3)数组名当作指针使用
inta[3]={10,20,30};
a代表数组a的首地址,同时可以将a当作一个指针来使用。
可以理解为下列的表达形式:
重点讲解课本P170例4:
(4)指针名当作数组使用
指针指向了数组中元素的地址,可以将指针当做一个数组使用,但是指针数组的第一个元素从该地址对应的值。
inta[5]={10,20,30,40,50},*p;
p=&a[2];
重点讲解课后习题P50第15题:
二、二维数组与指针
1.二维数组的首地址和数组元素地址
(1)二维数组的组成
inta[2][3]={{1,2,3},{4,5,6}};
二维数组在内存中是连续存储的,下图为二维数组在内存的存储形式:
通常我们也可以使用下图表示上述的地址图:
从图中可以看出,二维数组a是一个2行3列的数组,第一行中的元素为:
a[0][0]、a[0][1]、a[0][2];第二行中的元素为:
a[1][0]、a[1][1]、a[1][2];每行都可以看做一个一维数组,a[0]和a[1]分别表示每行的首地址,a[0]相当于&a[0][0],a[1]相当于&a[1][0],是一个地址常量,不能进行重新赋值。
1)指针指向二维数组中某行的首地址
inta[2][3]={{1,2,3},{4,5,6}};
int*p;
p=a[0];
依次类推:
如果指针p指向了二维数组a的第行行,即p=a[i],则p+j就是从第i行往后数j个元素的地址。
例如:
p=a[5],表示p指向了二维数组的第5行,那么p+3就表示a[5][3]的地址,*(p+3)就表示a[5][3]
(2)二维数组的数组名
inta[2][3]={{1,2,3},{4,5,6}};
1)二维数组名a表示数组a的一个元素的地址,即:
a[0][0]的地址,不能进行a++等赋值操作
2)二维数组名等价于一个二维指针,a[i]是一个一维指针
3)a+i表示&a[i],*(a+i)为a[i],表示第i行的首地址
4)int**q;q=a;是错误的表示方法,不能进行这样的赋值
5)int*p=a;也不能进行这样的赋值,类型不一致!
(3)二维数组中元素及其地址
inta[2][3]={{1,2,3},{4,5,6}};
1)a[i][j]表示第i行第j列的元素
2)&a[i][j]表示第i行第j列元素的地址
3)a[i]表示第i行的首地址,a[i]+j相当于&a[i][j]
4)*(a[i]+j)相当于a[i][j]
5)*(*(a+i)+j)相当于a[i][j]
6)讲解以上的的表达式一定要注意演变过程
2.指针数组与二维数组
(1)指针数组的定义如下:
类型名*指针数组名[常量表达式]
(2)通过指针数组引用二维数组元素(上机考试填空题重点)
(3)重点讲解课本P174例1
(4)
3.行指针与二维数组
(1)定义行指针
类型名(*指针数组名)[常量表达式]
int(*p)[2];表示p只能存放含有2个整型元素的一维数组的首地址,即p相当于是一个二维指针。
int(*p)[2],a[3][2]={{1,2},{3,4},{5,6}};
p=a;/*考试重点,填空题中经常出现该知识点*/
p+i就表示二维数组中第i行的首地址,相当于&a[i]
(2)通过行指针引用二维数组的元素
int(*p)[2],a[3][2]={{1,2},{3,4},{5,6}};
p=a;
p相当于二维数组,p[i][j]相当于a[i][j],其余的等价式可以不讲解
(3)讲解习题P53第30题
三、数组与函数
1.一维数组元素作实参
一维数组元素作实参相当于一个普通的变量,传递的是“值”
2.一维数组名作实参
viodfun(int*a)可以换为:
viodfun(inta[])或viodfun(inta[5])
重点讲解P177例1:
执行for语句:
(1)i=0,判断:
i<5为真,执行:
sum=sum+x[0];sum=1,继续执行i++i=1
(2)i=1,判断:
i<5为真,执行:
sum=sum+x[1];sum=3,继续执行i++i=2
(3)i=2,判断:
i<5为真,执行:
sum=sum+x[2];sum=6,继续执行i++i=3
(4)i=3,判断:
i<5为真,执行:
sum=sum+x[3];sum=10,继续执行i++i=4
(5)i=4,判断:
i<5为真,执行:
sum=sum+x[4];sum=15,继续执行i++i=5
(6)i=5,判断:
i<5为假,循环结束
函数返回值sum为15,s=fun(a,5);将函数返回值赋值给变量s,因此s的值为15
3.一维数组元素地址作实参
p[0]的值为3,p[-1]表示p[0]前面的值为2,p[1]为4,p[0]=p[-1]+p[1]p[0]=6
4.二维数组名作实参
当二维数组名作为实参时,对应的形成必须是一个行指针变量!
viodfun(int(*a)[10])可以换为:
viodfun(inta[][10])或是viodfun(inta[5][10])行下标可以省略,列下标不能省略。
讲解课本P179例3:
5.指针数组作实参
viodfun(int*a[10])可以换作:
viodfun(int*a[])或者是viodfun(int**a)
第八章字符串
本章考点
考点
考核几率
分值
字符串和字符串结束标志
60%
0~1
字符数组和指针对字符串的处理(难点)
100%
2~5
字符串的输入输出
100%
2~3
字符串处理函数
50%
1~2
学习提示
1.本章知识点具有结合性强的特点,因此学习时候一定要注意
2.本章涉及到字符串、数组、指针、函数,因此是考试的重点,笔试占5至10分,上机考试填空题中20%的题目涉及到字符串
教学内容
四、字符串与字符串数组
1.字符串常量
(1)字符串常量:
以双引号括起来的,由若干字符组成的序列
(2)字符串举例:
1)普通字符串:
”xiaoyuan”、”ABC”
2)空字符串:
””/*双引号里面什么也没有*/
3)空格字符串:
””/*双引号里面有一个空格*/
(3)字符串结构:
”字符+\0”
1)在存储字符串是,在字符串最后自动加上’\0’作为字符串的结尾符,’\0’是隐藏的
2)‘\0’是一个转义字符,它的ASCII为0,也称为“空值”
3)‘\0’是字符串结束的标志,如果没有’\0’就不能称为一个字符串。
如同分号是C语言语句结束的标志,没有分号就不能称为一条语句
(4)字符串长度:
第一个’\0’以前的字符个数
1)“xiaoyuan””xiaoyuan\0”字符串的长度为:
8
2)“xiao\0yuan””xiao\0yuan\0”字符串长度为:
4
3)“”字符串长度为0
4)“”字符串长度为1,因为双引号中有一个空格
(5)字符串的总长度:
所有字符个数和所有’\0’个数
1)“xiaoyuan”字符串长为8,总长度为9
2)“xiao\0yuan”字符串长度为4,总长度为10
3)“”字符串长度为0,总长度为1
4)“”字符串长度为1,总长度为2
2.使用一维字符数组存放字符串
(1)通过对单个数组元素赋值
1)先定义后赋值形式
charstr[5];
str[0]=’x’;
str[1]=’i’;
str[2]=’a’;
str[3]=’o’;
str[4]=’\0’;
将单个字符常量赋值给字符数组中的元素,从上面可以看出定义的数组长度为5,分别赋值了4个字符常量:
’x’、’i’、’a’、’o’和1个结束符:
’\0’
2)边定义边赋值形式
采取“一一对应”的赋值方法
3)数组长度大于元素个数
数组长度大于元素个数时,采取一一对应原则进行赋值,不够的部分填充字符’\0’
例
charstr[10]={‘s’,’p’,’e’,’l’,’s’,’\0’};
s
p
e
l
s
\0
\0
\0
\0
\0
字符数组的长度为10,赋值了6个数组元素,不够4个数组元素,因此补充4个’\0’
inta[10]={1,2,3,4,5};
1
2
3
4
5
0
0
0
0
0
数组的长度为10,赋值了5个数组元素,不够5个数组元素,因此补充5个0
4)比较下列的字符数组赋值
(1)charstr[5]={‘x’,’i’,’a’,’o’,’!
’};
str[0]
str[1]
str[2]
str[3]
str[4]
x
i
a
0
!
字符数组str存储的不是一个字符串,因为赋值号的右边没有出项’\0’,因此不能称之为字符串。
(2)charstr[5]={‘x’,’i’,’a’,’o’,’\0’};
str[0]
str[1]
str[2]
str[3]
str[4]
x
i
a
0
\0
字符数组str存储的是一个字符串”xiao”,因为赋值号右边有’\0’
(3)charstr[6]={‘x’,’i’,’a’,’o’,’!
’};
str[0]
str[1]
str[2]
str[3]
str[4]
str[5]
x
i
a
0
!
\0
字符数组str存储的是一个字符串”xiao!
”,因为赋值号右边会自动赋值一个’\0’,因此它是一个字符串
(4)讲解习题4:
正确的字符串语句是:
A)charstr[]={‘\046’};B)charstr=“\x43”
C)charstr=‘’;D)charstr[]=“\0”;
(2)直接将字符串常量赋值给字符数组
charstr[10]={“xiaoyuan”};或
charstr[10]=“xiaoyuan”;
charstr[10];
str=“xiaoyuan”;/*这种赋值方式是错误的,因为str是一个数组名,不能对数组名进行赋值运算*/
3.使用指针指向字符串
讲解例7、8
char*p=“xiaoyuan”;
char*p;
p=“xiaoyuan”;
讲解课本P109习题3
chars[20]=“Beijing”,*p;
p=s;
4.二维字符数组存放字符串数组
讲解例11:
charname[4][10]={“I”,”am”,”a”,”teacher”};
name[0]
I
\0
\0
\0
\0
\0
\0
\0
\0
\0
name[1]
a
m
\0
\0
\0
\0
\0
\0
\0
\0
name[2]
a
\0
\0
\0
\0
\0
\0
\0
\0
\0
name[3]
t
e
a
c
h
e
r
\0
\0
\0
五、字符串的输入和输出
1.字符串的输出
(1)使用printf函数输出字符串:
用%s格式控制符,输出列表是字符串的首地址
1)讲解P109例1:
charstr[]=“Hello,xiaoyuan!
”;
printf(“%s”,str);
2)讲解P109例2:
charstr[]=“Hello,xiaoyuan!
”;
printf(“%s”,str+6);
3)讲解P109例3:
charstr[]=“Hello\0,xiaoyuan!
”;
printf(“%s”,str);
4)讲解习题p61第16题
main()
{charstr[][10]={“China”,”Bejing”},*p=str;
printf(“%s\n”,p+10);
}
C
h
i
n
a
\0
\0
\0
\0
\0
B
e
i
j
i
n
g
\0
\0
\0
5)讲解习题P61第17题
main()
{
chars[]=“ABCD”,*p;
for(p=s+1;p
printf(“%s\n”,p);
}
(2)使用puts函数输出字符串:
puts(字符串首地址)
讲解P110例4:
char*p=“Hello,xiaoyuan!
”;
printf(“%s”,p);
puts(p);
2.字符串的输入
(1)scanf函数:
采用%s格式控制符,制表符、空格和回车不读入
讲解P110例5:
charstr[20];
scanf(“%s”,str);
输入:
xiaoyuan!
<回车>xiaoyuan!
\0
输入:
xiaoyuan!
<回车>xiao\0
(2)gets函数:
gets(待输入字符串的首地址),制表符、空格和回车读入
讲解P110例6:
charstr[20];
scanf(“%s”,str);
输入:
xiaoyuan!
<回车>xiaoyuan!
\0
输入:
xiaoyuan!
<回车>xiaoyuan\0
(3)讲解P111习题2:
六、对字符串的操作
1.字符串拷贝
char*strcopy(char*d,char*s)
{char*p=d;
while(*s!
=‘\0’)
{*p=*s;
p++;s++;
}
*p=‘\0’;
}
strcpy(d,s);:
将字符串s赋到字符串d的存储空间中将字符串s赋到字符串d的存储空间中。
红色部分为上机考试中填空题中经常考查的知识点!
2.字符串求长度
intstrlength(char*str)
{inti=0;
while(str[i]!
=’\0’)
i++;
returni;
}
strlen(s);:
求字符串s的长度。
红色部分为上机考试中填空题中经常考查的知识点!
3.字符串连接
charstrcat(char*d,char*s)
{intlen;
len=strlen(d);
while(*s!
=‘\0’)
{*d=*s;
d++;s++;
}
*d=‘\0’;
}
strcat(d,s);:
将字符串s赋值到字符串d的后面。
红色部分为上机考试中填空题中经常考查的知识点!
4.字符串比较
intstrcompare(char*s1,char*s2)
{while(*s1!
==*s2&&*s1)
{
s1++;s2++;
}
return(*s1-*s2);
}
strcmp(s1,s2);:
比较s1和s2两个字符串的大小。
红色部分为上机考试中填空题中经常考查的知识点!
5.讲解P113习题
(1)习题1
char*x=“abcdefghi”;
A)chary[10];strcpy(y,x[4]);
B)chary[10];strcpy(++y,&x[1]);
C)chary[10];strcpy(s=y+5,x);
D)chary[10];strcpy(s=y+1,x+1);
分析:
A答案中strcpy(y,x[4]);x[4]为数组元素,strcpy只能对字符串或是指针进行赋值,因此strcpy(y,x[4]);是错误的,改为:
strcpy(y,&x[4]);才正确;
B答案中strcpy(++y,&x[1]);++y是错误的,因为y是数组名,不能进行赋值运算
C答案中strcpy(s=y+5,x);y+5表示从数组中下标为5的位置开始,没有足够的存储空间容纳字符串“abcdefghi”
D答案中strcpy(s=y+1,x+1);正确
(2)习题2
main()
{charp[20]={‘a’,’b’,’c’,’d’},q[]=“abc”;
charr[]=“abcde”;
strcat(p,r);
strcpy(p+strlen(q),q);
printf(“%d\n”,strlen(p));
}
分析:
strcat(p,r);将字符串p连接到字符串r的后面,则r字符串为:
“abcddeabcd”
strcpy(p+strlen(q),q);strcpy(p+3,q);将字符串q赋值到以p+3开始的空间中,则字符串p为:
“abcabc”
printf(“%d\n”,strlen(p));输出字符串p的长度为:
6
(3)习题3