函数的基本知识
-
函数是对一系列计算或操作的过程的抽象
函数可以把大的计算任务分解成若干个较小的任务,程序设计人员可以基于函数进一步构造程序。函数可以把程序中不需要了解的具体操作细节隐藏起来,从而使整个程序结构更加清晰,并降低修改程序的难度。
程序可以看成是变量定义和函数定义的集合。函数之间的通信可以通过参数、函数返回值以及外部变量进行。
-
函数的定义形式
返回值类型 函数名(参数声明表) { 声明和语句 }
-
例子:打印输入中包含特定字符串的行(grep特例)
//打印输入中包含特定字符串的行 #include <stdio.h> #define MAXLINE 1000 //最行输入行长度 int getline(char line[], int max); int stringdex(char source[], char searchfor[]); char pattern[]="ould"; //带查找的字符串 int main() { char line[MAXLINE]; int found = 0; //符合行总数 while (getline(line, MAXLINE) > 0) { if (getline(line, MAXLINE) >=0) { printf("%s\n", line); found++; } } return found; } // getline函数:将行保存在s中,并返回该行的长度。lim为行限制长度 int getline(char s[], int lim) { int c; //读取字符 int l = 0; //存储长度 while (--lim > 0 && (c=getchar()) != EOF && c != '\n') { s[l++]=c; } s[l] = '\0'; return l; } //strindex函数:返回目标字符串t中s中的位置, 未找到则返回-1 int strindex(char s[], char t[]) { int i, j, k; for (i =0; s[i] != '\0'; i++) { for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++) ; if (k > 0 && t[k] == '\0') { return i; } } return -1; }
-
例子:atof 函数
#include <ctype.h> // atof 函数:把字符串s转换为相应的双精度浮点数 double atof(char s[]) { double int_part; //整数部分 double fra_part; //小数部分 int sign; //符号 int power; int i; for (i = 0; isspace(s[i]); i++) //跳过空白符 ; sign = (s[i] == '-') ? -1 : 1; if (s[i] == '+' || s[i] == '-') //跳过符号 i++; //整数部分 for (int_part = 0; isdigit(s[i]); i++) { int_part = 10.0 * int_part + (s[i] - '0'); } //跳过小数点 if (s[i] == '.') i++; //小数部分 for(power = 1, fra_part = 0.0; isdigit(s[i]); i++) { fra_part = fra_part * 10.0 + (s[i] - '0'); power *= 10; } fra_part = fra_part / power; return int_part + fra_part; } main() { //pass }
递归
-
递归是指函数可以直接或间接调用自身。
C语言中的函数可以递归调用,即函数可以直接或间接调用自身。递归调用过程须维护一个处理值得栈,开销较大,执行速度不快;但递归代码比较紧凑,比相应非递归代码更易编写与理解。
-
例子:将一个数作为字符串打印
#include<stdio.h> //pirntd函数:将一个数作为字符串打印 void printd(int n) { if (n < 0) { putchar('-'); n = -n; } if (n / 10) printd(n /10); putchar(n % 10 + '0'); } //test main() { int num; scanf("%d",&num); printd(num); }
-
例子:快速排序
快速排序算法是C.A.R. Hoare于1962年发明的。对于一个给定的数组,从中选择一个元素,以该元素为界将其余元素划分为两个子集,一个子集中所有元素都小于该元素,另一个子集中所有元素都大于或等于该元素。对这两个子集递归执行这一过程,当某个子集中的元素小于2时,这个子集就不需要再次排序,终止递归。
// qsort函数:以递增顺序对 v[left] ... v[right]进行排序 void qsort(int v[], int left, int right) { int i; int last; void swap(int v[], int i, int j); //递归边界 if(left >= right) return; //划分子集 swap(v, left, (left + right) / 2); last = left; for (i = left=1; i <= right; i++) { if (v[i] < v[left]) swap(v, ++last, i); } swap(v, left, last); //递归 qsort(v, left, last-1); qsort(v, last+1, right); } // swap函数:交换 v[i]与 v[j]的值 void swap(int v[], int i, int j) { int temp; temp = v[i]; v[i] = v[j]; v[j] = temp; }
变量
- 外部变量、内部变量、寄存器变量
- 静态变量
- 用
static
声明外部变量和函数,可以将其后的声明对象的作用域限定为被编译源文件的剩余部分,可以达到隐藏外部对象的目的。 -
static
也可用于声明内部变量。static
内部变量是一种只能贼某个特定函数中使用但一直占据存储空间的变量。
- 用
初始化
- 在不进行显示初始化的情况下,外部变量和静态变量都将被初始化为
0
,而自动变量和寄存器变量的处置没有定义。 - 外部变量和静态变量的初始化表达式必须是常量表达式。
作用域规则
- 名字的作用域指的是程序中可以使用该名字的部分。
- 对于在函数开头声明的自动变量,其作用域是声明该变量的函数。
- 外部变量或函数的作用域从声明它的地方开始,到其所在的文件的末尾结束。
- 如果要在外部变量的定义之前使用该变量,或者外部变量的定义与变量的使用不在同一个源文件中,则必须在相应的变量声明中强制性地使用关键字
extern
程序块结构
变量的声明除了可以紧随在函数开始的花括号之后,还可以紧跟在任何其他标识复合语句开始的左花括号之后。
四则运算计算器程序
-
实现方法:为了更容易实现,我们使用逆波兰表示法代替中缀表示法。计算器程序的实现过程:每个操作数都被依次压入到栈中;当一个运算符到达时,从栈中弹出相应数目的操作数,把该运算符作用于弹出的操作数,并把运算结果压入到栈中。到达输入行的末尾时,弹出栈顶值并打印。
中缀表示法: ( 1 - 2 ) * ( 4 + 5 ) 逆波兰表示法:1 2 - 4 5 + *
头文件
C预处理
- 文件包含
- 宏替换
- 条件替换
网友评论