C语言学习笔记
函数
子函数在主函数之后,须在主函数开头部分声明子函数。
定义
无参函数
类型标识符 函数名() {
函数体
}
类型标识符 函数名(void) {
函数体
}
- void表示空类型,无函数值(返回值)
- 函数体包括'声明部分'和'语句部分'
有参函数
类型标识符 函数名(形式参数表列) {
函数体
}
类型标识符 函数名(类型标识符 形式参数, 类型标识符 形式参数, .....) {
函数体
}
例如:
int max(int x,int y) {
int z; // 声明部分
z = x>y ? x : y; // 执行部分
return z;
}
空函数
类型标识符 函数名() {
}
C语言中,若未说明函数的类型,则系统默认该函数的类型是int型。
调用
格式
格式: 函数名(实参表列)
- 函数调用语句,针对无返回值的函数
printf("hello");
- 函数表达式,针对有返回值的函数
c = 2 * max(1,2);
- 函数参数,作为另一个函数的实参
m = max(1,max(2,3));
printf("max:%d",max(5,11));
形参与实参
在有参函数中,定义函数时函数名后面括号里的是形参
,在主函数中调用时,被调用函数名后面括号里的是实参
。实参可以是常量,变量,表达式。实参要求必须是确定的值。
数组作为函数参数
数组元素作为函数实参,其用法与变量相同,向形参传递数组元素的值。
数组名也可以作为实参和形参,传递的是数组第一个元素的地址
数组元素作为函数实参
可做实参,不可做形参,因为形参是在函数被调用处临时分配存储单元的,不可能为一个数组元素单独分配存储空间。是 ”值传递“ 方式,数据传输方向是从实参传递到形参,单向传递。
一维数组名作为函数参数
用数组元素作为实参时,向形参彻底的是数组元素的值。数组名作为函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址。
当用数组名作为函数的参数时,如果形参数组中的元素值发生改变时 实参元素的值也发生改变。
-
用数组名作为函数的参数时,应在主调用函数和被调用函数分别定义数组
-
实参数组与形参数组应类型一致
-
在定义函数时,指定数组大小时不起任何作用,因为C语言编译器不检查形参数组大小,只是将实参数组的首元素的地址传递给形参数组名
-
形参数组可以不知道大小
void foo(int a[]){......}
编译系统会把形参数组处理为指针变量,例如把float a[]转化为float *a,二者是等价的
多维数组名作为函数参数
可省略第一维大小
void foo(int a[][10]){......}
嵌套调用
C语言的函数定义是互相平行的、独立。在定义函数时,一个函数内不能在定义另一个函数,即不能嵌套定义,
但可以嵌套调用函数。
递归调用
直接或间接地调用该函数本身,称为函数的递归调用。
int foo(int x) {
int y,z;
z=foo(y);
return 2*z;
}
声明
来源
函数的来源有两种:1. 用户自定义的函数,2. 库函数。
-
被调用的函数必须是已定义的函数。
-
使用库函数,需要在本文件开头用
#include
指令将所需要的信息添加到本文件中。#include <math.h> .h是头文件所用的后缀,表示头文件
-
如果用户自定义的函数在主函数后面定义,需要在主函数开头声明该函数。以便编译器能够正确识别到。因为编译器是自上向下进行的。
-
如果已在文件的开头(在所有函数之前),对本文件中所调用的函数进行声明,则在个函数中不必对其所调用的函数再做声明。
int max(int,int); int add(int,int); int main() {......} // 在main函数中就无需对max和add函数进行声明 int max(int x,int y){......} int add(int x,int y){......}
格式
一般形式:
- 函数类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ...)
- 函数类型 函数名(参数类型1, 参数类型2, ...)
例如:
float add(float,float);
float add(float x,float y);
返回值
-
函数的返回值通过函数中的return语句获得
-
在定义函数时必须指定函数的类型
-
在定义函数指定的函数类型一般应该和return语句中的表达式一致,即函数类型觉得返回值类型
-
对于不带回值的函数,应当定义函数为 “void类型”
变量的作用域
在函数开头定义的变量,只在该函数中使用。引申到变量的作用域问题,每个变量都有一个作用域。
在函数内定义的变量是局部变量;在函数外定义的变量是全局变量。
定义变量的三种情况:
-
在函数开头的位置定义
-
在函数内的复合语句内定义
-
在函数外部定义
局部变量
-
主函数定义的变量只在主函数中有效
-
不同函数可以使用相同名的变量,他们代表不同的对象,互不干扰
-
形式参数也是局部变量
-
复合语句中定义的变量只在复合语句中有效
全局变量
为了便于区分全局变量和局部变量,有一个习惯将全局变量第一个字母大写
建议不在必要时不要使用全局变量,理由如下:
-
全局变量在程序的全部执行中占用内存
-
使函数的通用性降低
-
使用全局变量过多,会降低程序的清晰性
举例
// 变量的作用域
#include<stdio.h>
int G = 123;
int add(int x, int y) {
printf("add中打印g:%d\n", G);
return x + y;
}
char M = 'M'; // 编译器自上向下执行语句,虽然M和G都是全局作用域,但m的作用域比g小,不包含add函数
int main() {
int a = 0;
int sum=0;
for (int i = 0; i < 10 ;i++) {
int c=10;
sum = sum + add(a, i);
}
G = 321;
//G = G + i + c; // 未定义标识符 "i" 和 "c"
//printf("G:%d; a:%d; sum:%d; c:%d; i:%d\n",G,a,sum,c,i); // c和i无效
printf("g:%d; a:%d; sum:%d;\n", G, a, sum);
}
若全局变量与局部变量同盟,分析结果
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int a = 3, b = 5;
int main() {
int max(int a, int b);
int a = 8;
printf("main里的a:%d; b:%d\n", a, b); // a:8(局部变量) b:5(全局变量)
printf("max=%d\n", max(a, b));
return 0;
}
int max(int a, int b) {
int c;
printf("max里的a:%d; b:%d\n", a, b); // a,b为局部变量
c = a > b ? a : b;
return c;
}
// max=8
变量的存储方式和生存期
存储方法
变量的存储方式有两种:
-
静态存储方式
-
动态存储方式
静态存储方式:指程序运行期间由系统分配固定的存储空间的方式。
动态存储方式:指在程序运行期间根据需要进行的动态分配存储空间的方式。
常量的存储方式
取决于常量的类型和存储类别。一般来说,C语言中的常量存储方式有以下特点:
字面常量(Literal Constants):字符串常量和数值常量(包括整型、浮点型和字符型)通常存储在程序的静态存储区(Static Memory),也被称为常量存储区(Constant Pool)。这个区域在程序运行期间始终存在,不会随函数调用结束而消失。字符串常量尤为特殊,它们在内存中以只读形式存储,不可修改。
const修饰的变量(Const Variables):当使用
const
关键字定义一个常量变量时,虽然它在概念上被视为常量,但在内存中仍可能分配存储空间,且存储在静态存储区。一旦初始化,其值就不能再改变。编译时常量(Compile-Time Constants):对于整型和指针类型的编译时常量(如用
#define
预处理器定义的宏或者枚举常量),它们在编译阶段就被替换成了具体的值,不会在运行时占用内存空间。简而言之,在C语言中,大多数常量在内存中的存储是静态的,并且在程序的整个生命周期内保持不变。字符串常量具有额外的只读属性,防止它们在运行时被修改。而用
const
修饰的变量虽然名义上是常量,但在内存中仍有其专属的存储空间。
内存中供用户使用的存储空间,可分为三部分:
-
程序区
-
静态存储区
-
动态存储器
数据分别存放在静态存储区和动态存储区中,全局变量
全部
存放在静态存储区中,在整个程序执行期间
一直存在,程序开始
时分配存储空间,程序结束
时释放。
一般静态存储区存放全局变量,常量等。
在动态存储区中存放下列数据:
-
函数形式参数。在调用函数时给形参分配存储空间。
-
函数中定义没有用关键字static声明的变量,即自动变量。
-
函数调用时的现场包含和返回地址等。
存储类别
每一个变量和函数有两个属性:数据类型和数据的存储类别
C语言的存储类别包括4种:auto、static、register、extern;前三种用于局部变量,extern用于全局变量
局部变量的存储类别
-
auto—自动局部变量
使用关键字auto作为自动变量的存储列表声明。
函数中的局部变量,如果没有专门用static(静态)声明存储类别,都是动态分配存储空间的。
关键字auto可省略,不写auto则隐含指定为 ”自动存储类别“int foo(int a){ auto int b=2; return a+b; }
-
static—静态局部变量
使用关键字static声明。
函数调用结束后不会消失,而继续保留原值,即其占用的存储空间不释放,在下一次调用该函数时,该变量的值是上一次函数调用结束的值。
非必要情况下不要使用静态局部变量,会多占用内存空间。
建议定义静态局部变量时,同时初始化值,以免每次调用时重新赋值。// 考虑静态变量的 #include<stdio.h> int main() { int foo(int); int a = 2, i; for ( i = 0; i < 3; i++) { printf("%d\n", foo(a)); } return 0; } int foo(int a) { auto int b = 0; // auto可省略,默认局部变量为自动变量 static int c = 3; // static 静态局部变量,每次调用时替换成上一次调用结束后的值 printf("foo c:%d\n", c); b = b + 1; c = c + 1; return a + b + c; } # input foo c:3 7 foo c:4 8 foo c:5 9
对于静态局部变量来说,编译时会自动赋初值0(对数值类型)或空字符 ‘\0’ ,而对于自动局部变量来说,他的值是不确定的。
-
register—寄存器变量
局部变量存放在寄存器中,需要时直接从寄存器中取出参加运算,不必到内存中存取。常用于使用频繁的变量。
编译器能够识别到频繁的编码,从而自动优化它们,放在寄存器上register int f=0;
全局变量的存储类别
全局变量存放在静态存储区中,它们的生存周期固定,存在于程序的整个运行过程。
一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始到本程序文件的结束
-
在一个文件中内扩展外部变量的作用域
在全局变量之前的函数需要引用该外部变量时,则应该在该变量引用处前添加extern关键字对该变量作
外部声明
。调用函数,求3个整数中的较大者
#define _CRT_SECURE_NO_WARNINGS 1 #pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告 #pragma warning(disable:6031) // 禁止显示未经检查的返回值警告 #include<stdio.h> int main() { int max(); extern int A, B, C; // 把外部变量扩展到从此处开始; 扩展尝试去掉extern关键字,看结果是否一样 printf("please enter three interger numbers:"); scanf("%d %d %d", &A, &B, &C); printf("max is %d\n", max()); return 0; } int A, B, C; // 定义外部变量,编译系统会自动将外部(全局)变量赋初值0 int max() { int m; printf("A:%d B:%d C:%d\n",A,B,C); m = A > B ? A : B; if (C > m) { m = C; } return m; } 输入1 2 3 - 添加extern 关键字时 max=3 - 未添加extern关键字时 max=0,因为编译系统会自动将外部(全局)变量赋初值0,而且main函数中的A,B,C是局部变量
-
将外部变量的作用域扩展到其他文件
两个程序文件需要同一个外部变量时,在任意一个文件里定义外部变量,另一个文件里用extern关键字声明该变量。
给定b的值,输入a和m,求a*b和 a m a^m am的值
:文件file1.c #include<stdio.h> int A; int main() { int power(int); int b = 3, c, d, m; printf("enter the numbers a and its power m:\n"); scanf("%d %d", &A, &m); c = A * b; printf("%d * %d=%d\n", A, b, c); d = power(m); printf("%d * * %d=%d\n", A, m, d); return 0; } :文件file2.c extern A; int power(int n) { int i, y = 1; for ( i = 1; i <= n; i++) { y *= A; } return y; }
不需要在file1.c中用#include导入file2.c文件,因为编译系统给会自动从别处寻找已定义的外部变量。在个文件经过编译后,将个目标文件连接成一个可执行文件
-
将外部变量的作用域限制在本文件中
在定义外部变量时添加static关键字声明。file1.c static int A; // 静态外部变量 int main() {......} file2.c extern A; // 不能使用file1.c中全局变量A, 对于其他文件来说,file1.c中的这个静态外部变量是看不见的,不能用的 void foo() {......}
用static声明一个变量的作用:
-
对局部变量用static声明时,把该变量分配到
静态存储区
,在整个程序执行期间不释放,其所分配的空间始终存在。 -
对全局变量用static声明时,则该变量只限于本文件模块(即被声明的文件中)
用auto、static、register声明变量时,是在定义变量的基础上加上这些关键字的,而不能单独使用,extern是单独使用的
static int a=1; extern a; 下面做法是错误的 int a; // 先定义整型变量 static a; // 企图再将变量a声明为静态变量,编译时会被认为重新定义
变量的声明与定义
在函数中出现的对变量的声明(除了用extern声明意外)都是定义,在函数中对其他函数的声明不是函数的定义
内部函数和外部函数
函数本质上是全局的,可以被本文件或其他文件所调用
内部函数
一个函数只能被本文件中的其他函数所调,又称静态函数,通常把本文件所使用的函数和外部变量放在文件的开头,前面都加上关键词static使之局部化,其他文件不能引用,提供程序的可靠性。
static 类型名 函数名(形参表列) {......}
外部函数
定义函数时,在函数首部的最左端加关键词extern,则该函数是外部函数,可供其他文件调用,C语言规定,在定义函数省略extern,则默认为外部函数。
在需要调用此函数的其他文件中,需要对此函数作声明,要加关键字extern,表示该函数是在其他文件中定义的外部函数
extern 类型名 函数名(形参表列) {......}
其他文件调用该函数时,要用extern声明该函数
extern 类型名 函数名(形参表列);
举例
输出下列效果
***************
How do you do!
***************
#include <stdio.h>
void print_message() {
printf("How do you do!\n");
}
int main() {
void print_star(); // 位于主函数之后的函数需要在主函数中声明
print_star();
print_message();
print_star();
return 0;
}
void print_star() {
printf("***************\n");
}
输入两个整数,要求输出其中较大者
#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include <stdio.h>
int max(int x, int y) {
int z; // 零时变量
z = x > y ? x : y;
return z;
}
int main() {
int max(int x, int y); // 对max函数的声明,这里可以不用声明
int a, b, c;
printf("please enter two integer numbers:");
scanf("%d,%d", &a, &b);
c = max(a, b);
printf("max is %d\n", c);
return 0;
}
输入两个实数,用一个函数求出它们的和
#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include <stdio.h>
int main() {
float add(float x, float y);
float a, b, c;
printf("please enter a and b: ");
scanf("%f,%f", &a, &b);
c = add(a, b);
printf("sum is %f", c);
return 0;
}
float add(float x, float y) {
float z;
z = x + y;
return z;
}
输入4个整数,找出其中最大的数,用函数的嵌套调用来处理
#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include <stdio.h>
int max4(int a, int b, int c, int d); // 对max4函数进行声明
int main() {
int a, b, c, d, max;
printf("please enter 4 interger numbers: ");
scanf("%d,%d,%d,%d", &a, &b, &c, &d);
max = max4(a, b, c, d);
printf("max=%d\n", max);
return 0;
}
int max4(int a, int b, int c, int d) { // 定义max4函数
int max2(int a, int b); // 对max2函数进行声明
int m;
m = max2(a, b);
m = max2(m, c);
m = max2(m, d);
return m;
//return max2(max2(max2(a, b), c), d);
}
int max2(int a, int b) {
if (a >= b) {
return a;
}
else {
return b;
}
// return (a >= b) ? a : b;
}
有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生,又说比第2个学生大2岁。问第2个学生,说比第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大。
a g e ( n ) = 10 , ( n = 1 ) age(n)=10,(n=1) age(n)=10,(n=1)
a g e ( n ) = a g e ( n − 1 ) , + 2 ( n > 1 ) age(n)=age(n-1),+2(n>1) age(n)=age(n−1),+2(n>1)
#include <stdio.h>
int age(int n) {
int c;
if (n == 1) {
c = 10;
}
else {
c = age(n - 1) + 2;
}
return c;
}
int main() {
printf("NO.5,age:%d\n", age(5));
return 0;
}
用递归方法求 n ! n! n!
#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include<stdio.h>
int main() {
int fac(int n); // fac函数的声明
int n, y;
printf("input an interger number: ");
scanf("%d", &n);
y = fac(n); // fac函数的调用
printf("%d!=%d\n", n, y);
return 0;
}
int fac(int n) { // fac函数的定义
int f=-1;
if (n < 0) {
printf("n<0,data error!");
}
else if (n == 0 || n == 1) {
f = 1;
}
else {
f = fac(n - 1) * n;
}
return f;
}
如果输入13,求13! 会得不到预期的结果,因为超出int最大表示范围。使用float或double类型
汉诺塔问题
问题描述: 有三根柱子A、B、C,A柱上从下到上堆叠着若干个大小不等的盘子,盘子的直径从下往上逐渐减小(不允许大盘子压在小盘子之上)。任务是将所有盘子从柱子A经过柱子B,最终全部移到柱子C上,并且遵守任何时候大盘子都不能在小盘子之上这一规则。
解决方法: 解决汉诺塔问题的基本思路是采用递归策略,步骤如下:
- 将A柱上除了最下面的一个盘子之外的所有盘子借助C柱移动到B柱上。
- 将A柱底部的盘子直接移动到C柱上。
- 将B柱上的所有盘子借助A柱移动到C柱上,此时所有盘子都在C柱上按照原来的顺序排列。
用递归算法表示,假设n表示盘子的数量,函数hanoi(n, A, B, C)表示将n个盘子从A柱移动到C柱,借助B柱。函数主体可以写作:
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
void hanoi(int n, char one, char two, char three);
int m;
printf("input the number of diskes: ");
scanf("%d",&m);
printf("The step to move %d diskes:\n", m);
hanoi(m, 'A', 'B', 'C');
return 0;
}
void hanoi(int n, char one, char two, char three) {
// 将 n个盘从one座借助two座,移动three座
void move(char x, char y);
if (n == 1) {
move(one, three);
}
else {
hanoi(n - 1, one, three, two);
move(one, three);
hanoi(n - 1, two, one, three);
}
}
void move(char x, char y) {
printf("%c->%c\n",x,y);
}
输入10个数,要求输出其中值最大的元素和该数是第几个数
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
int max(int x, int y);
int a[10], m, n, i;
printf("enter 10 interger numbers: ");
for (i = 0; i < 10; i++) {
scanf("%d", &a[i]);
}
printf("\n");
for (i = 1, m = a[0], n = 0; i < 10; i++) {
if (max(m, a[i]) > m) {
m = max(m, a[i]);
n = i;
}
}
printf("the largest number is %d\nit is the %dth number.\n", m, n + 1);
return 0;
}
int max(int x, int y) {
return (x > y) ? x : y;
}
用一个数组存放10个学生成绩,求平均成绩
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
float average(float array[10]);
float score[10], aver;
int i;
printf("input 10 scores:\n");
for (i = 0; i < 10; i++) {
scanf("%f", &score[i]);
}
printf("\n");
aver = average(score); // 一维数组名作为实参
printf("average score is %5.2f\n", aver);
return 0;
}
float average(float array[10]) { // 可以不指定数组大小
int i;
float aver, sum = array[0];
for (i = 1; i < 10; i++) {
sum = sum + array[i];
}
aver = sum / 10;
return aver;
}
有两个班级,分别有5名和10学生,调用一个average函数分别求这两个班的平均成绩
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
float average(float array[], int n);
float score1[5] = { 98.5,97,91.5,60,55 };
float score2[10] = { 67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5 };
printf("the average of class A is %6.2f\n", average(score1, 5));
printf("the average of class B is %6.2f\n", average(score2, 10));
return 0;
}
float average(float array[],int n) {
int i;
float aver, sum = array[0];
for (i = 1; i < n; i++) {
sum = sum + array[i];
}
aver = sum / n;
return aver;
}
选择排序—对数组中10个整数由小到大排序
每趟选择一个最小的元素放在最终位置,n个元素第i趟比较n-i次
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
void sort(int array[], int n);
int a[10], i;
printf("enter array:\n");
for (i = 0; i < 10; i++) {
scanf("%d", &a[i]);
}
sort(a, 10);
printf("the sorted array: \n");
for (i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
void sort(int array[], int n) {
int i, j, k, t;
for ( i = 0; i < n-1; i++) {
k = i;
for ( j = i+1; j < n; j++) {
if (array[j] < array[k]) {
k = j;
}
}
t = array[k]; // 交换元素
array[k] = array[i];
array[i] = t;
}
}
有一个 3x4 的矩阵,求所有元素最大值
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
int max_value(int array[][4]);
int a[3][4] = { {1,2,3,4} ,{5,7,6,8},{10,9,12,11} };
printf("max value is %d\n", max_value(a));
return 0;
}
int max_value(int array[][4]) {
int i, j, max;
max = array[0][0];
for ( i = 0; i < 3; i++) {
for ( j = 0; j < 4; j++) {
if (array[i][j] > max) {
max = array[i][j];
}
}
}
return max;
}
有一个一维数组存放10名学生的成绩,要求编写一个函数求出平均分、最高分和最低分
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
float Max = 0, Min = 0;
int main() {
float average(float array[], int n);
float ave, score[10] = { 67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5 };
ave = average(score,10);
printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n", Max, Min, ave);
return 0;
}
float average(float array[], int n) {
float aver, sum = array[0];
Max = Min = array[0];
for (int i = 0; i < n; i++) {
if (array[i] > Max) {
Max = array[i];
}
else if (array[i] < Min) {
printf("aa\n");
Min = array[i];
}
sum = sum + array[i];
}
aver = sum / n;
return aver;
}
输出1到5的阶乘值
// 输出1到5的阶乘
#include<stdio.h>
int main() {
int fac(int n);
int i;
for ( i = 1; i <=5; i++) {
printf("%d!=%d\n", i, fac(i));
}
return 0;
}
int fac(int n) {
static int r = 1;
r = r * n;
return r;
}
用外部函数实现,有一个字符串,内有若干个字符,现输入一个字符,要求程序将字符串中该字符删去
file1.c
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
#include<stdio.h>
int main() {
extern void enter_string(char str[]); // 声明外部函数
extern void delete_string(char str[], char ch);
extern void print_string(char str[]);
char c, str[80];
enter_string(str);
printf("please input delete char: ");
scanf("%c",&c);
delete_string(str, c);
print_string(str);
return 0;
}
file2.c
#include <string.h>
#include <stdio.h>
void enter_string(char str[80]) {
printf("please input string: ");
gets(str);
}
void delete_string(char str[], char ch) {
int i, j;
for (i = j = 0; str[i] != '\0'; i++) {
if (str[i] != ch) {
str[j++] = str[i];
}
}
str[j] = '\0';
}
extern void print_string(char str[]) {
printf("%s\n", str);
}
引申:不用extern声明外部变量,用#include "file2.c"导入