标题:
C基础教程 第十一章 指 针(下)
[打印本页]
作者:
苹果也疯狂
时间:
2011-10-21 12:34
标题:
C基础教程 第十一章 指 针(下)
9.4
字符串的指针和指向字符串的指针变量
字符串在内存中的起始地址称为字符串的指针,可以定义一个字符指针变量指向一个字符串。
9.4.1
字符串的表示与引用
在C语言中,既可以用字符数组表示字符串,也可用字符指针变量来表示;引用时,既可以逐个字符引用,也可以整体引用。
1.
逐个引用
[
案例
9.8]
使用字符指针变量表示和引用字符串。
/*
案例代码文件名:
AL9_8.C*/
main()
{char *string=”I love Beijing.”;
for(; *string!=’\0’; string++) printf(“%c”, *string);
printf(“\n”);
}
程序运行结果:
I love Beijing.
程序说明:
char*string="I love Beijing.";
语句
定义并初始化字符指针变量
string
:用串常量“
I love Beijing.
”的地址(由系统自动开辟、存储串常量的内存块的首地址)给
string
赋初值。
该语句也可分成如下所示的两条语句:
char*string
;
string="I love Beijing."
;
注意:字符指针变量
string
中,仅存储串常量的地址,而串常量的内容(即字符串本身),是存储在由系统自动开辟的内存块中,并在串尾添加一个结束标志’
\0
’。
2.
整体引用
[
案例
9.9]
采取整体引用的办法,改写
[
案例
9.8]
。
/*
案例代码文件名:
AL9_9.C*/
/*
程序功能:使用字符指针变量表示和引用字符串
*/
main()
{char *string=”I love Beijing.”;
printf(“%s\n”,string);
}
[
程序演示
]
程序说明:
printf("%s\n",string);
语句
通过指向字符串的指针变量
string
,整体引用它所指向的字符串的原理:系统首先输出
string
指向的第一个字符,然后使
string
自动加1,使之指向下一个字符;重复上述过程,直至遇到字符串结束标志。
注意:其它类型的数组,是不能用数组名来一次性输出它的全部元素的,只能逐个元素输出。
例如:
int array[10]={……};
......
printf("%d\n",array);
/*
这种用法是非法的
*/
......
3.
字符指针变量与字符数组之比较
虽然用字符指针变量和字符数组都能实现字符串的存储和处理,但二者是有区别的,不能混为一谈。
(
1
)存储内容不同。
字符指针变量中存储的是字符串的首地址,而字符数组中存储的是字符串本身(数组的每个元素存放一个字符)。
(
2
)赋值方式不同。
对字符指针变量,可采用下面的赋值语句赋值:
char
*pointer;
pointer="This is a example.";
而字符数组,虽然可以在定义时初始化,但不能用赋值语句整体赋值。下面的用法是非法的:
char
char_array[20]
;
char_array="This is a example.";
/*
非法用法
*/
(
3
)指针变量的值是可以改变的,字符指针变量也不例外;而数组名代表数组的起始地址,是一个常量,而常量是不能被改变的。
9.4.2
字符串指针作函数参数
[
案例
9.10]
用函数调用方式,实现字符串的复制。
/*
案例代码文件名:
AL9_10.C*/
/**********************************************************/
/*string_copy()
函数:复制一个字符串
*/
/*
形参:字符指针
str_from
接收源串,字符指针
str_to
存储目标串
*/
/*
返回值:无
*/
/**********************************************************/
void string_copy(char *str_from, char*str_to)
{int i=0;
for(; (*(str_to+i)=*(str_from+i))!=
’
\0
’
; i++) ; /*
循环体为空语句
*/
}
main()
{char array_str1[20]=”I am a teacher.”;
char array_str2[20];
string_copy(array_str1, array_str2); /*
数组名作实参
*/
printf(“array_str2=%s\n”, array_str2);
}
程序运行结果:
I am a teacher.
程序说明:
for(;(*(str_to+i)=*(str_from+i))!=
’
\0
’
; i++) ;
语句的执行过程为:首先将源串中的当前字符,复制到目标串中;然后判断该字符(即赋值表达式的值)是否是结束标志。如果不是,则相对位置变量
i
的值增
1
,以便复制下一个字符;如果是结束标志,则结束循环。其特点是:先复制、后判断,循环结束前,结束标志已经复制。
在
C
语言中,用赋值运算符、而不是赋值语句来实现赋值操作,能给某些处理带来很大的灵活性,该语句(实现字符串的复制)的用法就是最好的例证。
9.5
返回指针值的函数
一个函数可以返回一个
int
型、
float
型、
char
型的数据,也可以返回一个指针类型的数据。
返回指针值的函数(简称指针函数)的定义格式如下:
函数类型
*
函数名
([
形参表
])
[
案例
9.11]
某数理化三项竞赛训练组有
3
个人,找出其中至少有一项成绩不合格者。要求使用指针函数实现。
/*
案例代码文件名:
AL9_11.C*/
/*************************************************************/
/*seek()
函数:判断是否有不合格成绩
*/
/*
形参:指向由
3
个
int
型元素组成的
1
维数组的行指针变量
*/
/*
返回值:
(1)
有不合格成绩,则返回指向本行首列的一个
(
列
)
指针;
*/
/*
(2)
没有有不合格成绩,返回值为指向下一行的一个
(
列
)
指针
*/
/*************************************************************/
int
*seek( int
(*pnt_row)[3] )
{int i=0, *pnt_col;
/*
定义一个
(
列
)
指针变量
pnt_col */
pnt_col=*(pnt_row+1);
/*
使
pnt_col
指向下一行之首
(
作标志用
)*/
for(; i<3; i++)
if(*(*pnt_row+i)<60)
/*
某项成绩不合格
*/
{ pnt_col=*pnt_row; /*
使
pnt_col
指向本行之首
*/
break;
/*
退出循环
*/
}
return(pnt_col);
}
/*
主函数
main
()
*/
main()
{int grade[3][3]={{55,65,75},{65,75,85},{75,80,90}};
int i,j,*pointer;
/*
定义一个
(
列
)
指针变量
pointer */
for(i=0; i<3; i++)
/*
控制每个学生
*/
{ pointer=seek(grade+i);
/*
用行指针作实参,调用
seek()
函数
*/
if(pointer==*(grade+i))
/*
该学生至少有一项成绩不合格
*/
{ /*
输出该学生的序号和各项成绩
*/
printf(“No.%d gradelist: ”, i+1);
for(j=0; j<3; j++)printf(“%d
”,*(pointer+j));
printf(“\n”);
}
}
}
[
程序演示
]
程序运行结果:
No.1 grade list: 55
65
75
程序说明:
(
1
)
主函数中的
pointer=seek(grade+i);
语句
调用
seek()
函数时,将实参
grade+i
(行指针
)
的值,复制到形参
pnt_row
(行指针变量
)
中,使形参
pnt_row
指向
grade
数组的第
i
行。
(
2
)在指针函数
seek()
中:
1
)
pnt_col=*(pnt_row+1);
语句
*(pnt_row+1)
将行指针转换为列指针,指向
grade
数组的第
i+1
行第0列,并赋值给(列)指针变量
pnt_col
。
2
)
if(*(*pnt_row+i)<60)
行
pnt_row
是一个行指针,指向数组
grade
的第
i
行;
*pnt_row
使指针由行转换为列,指向数组
grade
的第
i
行0列;
*pnt_row+j
的值还是一个指针,指向数组的第
i
行第
j
列;
*(*pnt_row
+
j)
是一个数据(数组元素
grade
[j]
的值)。
9.6
指针数组与主函数
main()
的形参
9.6.1
指针数组
1.
概念
数组的每个元素都是一个指针数据。指针数组比较适合用于指向多个字符串,使字符串处理更加方便、灵活。
2.
定义格式
数据类型
*
数组名
[
元素个数
]
注意:与行指针变量定义格式“
<
数据类型
>(*
行指针变量
)[<
元素个数
>]
”的差别。
[
案例
9.12]
有若干计算机图书,请按字母顺序,从小到大输出书名。解题要求:使用排序函数完成排序,在主函数中进行输入输出。
/*
案例代码文件名:
AL9_12.C*/
/*
程序功能:指针数组应用示例
*/
/***********************************************/
/* sort()
函数:对字符指针数组进行排序
*/
/*
形参:
name--
字符指针数组,
count--
元素个数
*/
/*
返回值:无
*/
/***********************************************/
void
sort(char *name[], int count)
{char *temp_p;
int i,j,min;
/*
使用选择法排序
*/
for(i=0; i<count-1; i++)
/*
外循环:控制选择次数
*/
{ min=i;
/*
预置本次最小串的位置
*/
for(j=i+1; j<count; j++)
/*
内循环:选出本次的最小串
*/
if(strcmp(name[min],name[j])>0)
/*
存在更小的串
*/
min=j;
/*
保存之
*/
if(min!=i)
/*
存在更小的串,交换位置
*/
temp_p=name
,name
=name[min],name[min]=temp_p;
}
}
/*
主函数
main()*/
main()
{char *name[5]={“BASIC”,”FORTRAN”,”PASCAL”,”C”,”FoxBASE”};
int i=0;
sort(name,5);
/*
使用字符指针数组名作实参,调用排序函数
sort()*/
/*
输出排序结果
*/
for(; i<5; i++) printf(“%s\n”,name
);
}
[
程序演示
]
程序运行结果:
BASIC
C
FORTRAN
FoxBASE
PASCAL
程序说明:
(
1
)实参对形参的值传递:
sort(
name
,
5 )
;
↓
↓
void sort(char *name[], int count)
(
2
)字符串的比较只能使用
strcmp()
函数。形参字符指针数组
name
的每个元素,都是一个指向字符串的指针,所以有
strcmp(name[min],name[j])
。
9.6.2
主函数
main()
的形参
在以往的程序中,主函数
main()
都使用其无参形式。实际上,主函数
main()
也是可以指定形参的。
[
案例
9.13]
用同一程序实现文件的加密和解密。约定:程序的可执行文件名为
lock.exe
,
其用法为:
lock +|- <
被处理的文件名
>
,其中“
+
”为加密,“
-
”为解密。
/*
案例代码文件名:
AL9_13.C*/
/*
程序功能:带参主函数的应用示例
*/
main(int argc, char *argv[])
{char c;
if (argc != 3) printf("
参数个数不对!
\n");
else
{ c=*argv[1];
/*
截取第二个实参字符串的第一个字符
*/
switch(c)
{ case '+':
/*
执行加密
*/
{ /*
加密程序段
*/
printf("
执行加密程序段。
\n");
}
break;
case '-':
/*
执行解密
*/
{ /*
解密程序段
*/
printf("
执行解密程序段。
\n");
}
break;
default: printf("
第二个参数错误!
\n");
}
}
}
1.
主函数
main()
的有参形式
main(int argc
,
char *argv[])
{ … …}
2.
实参的来源
运行带形参的主函数,必须在操作系统状态下,输入主函数所在的可执行文件名,以及所需的实参,然后回车即可。
命令行的一般格式为:
可执行文件名实参
[
实参
2
……
]
例如,本案例程序的用法:
lock
+|-
<
被处理的文件名
>
←┘
●在
TC
的集成环境下,也可直接利用
Options | Arguments
项,输入主函数所需要的实参:只须输入各参数(相邻参数间用空格分开),可执行文件名可省略。
就本案例而言,输入“
+|-
<
被处理的文件名
>
”即可。
3.
形参说明
(
1
)形参
argc
是命令行中参数的个数(可执行文件名本身也算一个)。
在本案例中,形参
argc
的值为
3
(
lock
、
+|-
、文件名)。
(
2
)形参
argv
是一个字符指针数组,即形参
argv
首先是一个数组(元素个数为形参
argc
的值),其元素值都是指向实参字符串的指针。
在本案例中,元素
argv[0]
指向第
1
个实参字符串“
lock
”,元素
argv[1]
指向第
2
个实参字符串“
+|-
”,元素
argv[2]
指向第
3
个实参字符串“被处理的文件名”。
3.
形参说明
(
1
)形参
argc
是命令行中参数的个数(可执行文件名本身也算一个)。
在本案例中,形参
argc
的值为
3
(
lock
、
+|-
、文件名)。
(
2
)形参
argv
是一个字符指针数组,即形参
argv
首先是一个数组(元素个数为形参
argc
的值),其元素值都是指向实参字符串的指针。
在本案例中,元素
argv[0]
指向第
1
个实参字符串“
lock
”,元素
argv[1]
指向第
2
个实参字符串“
+|-
”,元素
argv[2]
指向第
3
个实参字符串“被处理的文件名”。
9.6.3
指向指针的指针变量简介
在
[
案例
9.12]
的主函数
main()
中,数组
name
是一个字符指针数组,即数组的每一个元素都是一个指向字符串的指针。
既然
name
是一个数组,则它的每一个元素也同样有相应的地址,因此可以设置一个指针变量
pointer
,使其指向指针数组的元素(元素的值还是一个指针),称
pointer
为指向指针的指针变量。显然,指向指针的指针变量是一个两级的指针变量。
1.
指向指针的指针变量的定义
数据类型
**
指针变量
[, **
指针变量
2
……
]
;
2.
指向指针的指针变量的赋值
指针变量
=
指针数组名
+ i
9.7
函数的指针和指向函数的指针变量简介
1.
函数指针的概念
一个函数在编译时,被分配了一个入口地址,这个地址就称为该函数的指针。
可以用一个指针变量指向一个函数,然后通过该指针变量调用此函数。
2.
指向函数的指针变量
(
1
)定义格式
函数类型
(*
指针变量
)( )
;
注意:“
*
指针变量”外的括号不能缺,否则成了返回指针值的函数。
例如,
int (*fp)();
/* fp
为指向
int
函数的指针变量
*/
(
2
)赋值
函数名代表该函数的入口地址。因此,可用函数名给指向函数的指针变量赋值。
指向函数的指针变量=
[&]
函数名
;
注意:函数名后不能带括号和参数;函数名前的“
&
”符号是可选的。
(3)
调用格式
(*
函数指针变量
)([
实参表
])
3.
指向函数的指针变量作函数参数
指向函数的指针变量的常用用途之一,就是将函数指针作参数,传递到其它函数。
函数名作实参时,因为要缺省括号和参数,造成编译器无法判断它是一个变量还是一个函数,所以必须加以说明。函数说明的格式,与第
7
章中介绍的一样。
注意:对指向函数的指针变量,诸如
p+i
、
p++/p--
等运算是没有意义的。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0