1、定义函数(实现)
在C语言中,函数的定义顺序是有讲究的:默认情况下,只有后面定义的函数才可以调用前面定义过的函数。
例如,
#include <stdio.h>
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
int main ()
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
/* 调用函数来获取最大值 */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
注意:上面这样调用合法的,但如果调换sum
函数和main
函数的顺序,在标准的C编译器环境下是不合法的(不过在GCC
编译器环境下只是一个警告)。
2、函数声明
如果想把函数的定义写在main函数后面,而且main函数能正常调用这些函数,那就必须在main函数的前面进行函数的声明。
函数声明地格式:
返回值类型 函数名 (参数1, 参数2, ...)
例如,
#include <stdio.h>
/* 函数声明 */
int max(int num1, int num2);
int main ()
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
/* 调用函数来获取最大值 */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
3、调用函数
函数调用的一般形式为:
函数名(实参列表);
调用函数时,传递所需参数,如果函数返回一个值,则可以存储返回值。例如:
#include <stdio.h>
/* 函数声明 */
int max(int num1, int num2);
int main ()
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
/* 调用函数来获取最大值 */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
4、函数参数
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
当调用函数时,有三种向函数传递参数的方式:
1)传值
#include<stdio.h>
void myswap(int x, int y)
{
int t;
t=x;
x=y;
y=t;
}
int main()
{
int a, b;
printf("请输入待交换的两个整数:");
a=10,b=20;
myswap(a,b); //作为对比,直接交换两个整数,显然不行
printf("调用交换函数后的结果是:%d 和 %d\n", a, b);
return 0;
}
2)传引用
#include<stdio.h>
void myswap(int *p1, int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}
int main()
{
int a, b;
printf("请输入待交换的两个整数:");
a=10,b=20;
myswap(&a,&b); //交换两个整数的地址
printf("调用交换函数后的结果是:%d 和 %d\n", a, b);
return 0;
}
5、函数递归
一个函数在它的函数体内,直接或者间接地调用了他本身。
例如,
问第五个学生,说他比第四个学生大两岁
第四个学生说他比第三个学生大两岁
第三个学生说他比第二个学生大两岁
第二个学生说他比第一个学生大两岁
第一个说他10岁
求第五个学生的年龄,可以使用如下解法:
#include<stdio.h>
/*int Age (int n)
{
int tmp;
tmp=10;
for(int i=1;i<n;i++)
{
tmp+=2;
}
return tmp;
}
*/
//递归法
int Age(int n)
{
int x=0;
if(n==1) //是递归停止的条件,当n=1时停止递归调用
{
x=10;
}
else
{
x=Age(n-1)+2;//调用自身的Age函数
}
return x;
}
int main()
{
printf("%d\n",Age(5));
return 0;
}
注意:函数的递归调用,就是函数本身调用自己。但是应用递归调用的时候,我们有必要设置一个条件,也就是if语句,目的是能够让这个函数停下来,否则程序将进入到死循环。
6、常用库函数
1)数学函数(#include <math.h>)
函数原型说明 | 功能 | 返回值 | 说明 |
int abs( int x) | 求整数x的绝对值 | 计算结果 |
|
double fabs(double x) | 求双精度实数x的绝对值 | 计算结果 |
|
double acos(double x) | 计算cos-1(x)的值 | 计算结果 | x在-1~1范围内 |
double asin(double x) | 计算sin-1(x)的值 | 计算结果 | x在-1~1范围内 |
double atan(double x) | 计算tan-1(x)的值 | 计算结果 |
|
double atan2(double x) | 计算tan-1(x/y)的值 | 计算结果 |
|
double cos(double x) | 计算cos(x)的值 | 计算结果 | x的单位为弧度 |
double cosh(double x) | 计算双曲余弦cosh(x)的值 | 计算结果 |
|
double exp(double x) | 求ex的值 | 计算结果 |
|
double fabs(double x) | 求双精度实数x的绝对值 | 计算结果 |
|
double floor(double x) | 求不大于双精度实数x的最大整数 |
|
|
double fmod(double x,double y) | 求x/y整除后的双精度余数 |
|
|
double frexp(double val, int *exp) | 把双精度val分解尾数 和以2为底的指数n, 即val=x*2n, n存放在exp所指的变量中 | 返回位数x 0.5≤x<1 |
|
double log(double x) | 求㏑x | 计算结果 | x>0 |
double log10(double x) | 求log10x | 计算结果 | x>0 |
double modf(double val, double *ip) | 把双精度val分解成整数部分 和小数部分, 整数部分存放在ip所指的变量中 | 返回小数部分 |
|
double pow(double x, double y) | 计算xy的值 | 计算结果 |
|
double sin(double x) | 计算sin(x)的值 | 计算结果 | x的单位为弧度 |
double sinh(double x) | 计算x的双曲正弦函数sinh(x)的值 | 计算结果 |
|
double sqrt(double x) | 计算x的开方 | 计算结果 | x≥0 |
double tan(double x) | 计算tan(x) | 计算结果 |
|
double tanh(double x) | 计算x的双曲正切函数tanh(x)的值 | 计算结果 |
|
2)字符函数(#include <ctype.h>)
函数原型说明 | 功能 | 返回值 |
int isalnum(int ch) | 检查ch是否为字母或数字 | 是,返回1; 否则返回0 |
int isalpha(int ch) | 检查ch是否为字母 | 是,返回1; 否则返回0 |
int iscntrl(int ch) | 检查ch是否为控制字符 | 是,返回1; 否则返回0 |
int isdigit(int ch) | 检查ch是否为数字 | 是,返回1; 否则返回0 |
int isgraph(int ch) | 检查ch是否为ASCII码值在ox21 到ox7e的可打印字符(即不包含空格字符) | 是,返回1; 否则返回0 |
int islower(int ch) | 检查ch是否为小写字母 | 是,返回1; 否则返回0 |
int isprint(int ch) | 检查ch是否为包含空格符在内的可打印字符 | 是,返回1; 否则返回0 |
int ispunct(int ch) | 检查ch是否为除了空格、字母、数字之外的可打印字符 | 是,返回1; 否则返回0 |
int isspace(int ch) | 检查ch是否为空格、制表或换行符 | 是,返回1; 否则返回0 |
int isupper(int ch) | 检查ch是否为大写字母 | 是,返回1; 否则返回0 |
int isxdigit(int ch) | 检查ch是否为16进制数 | 是,返回1; 否则返回0 |
int tolower(int ch) | 把ch中的字母转换成小写字母 | 返回对应的小写字母 |
int toupper(int ch) | 把ch中的字母转换成大写字母 | 返回对应的大写字母 |
3)字符串函数(#include <string.h>)
函数原型说明 | 功能 | 返回值 |
char *strcat(char *s1, char *s2) | 把字符串s2接到s1后面 | s1所指地址 |
char *strchr(char *s, int ch) | 在s所指字符串中, 找出第一次出现字符ch的位置 | 返回找到的字符的地址, 找不到返回NULL |
int strcmp(char *s1, char *s2) | 对s1和s2所指字符串进行比较 | s1<s2,返回负数; s1= =s2,返回0; s1>s2,返回正数 |
char *strcpy(char *s1, char *s2) | 把s2指向的串复制到s1指向的空间 | s1 所指地址 |
unsigned strlen(char *s) | 求字符串s的长度 | 返回串中字符 (不计最后的'\0')个数 |
char *strstr(char *s1, char *s2) | 在s1所指字符串中, 找出字符串s2第一次出现的位置 | 返回找到的字符串的地址, 找不到返回NULL |
4) 输入输出函数(#include <stdio.h>)
函数原型说明 | 功能 | 返回值 |
void clearer(FILE *fp) | 清除与文件指针fp有关的所有出错信息 | 无 |
int fclose(FILE *fp) | 关闭fp所指的文件, 释放文件缓冲区 | 出错返回非0, 否则返回0 |
int feof (FILE *fp) | 检查文件是否结束 | 遇文件结束返回非0, 否则返回0 |
int fgetc (FILE *fp) | 从fp所指的文件中取得下一个字符 | 出错返回EOF, 否则返回所读字符 |
char *fgets(char *buf,int n, FILE *fp) | 从fp所指的文件中 读取一个长度为n-1的字符串, 将其存入buf所指存储区 | 返回buf所指地址, 若遇文件结束或出错返回NULL |
FILE *fopen(char *filename, char *mode) | 以mode指定的方式 打开名为filename的文件 | 成功, 返回文件指针 (文件信息区的起始地址), 否则返回NULL |
int fprintf(FILE *fp, char *format, args,…) | 把args,…的值以format指定的格式 输出到fp指定的文件中 | 实际输出的字符数 |
int fputc(char ch, FILE *fp) | 把ch中字符输出到fp指定的文件中 | 成功返回该字符, 否则返回EOF |
int fputs(char *str, FILE *fp) | 把str所指字符串输出到fp所指文件 | 成功返回非负整数, 否则返回-1(EOF) |
int fread(char *pt, unsigned size, unsigned n, FILE *fp) | 从fp所指文件中读取长度size 为n个数据项存到pt所指文件 | 读取的数据项个数 |
int fscanf (FILE *fp, char *format,args,…) | 从fp所指的文件中按format指定的格式 把输入数据存入到args,…所指的内存中 | 已输入的数据个数, 遇文件结束或出错返回0 |
int fseek (FILE *fp, long offer, int base) | 移动fp所指文件的位置指针 | 成功返回当前位置, 否则返回非0 |
long ftell (FILE *fp) | 求出fp所指文件当前的读写位置 | 读写位置, 出错返回 -1L |
int fwrite(char *pt,unsigned size, unsigned n, FILE *fp) | 把pt所指向的n*size个字节 输入到fp所指文件 | 输出的数据项个数 |
int getc (FILE *fp) | 从fp所指文件中读取一个字符 | 返回所读字符, 若出错或文件结束返回EOF |
int getchar(void) | 从标准输入设备读取下一个字符 | 返回所读字符, 若出错或文件结束返回-1 |
char *gets(char *s) | 从标准设备读取一行字符串 放入s所指存储区, 用’\0’替换读入的换行符 | 返回s,出错返回NULL |
int printf(char *format, args,…) | 把args,…的值以format指定的格式 输出到标准输出设备 | 输出字符的个数 |
int putc (int ch, FILE *fp) | 同fputc | 同fputc |
int putchar(char ch) | 把ch输出到标准输出设备 | 返回输出的字符, 若出错则返回EOF |
int puts(char *str) | 把str所指字符串输出到标准设备, 将’\0’转成回车换行符 | 返回换行符, 若出错,返回EOF |
int rename(char *oldname, char *newname) | 把oldname所指文件名 改为newname所指文件名 | 成功返回0, 出错返回-1 |
void rewind(FILE *fp) | 将文件位置指针置于文件开头 | 无 |
int scanf(char *format, args,…) | 从标准输入设备按format指定的格式 把输入数据存入到args,…所指的内存中 | 已输入的数据的个数 |
5)动态分配函数和随机函数(#include <stdlib.h>)
函数原型说明 | 功能 | 返回值 |
void *calloc(unsigned n, unsigned size) | 分配n个数据项的内存空间, 每个数据项的大小为size个字节 | 分配内存单元的起始地址; 如不成功,返回0 |
void *free(void *p) | 释放p所指的内存区 | 无 |
void *malloc(unsigned size) | 分配size个字节的存储空间 | 分配内存空间的地址; 如不成功,返回0 |
void *realloc(void *p, unsigned size) | 把p所指内存区的大小改为size个字节 | 新分配内存空间的地址; 如不成功, 返回0 |
int rand(void) | 产生0~32767的随机整数 | 返回一个随机整数 |
void exit(int state) | 程序终止执行, 返回调用过程, state为0正常终止, 非0非正常终止 | 无 |