第 9章 预处理命令和常用库函数本章要点
9.1预处理命令
9.2常用输入/输出函数
9.3常用字符串函数
9.4动态内存分配函数本章要点:
熟悉宏定义与宏扩展。宏与函数的区别。
熟悉文件包含命令 #include的作用及其预处理方法。
熟悉条件编译的使用。
9.1 预处理命令文件包含命令
文件包含预定处理命令 #include的作用是使一个源文件可以将另外一个源文件的全部内容包含进来,把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。
9.1.2 宏定义
1.不带参的宏定义
在C语言源程序中允许用一个标识符来表示一个字符串,称为,宏,。不带参的宏定义在第二章已有简单介绍,那里用来定义一个符号常量,这里做进一步的说明。不带参的宏定义用一个指定的标识符来代表一个特殊的字符串,它的一般形式是:
#define 标识符 (或称宏名 ) 字符串
【 例 9-2】 不带参的宏定义示例
#define R 4.6
#define PI 3.1415926
#define L 2*PI*R
#define S PI*R*R
#include"stdio.h"
main()
{
printf("L=%f\tS=%f\n",L,S);
}
运行结果:
2.带参的宏定义
带参的宏定义,也称函数宏。格式如下:
#deflne 宏名 (参数表 ) 宏体
参数表中的参数可有多个,用逗号隔开。在宏展开时,宏体中与参数表中相同的标识符被相应的参数所代替。
一个宏一旦被定义,它在文件中是存在的和可见的。
这一点很像外部变量。如要对某一宏定义撤消,可用命令:
#undef宏标识符
一个宏标识符一旦消除了原来的定义,便可以被重新定义其他不同的宏。
9.1.3 条件编译
命令格式一
#if 表达式程序段 1
#else
程序段 2
#endif
命令格式二
#ifdef标识符程序段 1
#else
程序段 2
#endif
【 例 9-4】 阅读下面的程序,了解条件编译的使用
#include<stdio.h>
#define MAX 10
main()
{
#if MAX>99
printf("compile for array greater than 99\n");
#else
printf("compile for small array\n");
#endif
}
程序运行结果:
9.2 常用输入/输出函数
1,printf函数
输出表列
格式控制字符
修饰符
【 例 9-6】 输出各种格式的数据。
#include<stdio.h>
void main()
{
double f1=1e+10;
double f2=3.14;
printf("%%f,%f\n",f1);
printf("%%e,%e\n",f1);
printf("%%g,%g\n",f1);
printf("%%f,%f\n",f2);
printf("%%e,%e\n",f2);
printf("%%g,%g\n",f2);
}
程序运行结果为:
【 例 9-8】 修饰符在 printf函数中的使用
#include<stdio.h>
void main()
{
int a=123;
float f1=12.34567,f2=678.9;
printf("%d,%6d,%-6d,%2d\n",a,a,a,a);
printf("%f,%10.4f,%3.2f\n",f1,f1,f1);
printf("\%e,%e\n",f1,f2);
printf("\%8e,%14e\n",f1,f1);
printf("\%10.7e,%10.3e\n",f1,f1);
}
程序的运行结果为:
9.3 常用字符串函数
1.字符串长度函数 strlen()。
该函数的原型是:
int strlen(char*s);
该函数返回一个整数值,这个整数值是字符型指针 s
所指向的字符串的长度。实际调用时的参数可以是已赋值的字符型指针,也可以是已定义的字符型数组名或采用已知的字符串本身
【 例 9-13】 计算给定字符串的长度
#include<stdio.h>
#include<string.h>
void main()
{ char *s1="Welcome!";
char s2 []="How are you?";
char s3 [40],s4;
printf("Input string s3,\n");
gets(s3);
printf("s1,%d\n",strlen(s1)); /*用字符指针调用 */
printf("s2,%d\n",strlen(s2)); /*用字符数组名调用 */
printf("s3,%d\n",strlen(s3));
s4=strlen("Good morning!"); /*用字符串本身调用 */
printf("s4,%d\n",s4);
}
程序运行结果为:
2.字符串连接函数 strcat()
strcat函数用来连接两个字符数组中的字符串,把字符串 2连接到字符数组 1后面,并在最后加一个
‘ \0’,结果放在字符数组 1中,其调用形式为:
strcat(strl,str2);
这里需要注意,字符数组 strl必须足够长,以便容纳得下两个字符串中的全部字符。使用 strcat函数时,需用 #include命令,将 <string.h>头文件包含到源文件中。
3.字符串复制函数
它用来将一个字符串复制到一个字符数组中,例如:
strcpy(namel,"Apple");
其作用是将,Apple”这个字符串复制到 namel数组中。
注意,不能直接用赋值语句对一个数组整体赋值。
4.字符串比较函数
调用方式,strcmp(字符串 1,字符串 2)
其中,字符串,可以是串常量,也可以是一维字符数组。
函数功能:比较两个字符串的大小。
如果,字符串 1=字符串 2,函数返回值等于 0;字符串
1<字符串 2,函数返回值为负整数,字符串 1>字符串 2,函数返回值为正整数。
注意:对两个字符串进行比较,不能直接用两个字符数组名比较,
5.字符串输入函数 gets()
gets()函数的作用是:从键盘上输入一个字符串,
并把它存放在参数所指示的字符数组中,输入的字符串以 <回车 >作为结束。函数 gets()的调用格式:
gets(字符数组名 )
如果函数调用成功,将返回字符数组的首地址,否则,返回空值 NULL。
6.字符串输出函数 puts()
函数 puts()的作用是:将参数中提供的字符串输出到显示屏。函数 puts()的调用格式:
puts(字符数组名 )
如果函数调用成功,将返回字符串结束符,\0”,否则,返回一个非 0值。
注意:
( 1) gets(),puts()函数每次只能处理一个字符串。
( 2)在使用 gets(),puts()函数之前,应当使用预处理命令 #include<stdio.h>。
7.将字符串中大写字母转换成小写字母函数 strlwr()
函数 strlwr()的作用是:将由参数提供的字符串中所有的大写字母转换成小写字母。
函数 strlwr()的调用格式:
strlwr(字符数组名 )
例如,执行语句:
puts(strlwr("AStudent"));
在显示屏上输出,astudent。
8.将字符串中小写字母转换成大写字母函数 strupr()
函数 strupr()的作用是:将由参数提供的字符串中所有的小写字母转换成大写字母。
函数 strupr()的调用格式:
strupr(字符数组名 )
例如,执行语句:
puts(strupr("English"));
在显示屏上输出,ENGLISH
9.4 动态内存分配函数动态分配内存时,需要注意以下几个方面:
结构类型占用的内存空间不一定是连续的,因此,
应该用 sizeof运算符来确定结构类型占用内存空间的大小 ;
使用 mallco()函数时,应对其返回值进行检测是否为 NULL,以确保程序的正确 ;
要及时地使用 free()函数释放不再需要的内存空间,
避免系统资源过早地用光 ;
不要引用已经释放的内存空间。
【 例 9-15】 动态内存分配函数应用示例
#include<stdio.h>
#include<stdlib.h>
#define LEN sizeof(struct Worker)
struct Worker
{
int num;
char name[20];
float pay;
};
main()
{
int i;
struct Worker *p;
float a;/*程序接下页 */
/*程序接上页 */
scanf("%f",&a);
p=(struct Worker*)malloc(LEN);
scanf("%d%s%f",&p->num,p->name,&p->pay);
printf("%d,%s,%0.1f\n",p->num,p->name,p->pay);
free(p);
p=(struct Worker*)malloc(2*LEN);
scanf("%d%s%f",&p->num,p->name,&p->pay);
scanf("%d%s%f",&(p+1)->num,(p+1)->name,&(p+1)->pay);
printf("%d,%s,%0.1f\n",p->num,p->name,p->pay);
printf("%d,%s,%0.1f\n",(p+1)->num,(p+1)-
>name,(p+1)->pay);
free(p);
}
程序运行结果为: