函数
复习创建函数
#include <stdio.h>
#define NAME "GIGATHINK INC."
#define ADDRESS "101 MEgabuck Plaza"
#define PLACE "Megapolis, CA 97904"
#define WIDTH 40
void starbar(); //不带参数
int main(){
starbar();
printf("%s\n",NAME);
printf("%s\n",ADDRESS);
printf("%s\n",PLACE);
starbar();
return 0;
}
void starbar(){
int count;
for (count = 1; count <= WIDTH; count++)
putchar('*');
putchar('\n');
}
程序流程
简单函数的结构
函数参数
#include <stdio.h>
#include <string.h>
#define NAME "GIGATHINK INC."
#define ADDRESS "101 MEgabuck Plaza"
#define PLACE "Megapolis, CA 97904"
#define WIDTH 40
#define SPACE ' '
void show_n_char(char ch , int num);
int main(){
int space;
show_n_char('*',WIDTH);
putchar('\n');
show_n_char(SPACE,12);
printf("%s\n",NAME);
space = (WIDTH - strlen(ADDRESS))/2;
show_n_char(SPACE,space);
printf("%s\n",ADDRESS);
show_n_char(SPACE,(WIDTH - strlen(PLACE)) /2 );
printf("%s\n",PLACE);
show_n_char('*',WIDTH);
putchar('\n');
return 0;
}
void show_n_char(char ch,int num){
int count;
for (count =1;count <= num; count++)
putchar(ch);
}
定义带形参的函数
void dibs(int x,y,z) //无效的函数头
void dibs(int x double y, int z) //有效
void dibs(x,y,z)
int x,y,z;{
}
声明带形式参数函数的原型
void dibs(char, int);//函数原型声明可以省略变量名 注意有分号 写在头部
调用带实际参数的函数
黑盒视角
函数内部与main()中的同名变量是相互独立的。
使用return从函数中返回值
#include <stdio.h>
int main(){
int imin(int,int); //函数声明 必须放在使用之前
int evil1,evil2;
printf("Enter a pair of integers (q to quit):\n");
while (scanf("%d %d",&evil1,&evil2) ==2)
{
printf("The lesser of %d and %d is %d.\n",evil1,evil2,imin(evil2,evil2));
printf("Enter a pair of itegers (q to quit):\n");
}
printf("Bye.\n");
return 0;
}
int imin(m,n)
int m,n;
{
int min;
if (n <m)
min = n; //return n;
else
min =m; //return m;
return min;
}
return (m > n) ? n:m;
ANSIC函数原型
#include <stdio.h>
int main(){
int imax(); //参数不完整
printf("The maximum of %d and %d is %d.\n",3,5,imax(3));
printf("The maxmum of %d and %d is %d.\n",3,5,imax(3.0,5.0));
return 0;
}
int imax(n,m)
int n,m;{
return (m>n)?m:n;
}
无参数和未指定参数
void print_name();
int printf(const char *, ...); //有许多参数
函数原型的优点
是为了让编译器在第1次执行到该函数之前就知道如何使用它。
可以将函数定义在mian()函数前,省略函数原型声明。
递归(Recursion)
#include <stdio.h>
void up_and_down(int);
int main(){
up_and_down(1);
return 0;
}
void up_and_down(int n){
printf("Level %d: n location %p\n",n,&n);
if (n < 4)
up_and_down(n + 1);
printf("Level %d : n location %p\n",n,&n);
}
递归的基本原理
递归和倒序计算
递归在处理倒序时非常方便
#include <stdio.h>
void to_binary(unsigned long n);
int main(){
unsigned long number;
printf("Enter an integer (q to quit):\n");
while (scanf("%lu",&number) ==1)
{
printf("Binary equivalent: ");
to_binary(number);
putchar('\n');
printf("Enter an integer(q to quit):\n");
}
printf("Done.\n");
return 0;
}
void to_binary(unsigned long n){
int r;
r = n %2;
if (n >= 2)
to_binary(n / 2);
putchar(r == 0?'0':'1' );
return;
}
递归优缺点
优点是递归为某些编程问题提供了最简单的解决方案。
缺点是一些递归算法会快速消耗计算机的内存资源,每次递归都会创建一组变量,所以递归使用的 内存更多,而且每次递归调用都会把创建的一组新变量放在栈中。递归调用 的数量受限于内存空间。其次,由于每次函数调用要花费一定的时间,所以 递归的执行速度较慢。
编译多源代码文件的程序
查找地址:&运算符
指针(pointer)用于储存变量的地址。如scanf()函数使用地址作为参数。
一元&运算符给出变量的存储地址
pooh = 24;
printf("%p",&pooh); //打印pooh存储地址
#include <stdio.h>
int main(){
void mikdo(int);
int pooh =2,bah=10;
printf("In main(),pooh =%d and &pooh = %p",pooh,&pooh);
printf("In main(), bah = %d and &bah = %p\n",bah,&bah);
mikdo(pooh);
return 0;
}
void mikdo(int bah){
int pooh = 10;
printf("In mikdo(),pooh =%d and &pooh = %p",pooh,&pooh);
printf("In mikdo(), bah = %d and &bah = %p\n",bah,&bah);
}
In main(),pooh =2 and &pooh = 000000000061FE1CIn main(), bah = 10 and &bah = 000000000061FE18
In mikdo(),pooh =10 and &pooh = 000000000061FDDCIn mikdo(), bah = 2 and &bah = 000000000061FDF0
两个pooh地址不同,两个bah地址也不同,4个变量互相独立,函数只是传递了值。
更改主调函数中的变量
#include <stdio.h>
void innterchange(int,int);
int main(){
int x=5,y=10;
printf("Originally x = %d and y =%d.\n",x,y);
innterchange(x,y);
printf("Now x = %d and y = %d.\n",x,y);
return 0;
}
void innterchange(int m,int n){
int temp;
temp = m;
m = n;
n =temp;
}
程序并没有交换x,y的值,而是交换了m,n的值。
指针简介
ptr = &pooh; //pooh的地址赋给ptr
间接运算符:*
// 以下相当于val = bah;
ptr = &bah;
val = *ptr;
声明指针
int *pi; //pi是指向int类型变量的指针
char *pc; //pc是指向char类型变量的指针
float *pf,*pg; //指向float类型变量的指针
#include <stdio.h>
void interchange(int *m,int *n);
int main(){
int x=5,y=10;
printf("Originally x = %d and y =%d.\n",x,y);
interchange(&x,&y);
printf("Now x = %d and y = %d.\n",x,y);
return 0;
}
void interchange(int *m,int *n){
int temp;
temp = *m;
*m = *n;
*n = temp;
}
字节寻址系统中变量的名称、地址和值
程序编写时可认为程序有两个属性:名称和值。
计算机编译加载后,变量有两个属性:地址和值。