C语言04函数与递归
1 函数的定义
1.1 问题
自定义两个简单的函数,使用return返回数据。
1.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:函数的定义
代码如下所示:
- #include
- int getint()
- {
- return 10;
- }
- double getdouble()
- {
- return 5.5;
- }
- int main()
- {
- int n;
- n = getint();
- printf ("%d\n", n);
- double d;
- d = getdouble();
- printf("%lf\n", d);
- return 0;
- }
上述代码中,以下代码:
- int getint()
- {
- return 10;
- }
定义了一个函数getint,该函数返回一个整型数据,没有参数。
上述代码中,以下代码:
- double getdouble()
- {
- return 5.5;
- }
定义了一个函数getdouble,该函数返回一个双精度浮点型数据,没有参数。
上述代码中,以下代码:
- int n;
- n = getint();
- printf ("%d\n", n);
首先,定义一个整型变量n,用于存储getint函数的返回值。
然后,调用函数getint得到返回值,并存储在变量n中。
最后,使用函数printf输出变量n的内容。
上述代码中,以下代码:
- double d;
- d = getdouble();
- printf("%lf\n", d);
首先,定义一个双精度浮点型变量d,用于存储getdouble函数的返回值。
然后,调用函数getdouble得到返回值,并存储在变量d中。
最后,使用函数printf输出变量d的内容。
1.3 完整代码
本案例的完整代码如下所示:
- #include
- int getint()
- {
- return 10;
- }
- double getdouble()
- {
- return 5.5;
- }
- int main()
- {
- int n;
- n = getint();
- printf ("%d\n", n);
- double d;
- d = getdouble();
- printf("%lf\n", d);
- return 0;
- }
2 函数的声明
2.1 问题
定义两个函数,分别测试隐式声明和显式声明,同时体现出隐式声明中类型的自动提示效果。
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:函数的声明
代码如下所示:
- #include
- int main()
- {
- f1();
- double f2(/*void*//*int i*/);
- f2(1,2);
- return 0;
- }
- int f1()
- {
- printf("f1()\n");
- return 0;
- }
- double f2(int a,int b)
- {
- printf("f2()\n");
- return 3.0;
- }
上述代码中,以下代码:
- f1();
由于在调用f1前未对其进行声明,所以是隐式声明。
上述代码中,以下代码:
- double f2(/*void*//*int i*/);
对函数f2进行显示声明。其中,参数可以省略。如果没有任何参数,表示可以接受任意的参数,如果写void表示不接受任何参数。
上述代码中,以下代码:
- f2(1,2);
调用函数f2。
上述代码中,以下代码:
- int f1()
- {
- printf("f1()\n");
- return 0;
- }
定义了一个函数f1。该函数没有参数,返回一个整型数据。
上述代码中,以下代码:
- double f2(int a,int b)
- {
- printf("f2()\n");
- return 3.0;
- }
定义了一个函数f2。该函数有两个参数,分别是整型变量a和b。在函数体中并没有使用这两个参数,这是允许的。
2.3 完整代码
本案例的完整代码如下所示:
- #include
- int main()
- {
- f1();
- double f2(/*void*//*int i*/);
- f2(1,2);
- return 0;
- }
- int f1()
- {
- printf("f1()\n");
- return 0;
- }
- double f2(int a,int b)
- {
- printf("f2()\n");
- return 3.0;
- }
3 函数参数的应用
3.1 问题
定义两个函数,分别体现参数传递时的值传递和数组做参数时的处理方法。
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:函数参数的应用
代码如下所示:
- #include
- void fun1(int a)
- {
- printf("形参a从主函数传入fun1时的值为%d\n", a);
- a = a + 10;
- printf("形参a在fun1中改变后的值为%d\n", a);
- }
- void fun2(int array[])
- {
- printf("形参array[0]从主函数传入fun2时的值为%d\n", array[0]);
- array[0] = array[0] + 10;
- printf("形参array[0]在fun2中改变后的值为%d\n", array[0]);
- }
- int main()
- {
- int a = 5;
- int array[10] = {1};
- printf("变量a在调用函数fun1之前的值为%d\n", a);
- fun1(a);
- printf("变量a在调用函数fun1之后的值为%d\n", a);
- printf("\n");
- printf("数组元素a[0]在调用函数fun2之前的值为%d\n", array[0]);
- fun2(array);
- printf("数组元素a[0]在调用函数fun2之后的值为%d\n", array[0]);
- return 0;
- }
上述代码中,以下代码:
- void fun1(int a)
- {
- printf("形参a从主函数传入fun1时的值为%d\n", a);
- a = a + 10;
- printf("形参a在fun1中改变后的值为%d\n", a);
- }
首先,定义了一个函数fun1,该函数有一个参数,为整型变量a。
然后,使用函数printf输出形参a从调用函数传入的值。
下一步,将形参a加上10。
最后,再使用函数printf输出形参a加上10后的值。两次调用可以看出形参a的变化情况。
上述代码中,以下代码:
- void fun2(int array[])
- {
- printf("形参array[0]从主函数传入fun2时的值为%d\n", array[0]);
- array[0] = array[0] + 10;
- printf("形参array[0]在fun2中改变后的值为%d\n", array[0]);
- }
首先,定义了一个函数fun1,该函数有一个参数,为整型数组array。
然后,使用函数printf输出形参数组的第一个元素array[0]从调用函数传入的值。
下一步,将形参数组的第一个元素array[0]加上10。
最后,再使用函数printf输出形参数组的第一个元素array[0]加上10后的值。两次调用可以看出形参数组的第一个元素array[0]的变化情况。
上述代码中,以下代码:
- int main()
- {
- int a = 5;
- int array[10] = {1};
在主函数中定义一个整型变量a和一个整型数组array,并将变量a初始化为5,将数组array的第一个元素初始化成1。
上述代码中,以下代码:
- printf("变量a在调用函数fun1之前的值为%d\n", a);
- fun1(a);
- printf("变量a在调用函数fun1之后的值为%d\n", a);
首先,使用函数printf输出变量a在调用函数fun1之前的值。
然后,调用函数fun1。
最后,再使用函数printf输出变量a在调用函数fun1之后的值。两次调用可以看出变量a的变化情况。
上述代码中,以下代码:
- printf("数组元素a[0]在调用函数fun2之前的值为%d\n", array[0]);
- fun2(array);
- printf("数组元素a[0]在调用函数fun2之后的值为%d\n", array[0]);
首先,使用函数printf输出整型数组array的第一个元素array[0]在调用函数fun2之前的值。
然后,调用函数fun2。
最后,再使用函数printf输出整型数组array的第一个元素array[0]在调用函数fun2之后的值。两次调用可以看出整型数组array的第一个元素array[0]的变化情况。
3.3 完整代码
本案例的完整代码如下所示:
- #include
- void fun1(int a)
- {
- printf("形参a从主函数传入fun1时的值为%d\n", a);
- a = a + 10;
- printf("形参a在fun1中改变后的值为%d\n", a);
- }
- void fun2(int array[])
- {
- printf("形参array[0]从主函数传入fun2时的值为%d\n", array[0]);
- array[0] = array[0] + 10;
- printf("形参array[0]在fun2中改变后的值为%d\n", array[0]);
- }
- int main()
- {
- int a = 5;
- int array[10] = {1};
- printf("变量a在调用函数fun1之前的值为%d\n", a);
- fun1(a);
- printf("变量a在调用函数fun1之后的值为%d\n", a);
- printf("\n");
- printf("数组元素a[0]在调用函数fun2之前的值为%d\n", array[0]);
- fun2(array);
- printf("数组元素a[0]在调用函数fun2之后的值为%d\n", array[0]);
- return 0;
- }
4 函数和程序的终止
4.1 问题
定义一个函数,分别调用return语句和exit()函数,并在主函数中调用测试效果。
4.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:函数和程序的终止
代码如下所示:
- #include
- #include
- void fun(int e)
- {
- if (1 == e)
- exit(exit_success);
- else
- return;
- }
- int main()
- {
- int n;
- printf("输入1在函数fun中调用exit函数\n输入2函数fun中执行return语句\n请选择输入:");
- scanf("%d", &n);
- fun(n);
- printf("选择2才会输出此句");
- return 0;
- }
上述代码中,以下代码:
- void fun(int e)
- {
- if (1 == e)
- exit(exit_success);
- else
- return;
- }
定义了一个函数,该函数有一个参数为整型变量e。当参数e为1时,函数fun将调用函数exit退出程序;当参数e为其它值时,函数fun执行return语句返回。
上述代码中,以下代码:
- int n;
- printf("输入1在函数fun中调用exit函数\n输入2函数fun中执行return语句\n请选择输入:");
- scanf("%d", &n);
首先,定义一个整型变量n,用于存储用户输入的选择。
然后,使用函数printf提示输入选择。
最后,使用函数scanf输入一个选择到变量n中。
上述代码中,以下代码:
- fun(n);
将用户的选择,变量n,作为实参调用函数fun。
上述代码中,以下代码:
- printf("选择2才会输出此句");
当用户选择1时,程序会在函数fun中退出,则此语句将不被执行。只有用户选择了2或其他值时,函数fun将执行return语句返回,此语句才被执行。
4.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- void fun(int e)
- {
- if (1 == e)
- exit(exit_success);
- else
- return;
- }
- int main()
- {
- int n;
- printf("输入1在函数fun中调用exit函数\n输入2函数fun中执行return语句\n请选择输入:");
- scanf("%d", &n);
- fun(n);
- printf("选择2才会输出此句\n");
- return 0;
- }
5 递归和递推的应用
5.1 问题
分别使用递归函数和循环递推的方式实现n的阶乘。
5.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:递归和递推的应用。
代码如下所示:
- #include
- int factorial(int n)
- {
- if (1 == n)
- return 1;
- int f;
- f = n * factorial(n - 1);
- return f;
- }
- int main()
- {
- int n;
- printf("请输入求阶乘的数:");
- scanf("%d", &n);
- int f = 1;
- for (int i = 2; i <= n; i++)
- f *= i;
- printf("递推方法求得%d的阶乘为%d\n", n, f);
- f = factorial(n);
- printf("递归方法求得%d的阶乘为%d\n", n, f);
- return 0;
- }
上述代码中,以下代码:
- int factorial(int n)
- {
- if (1 == n)
- return 1;
- int f;
- f = n * factorial(n - 1);
- return f;
- }
定义递归函数factorial,用于计算整数n的阶乘。在该函数中,以下语句:
- if (1 == n)
- return 1;
为递归函数的出口,因为1的阶乘还是1。在该函数中,以下语句:
- int f;
- f = n * factorial(n - 1);
如果求整数n的阶乘,则转化为求n乘以n–1的阶乘,而n–1的阶乘的计算方法还是调用factorial函数,只是参数变成n-1。
上述代码中,以下代码:
- int main()
- {
- int n;
- printf("请输入求阶乘的数:");
- scanf("%d", &n);
首先,定义一个整型变量n,用于存储求阶乘的数。
然后,使用函数printf提示输入求阶乘的数。
最后,使用函数scanf输入求阶乘的数到变量n中。
上述代码中,以下代码:
- int f = 1;
- for (int i = 2; i <= n; i++)
- f *= i;
- printf("递推方法求得%d的阶乘为%d\n", n, f);
是使用递推的方法求整数n的阶乘,n的阶乘是计算方法为1x2x3x· · ·xn,所以使用循环逐次相乘,得到整数n的阶乘。
上述代码中,以下代码:
- f = factorial(n);
- printf("递归方法求得%d的阶乘为%d\n", n, f);
是使用递归的方法求整数n的阶乘,调用函数factorial,得到整数n的阶乘。
5.3 完整代码
本案例的完整代码如下所示:
- #include
- int factorial(int n)
- {
- if (1 == n)
- return 1;
- int f;
- f = n * factorial(n - 1);
- return f;
- }
- int main()
- {
- int n;
- printf("请输入求阶乘的数:");
- scanf("%d", &n);
- int f = 1;
- for (int i = 2; i <= n; i++)
- f *= i;
- printf("递推方法求得%d的阶乘为%d\n", n, f);
- f = factorial(n);
- printf("递归方法求得%d的阶乘为%d\n", n, f);
- return 0;
- }
6 递归和递推的比较
6.1 问题
定义两个函数,分别用递归和递推方式计算费氏数列的第n项,并利用time命令查看时间差。
6.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:递归和递推的应用。
代码如下所示:
- #include
- #include
- long fib(int n)
- {
- long f1 = 1;
- long f2 = 1;
- long fn = 1;
- for (int i = 2; i < n; i++)
- {
- fn = f1 + f2;
- f1 = f2;
- f2 = fn;
- }
- return fn;
- }
- long fib_f(int n)
- {
- if (1 == n || 2 == n)
- return 1;
- return fib_f(n - 1) + fib_f(n - 2);
- }
- int main()
- {
- int n;
- printf("请输入月份:");
- scanf("%d", &n);
- time_t begin = time(0);
- long sum = fib(n);
- time_t stop = time(0);
- printf("费氏数列第%d月兔子数为%ld,递推方法用时%lf秒\n", n, sum, difftime(stop, begin));
- begin = time(0);
- sum = fib_f(n);
- stop = time(0);
- printf("费氏数列第%d月兔子数为%ld,递推方法用时%lf秒\n", n, sum, difftime(stop, begin));
- return 0;
- }
上述代码中,以下代码:
- long fib(int n)
- {
- long f1 = 1;
- long f2 = 1;
- long fn = 1;
- for (int i = 2; i < n; i++)
- {
- fn = f1 + f2;
- f1 = f2;
- f2 = fn;
- }
- return fn;
- }
定义了一个使用递推的方法求费氏数列的函数fib,该函数有一个参数是要求第几个月的兔子数。费氏数列的计算公式为:
f1 = 1
f2 = 1
fn = fn-1 + fn-2
上述代码中,以下代码:
- fn = f1 + f2;
按计算公式fn = fn-1 + fn-2计算。
上述代码中,以下代码:
- f1 = f2;
- f2 = fn;
为下一次循环中公式fn = fn-1 + fn-2中的f1和f2做准备。
上述代码中,以下代码:
- long fib_f(int n)
- {
- if (1 == n || 2 == n)
- return 1;
- return fib_f(n - 1) + fib_f(n - 2);
- }
定义了一个使用递归的方法求费氏数列的函数fib_f,该函数有一个参数是要求第几个月的兔子数。该函数中,以下代码:
- if (1 == n || 2 == n)
- return 1;
为递归出口,根据公式,第1个月和第2个月的兔子数均为1。该函数中,以下代码:
- return fib_f(n - 1) + fib_f(n - 2);
根据公式fn = fn-1 + fn-2求第n个月的兔子数,因为求第n-1个月和第n-2个月与求第n个月的兔子数方法相同,都是调用fib_f函数,只是参数不同罢了,所以使用递归方法。
上述代码中,以下代码:
- int main()
- {
- int n;
- printf("请输入月份:");
- scanf("%d", &n);
首先,定义一个整型变量n,用于存储求兔子数的月份数。
然后,使用函数printf提示输入求兔子数的月份数。
最后,使用函数scanf输入求兔子数的月份数到变量n中。
上述代码中,以下代码:
- time_t begin = time(0);
- long sum = fib(n);
- time_t stop = time(0);
- printf("费氏数列第%d月兔子数为%ld,递推方法用时%lf秒\n", n, sum, difftime(stop, begin));
首先,使用time函数记录调用递推方法函数fib开始的时间。
然后,调用函数fib计算输入月份的兔子数。
下一步,使用time函数记录调用递推方法函数fib结束的时间。
最后,打印输入月份的兔子数和计算所用的时间数。
上述代码中,以下代码:
- begin = time(0);
- sum = fib_f(n);
- stop = time(0);
- printf("费氏数列第%d月兔子数为%ld,递推方法用时%lf秒\n", n, sum, difftime(stop, begin));
首先,使用time函数记录调用递归方法函数fib_f开始的时间。
然后,调用函数fib_f计算输入月份的兔子数。
下一步,使用time函数记录调用递归方法函数fib_f结束的时间。
最后,打印输入月份的兔子数和计算所用的时间数。
6.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- long fib(int n)
- {
- long f1 = 1;
- long f2 = 1;
- long fn = 1;
- for (int i = 2; i < n; i++)
- {
- fn = f1 + f2;
- f1 = f2;
- f2 = fn;
- }
- return fn;
- }
- long fib_f(int n)
- {
- if (1 == n || 2 == n)
- return 1;
- return fib_f(n - 1) + fib_f(n - 2);
- }
- int main()
- {
- int n;
- printf("请输入月份:");
- scanf("%d", &n);
- time_t begin = time(0);
- long sum = fib(n);
- time_t stop = time(0);
- printf("费氏数列第%d月兔子数为%ld,递推方法用时%lf秒\n", n, sum, difftime(stop, begin));
- begin = time(0);
- sum = fib_f(n);
- stop = time(0);
- printf("费氏数列第%d月兔子数为%ld,递推方法用时%lf秒\n", n, sum, difftime(stop, begin));
- return 0;
- }
7 递归的典型应用
7.1 问题
使用递归实现汉诺塔。
汉诺塔是指法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
7.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:递归的典型应用。
代码如下所示:
- #include
- void move(int n,char a,char b,char c)
- {
- if(n==1)
- printf("\t%c->%c\n",a,c);
- else
- {
- move(n-1,a,c,b);
- printf("\t%c->%c\n",a,c);
- move(n-1,b,a,c);
- }
- }
- int main()
- {
- int n;
- printf("请输入要移动的块数:");
- scanf("%d",&n);
- move(n,'a','b','c');
- return 0;
- }
上述代码中,以下代码:
- void move(int n,char a,char b,char c)
- {
- if(n==1)
- printf("\t%c->%c\n",a,c);
- else
- {
- move(n-1,a,c,b);
- printf("\t%c->%c\n",a,c);
- move(n-1,b,a,c);
- }
- }
定义了一个递归函数move,用来模拟移动盘子。该函数有四个参数,说明如下:
第一个参数为盘子的数量。
第二个参数为从这根针移走。
第三个参数为经过这根针。
第四个参数为移到这根针。
在该函数中,以下代码:
- if(n==1)
- printf("\t%c->%c\n",a,c);
表示当n只有1个盘子的时候直接从a移动到c。
在该函数中,以下代码:
- move(n-1,a,c,b);
表示第n-1个盘子要从a通过c移动到b。
在该函数中,以下代码:
- printf("\t%c->%c\n",a,c);
输出从a移动到c。
在该函数中,以下代码:
- move(n-1,b,a,c);
表示n-1个盘子移动到b后,b变开始盘,b通过a移动到c。
上述代码中,以下代码:
- int main()
- {
- int n;
- printf("请输入要移动的块数:");
- scanf("%d",&n);
首先,定义一个整型变量n,用于存储要移动的盘子数。
然后,使用函数printf提示输入要移动的盘子数。
最后,使用函数scanf输入要移动的盘子数到变量n中。
上述代码中,以下代码:
- move(n,'a','b','c');
启动移动函数,输出移动过程。
7.3 完整代码
本案例的完整代码如下所示:
- #include
- void move(int n,char a,char b,char c)
- {
- if(n==1)
- printf("\t%c->%c\n",a,c); //当n只有1个的时候直接从a移动到c
- else
- {
- move(n-1,a,c,b); //第n-1个要从a通过c移动到b
- printf("\t%c->%c\n",a,c);
- move(n-1,b,a,c); //n-1个移动过来之后b变开始盘,b通过a移动到c,这边很难理解
- }
- }
- int main()
- {
- int n;
- printf("请输入要移动的块数:");
- scanf("%d",&n);
- move(n,'a','b','c');
- return 0;
- }
标准函数库
1 格式化输入输出
1.1 问题
测试格式化输入输出函数的中格式字符串的各种效果。
1.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:格式化输入输出
代码如下所示:
- #include
- int main()
- {
- int a = 0, b = 0;
- scanf("%*d%d", &a, &b);
- printf("a = %d, b = %d\n", a, b);
- printf("%10d,%-10d,%d\n", 100, 200, 300);
- printf("%08d\n", 100);
- printf("%0*d\n", 8, 100);
- printf("0%o,0x%x\n", 8, 16);
- printf("%.2f\n", 12.34567);
- printf("%10.2f\n", 12.34567);
- return 0;
- }
上述代码中,以下代码:
- scanf("%*d%d", &a, &b);
%*d中的*表示禁止字符,即输入的第一个数据被跳过,不进行赋值。
上述代码中,以下代码:
- printf("%10d,%-10d,%d\n", 100, 200, 300);
首先,%10d中的10表示该数据如果不足10位则左边补空格。
然后,%-10d中的-10表示该数据如果不足10位则右边补空格。
上述代码中,以下代码:
- printf("%08d\n", 100);
%08d中的08表示数据如果不足8位则左边补0。
上述代码中,以下代码:
- printf("%0*d\n", 8, 100);
%0*d中的0*表示数据不足后面第一个参数,即8,所含的位数,则左边补0。
上述代码中,以下代码:
- printf("0%o,0x%x\n", 8, 16);
0%o表示将数据按8进制输出;0x%x表示将数据按16进制输出。
上述代码中,以下代码:
- printf("%.2f\n", 12.34567);
%.2f表示将数据保留2位小数。
上述代码中,以下代码:
- printf("%10.2f\n", 12.34567);
%10.2表示将数据保留2位小数,且包括小数点在内的位数不足10位时,左边补0。
1.3 完整代码
本案例的完整代码如下所示:
- #include
- int main()
- {
- int a = 0, b = 0;
- scanf("%*d%d", &a, &b);
- printf("a = %d, b = %d\n", a, b);
- printf("%10d,%-10d,%d\n", 100, 200, 300);
- printf("%08d\n", 100);
- printf("%0*d\n", 8, 100);
- printf("0%o,0x%x\n", 8, 16);
- printf("%.2f\n", 12.34567);
- printf("%10.2f\n", 12.34567);
- return 0;
- }
2 动态分配内存
2.1 问题
动态分配基本类型和字符串的内存,并进行数据存储和取出打印。(最后记得用free()释放)
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:动态分配内存
代码如下所示:
- #include
- #include
- #include
- int main()
- {
- int *pi = (int*)malloc(sizeof(int));
- *pi = 10;
- printf("*pi = %d\n", *pi);
- free(pi);
- float *pf = (float*)malloc(sizeof(float));
- *pf = 10.23;
- printf("*pf = %f\n", *pf);
- free(pf);
- double *pd = (double*)malloc(sizeof(double));
- *pd = 123.456;
- printf("*pd = %lf\n", *pd);
- free(pd);
- char *pstr = (char*)malloc(1024);
- strcpy(pstr, "将字符串放在堆上");
- printf("%s\n", pstr);
- free(pstr);
- return 0;
- }
上述代码中,以下代码:
- int *pi = (int*)malloc(sizeof(int));
在堆上动态分配一个整型变量。
上述代码中,以下代码:
- *pi = 10;
将动态分配的整型变量赋值。
上述代码中,以下代码:
- printf("*pi = %d\n", *pi);
使用printf函数输出动态变量的值。
上述代码中,以下代码:
- free(pi);
释放动态变量所占的存储空间。
上述代码中,以下代码:
- float *pf = (float*)malloc(sizeof(float));
在堆上动态分配一个单精度浮点型变量。
上述代码中,以下代码:
- *pf = 10.23;
将动态分配的单精度浮点型变量赋值。
上述代码中,以下代码:
- printf("*pf = %f\n", *pf);
使用printf函数输出动态变量的值。
上述代码中,以下代码:
- free(pf);
释放动态变量所占的存储空间。
上述代码中,以下代码:
- double *pd = (double*)malloc(sizeof(double));
在堆上动态分配一个双精度浮点型变量。
上述代码中,以下代码:
- *pd = 123.456;
将动态分配的双精度浮点型变量赋值。
上述代码中,以下代码:
- printf("*pd = %lf\n", *pd);
使用printf函数输出动态变量的值。
上述代码中,以下代码:
- free(pd);
释放动态变量所占的存储空间。
上述代码中,以下代码:
- char *pstr = (char*)malloc(1024);
在堆上动态分配一个字符型数组。
上述代码中,以下代码:
- strcpy(pstr, "将字符串放在堆上");
将字符型数组赋值为字符串。
上述代码中,以下代码:
- printf("%s\n", pstr);
使用printf函数输出动态字符型数组。
上述代码中,以下代码:
- free(pstr);
释放动态字符型数组所占的存储空间。
2.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- #include
- int main()
- {
- int *pi = (int*)malloc(sizeof(int));
- *pi = 10;
- printf("*pi = %d\n", *pi);
- free(pi);
- float *pf = (float*)malloc(sizeof(float));
- *pf = 10.23;
- printf("*pf = %f\n", *pf);
- free(pf);
- double *pd = (double*)malloc(sizeof(double));
- *pd = 123.456;
- printf("*pd = %lf\n", *pd);
- free(pd);
- char *pstr = (char*)malloc(1024);
- strcpy(pstr, "将字符串放在堆上");
- printf("%s\n", pstr);
- free(pstr);
- return 0;
- }
3 动态分配内存(续1)
3.1 问题
动态分配整型数组和结构的内存,并进行数据存储和取出打印。(最后记得用free()释放)
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:动态分配内存(续1)
代码如下所示:
- #include
- #include
- int main()
- {
- int *array = (int *)malloc(sizeof(int) * 10);
- for (int i = 0; i < 10; i++)
- array[i] = i + 1;
- for (int i = 0; i < 10; i++)
- printf("%d ", array[i]);
- printf("\n");
- free(array);
- struct data
- {
- int a;
- double b;
- char c;
- };
- struct data *p = (struct data*)malloc(sizeof(struct data));
- p->a = 10;
- p->b = 12.34;
- p->c = 'a';
- printf("%d %lf %c\n", p->a, p->b, p->c);
- free(p);
- return 0;
- }
上述代码中,以下代码:
- int *array = (int *)malloc(sizeof(int) * 10);
在堆上定义了一个整型数组。该数组共有10个元素。
上述代码中,以下代码:
- for (int i = 0; i < 10; i++)
- array[i] = i + 1;
使用循环对堆上的数组元素进行逐个赋值。
上述代码中,以下代码:
- for (int i = 0; i < 10; i++)
- printf("%d ", array[i]);
- printf("\n");
使用循环遍历输出堆上的数组中的所有元素。
上述代码中,以下代码:
- free(array);
释放堆上的整型数组。
上述代码中,以下代码:
- struct data
- {
- int a;
- double b;
- char c;
- };
定义一个结构体data,有三个成员,整型变量a,双精度浮点型变量b,字符型变量c。
上述代码中,以下代码:
- struct data *p = (struct data*)malloc(sizeof(struct data));
在堆上动态分配一个结构体data的变量。
上述代码中,以下代码:
- p->a = 10;
- p->b = 12.34;
- p->c = 'a';
対堆上的结构体变量的每个成员进行赋值。
上述代码中,以下代码:
- printf("%d %lf %c\n", p->a, p->b, p->c);
使用printf函数输出堆上的结构体data的变量。
上述代码中,以下代码:
- free(p);
释放堆上的结构体data的变量。
3.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- int main()
- {
- int *array = (int *)malloc(sizeof(int) * 10);
- for (int i = 0; i < 10; i++)
- array[i] = i + 1;
- for (int i = 0; i < 10; i++)
- printf("%d ", array[i]);
- printf("\n");
- free(array);
- struct data
- {
- int a;
- double b;
- char c;
- };
- struct data *p = (struct data*)malloc(sizeof(struct data));
- p->a = 10;
- p->b = 12.34;
- p->c = 'a';
- printf("%d %lf %c\n", p->a, p->b, p->c);
- free(p);
- return 0;
- }
4 时间函数的使用
4.1 问题
打印年月日小时分秒格式的当前时间。
4.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:时间函数的使用
代码如下所示:
- #include
- #include
- int main()
- {
- time_t t = time(0);
- struct tm * local = localtime(&t);
- printf("%d年%d月%d日 %d:%d:%d\n", 1900 + local->tm_year, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec);
- return 0;
- }
上述代码中,以下代码:
- time_t t = time(0);
使用函数time获取当前系统时间。
上述代码中,以下代码:
- struct tm * local = localtime(&t);
将系统时间转换成本地时间。
上述代码中,以下代码:
- printf("%d年%d月%d日 %d:%d:%d\n", 1900 + local->tm_year, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec);
使用printf函数输出本地时间。
4.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- int main()
- {
- time_t t = time(0);
- struct tm * local = localtime(&t);
- printf("%d年%d月%d日 %d:%d:%d\n", 1900 + local->tm_year, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec);
- return 0;
- }
输入输出函数(io)
1 打开文件
1.1 问题
用各种模式打开文件。
1.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:格式化输入输出
代码如下所示:
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
- fp=fopen("file.c","a");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
- return 0;
- }
上述代码中,以下代码:
- file*fp=null;
定义一个file类型的指针fp。
上述代码中,以下代码:
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
首先,使用函数fopen打开一个文件,该函数有两个参数,说明如下:
第一个参数为字符串包含欲打开的文件路径及文件名。
第二个参数为字符串代表文件打开方式。
在上述语句中,打开的文件名为当前目录下的file.c。使用w方式打开,该方式打开只写文件,若文件存在则清空原文件,若不存在新建。
然后,使用函数fclose关闭打开的文件。
上述代码中,以下代码:
- fp=fopen("file.c","a");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
首先,使用函数fopen打开一个文件。
在上述语句中,打开的文件名为当前目录下的file.c。使用a方式打开,该方式以追加的方式打开只写文件,若文件存在则在最后追加写入,若不存在新建。
然后,使用函数fclose关闭打开的文件。
上述代码中,以下代码:
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
首先,使用函数fopen打开一个文件。
在上述语句中,打开的文件名为当前目录下的file.c。使用r方式打开,该方式打开只读文件,该文件必须存在。
然后,使用函数fclose关闭打开的文件。
1.3 完整代码
本案例的完整代码如下所示:
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
- fp=fopen("file.c","a");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- fclose(fp);
- fp=null;
- return 0;
- }
2 使用fscanf()和fprintf()读写文件
2.1 问题
fscanf函数的功能是从一个流中执行格式化输入,fscanf遇到空格和换行时结束。
fprintf函数的功能是传送格式化输出到一个文件中。
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用fscanf()和fprintf()读写文件
代码如下所示:
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- int a = 10;
- float f = 12.34;
- double d = 12345.6789;
- char c = 'a';
- fprintf(fp, "%c %d %f %lf", c, a, f, d);
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- char c1;
- int a1;
- float f1;
- double d1;
- fscanf(fp, "%c%d%f%lf", &c1, &a1, &f1, &d1);
- printf("%c\n%d\n%f\n%lf\n", c1, a1, f1, d1);
- fclose(fp);
- fp=null;
- return 0;
- }
上述代码中,以下代码:
- file*fp=null;
定义一个file类型的指针fp。
上述代码中,以下代码:
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
使用函数fopen用w的方式打开一个文件file.c。
上述代码中,以下代码:
- int a = 10;
- float f = 12.34;
- double d = 12345.6789;
- char c = 'a';
定义四个变量,并对它们进行初始化。
上述代码中,以下代码:
- fprintf(fp, "%c %d %f %lf", c, a, f, d);
使用函数fprintf用格式化方法将上述四个变量写入文件中。该函数与printf使用方法非常类似。
上述代码中,以下代码:
- float *pf = (float*)malloc(sizeof(float));
在堆上动态分配一个单精度浮点型变量。
上述代码中,以下代码:
- fclose(fp);
- fp=null;
使用函数fclose关闭打开的文件。
上述代码中,以下代码:
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
首先,使用函数fopen用r的方式重新打开文件file.c。
上述代码中,以下代码:
- char c1;
- int a1;
- float f1;
- double d1;
重新定义四个新的变量,但并不对它们进行初始化。
上述代码中,以下代码:
- fscanf(fp, "%c%d%f%lf", &c1, &a1, &f1, &d1);
使用函数fscanf用格式化方法从文件file.c中读入数据到这四个新的变量中。该函数与scanf使用方法非常类似。
上述代码中,以下代码:
- printf("%c\n%d\n%f\n%lf\n", c1, a1, f1, d1);
使用函数printf输出这四个新的变量值,已验证读入的效果。
上述代码中,以下代码:
- fclose(fp);
- fp=null;
使用函数fclose关闭打开的文件。
2.3 完整代码
本案例的完整代码如下所示:
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- int a = 10;
- float f = 12.34;
- double d = 12345.6789;
- char c = 'a';
- fprintf(fp, "%c %d %f %lf", c, a, f, d);
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- char c1;
- int a1;
- float f1;
- double d1;
- fscanf(fp, "%c%d%f%lf", &c1, &a1, &f1, &d1);
- printf("%c\n%d\n%f\n%lf\n", c1, a1, f1, d1);
- fclose(fp);
- fp=null;
- return 0;
- }
3 使用fread()和fwrite()读写文件
3.1 问题
使用fwrite()和fread()读写int、double、字符串类型的数据,先写入后读取。
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用fread()和fwrite()读写文件
代码如下所示:
- #include
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- int a = 10;
- double d = 12345.6789;
- char str[1024] = "this is a string.";
- fwrite(&a, sizeof(int), 1, fp);
- fwrite(&d, sizeof(double), 1, fp);
- int len = strlen(str) + 1;
- fwrite(&len, sizeof(int), 1, fp);
- fwrite(str, sizeof(char), len, fp);
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- int a1;
- double d1;
- char str1[1024];
- fread(&a1, sizeof(int), 1, fp);
- fread(&d1, sizeof(double), 1, fp);
- int len1;
- fread(&len1, sizeof(int), 1, fp);
- fread(str1, sizeof(char), len, fp);
- printf("%d\n%lf\n%s\n", a1, d1, str1);
- fclose(fp);
- fp=null;
- return 0;
- }
上述代码中,以下代码:
- file*fp=null;
定义一个file类型的指针fp。
上述代码中,以下代码:
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
使用函数fopen用w的方式打开一个文件file.c。
上述代码中,以下代码:
- int a = 10;
- double d = 12345.6789;
- char str[1024] = "this is a string.";
定义两个变量和一个数组,并对它们进行初始化。
上述代码中,以下代码:
- fwrite(&a, sizeof(int), 1, fp);
使用fwrite函数将变量a写入文件。该函数有四个参数,说明如下:
第一个参数为是一个指针,是要获取写入文件的数据的地址。
第二个参数为要写入内容的单字节数。
第三个参数为要进行写入第二个参数中字节的数据项的个数。
第四个参数为目标文件指针。
上述代码中,以下代码:
- fwrite(&d, sizeof(double), 1, fp);
使用fwrite函数将变量d写入文件。
上述代码中,以下代码:
- int len = strlen(str) + 1;
- fwrite(&len, sizeof(int), 1, fp);
- fwrite(str, sizeof(char), len, fp);
使用fwrite函数将字符数组str写入文件。写入字符数组时,应先将该数组中字符串的长度存入文件,再存入字符串本身,这样有理由读文件时,定义读取字符串的长度。
上述代码中,以下代码:
- fclose(fp);
- fp=null;
使用函数fclose关闭打开的文件。
上述代码中,以下代码:
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
使用函数fopen用r的方式重新打开文件file.c。
上述代码中,以下代码:
- int a1;
- double d1;
- char str1[1024];
重新定义两个变量和一个数组,但并不对它们进行初始化。
上述代码中,以下代码:
- fread(&a1, sizeof(int), 1, fp);
使用fread函数从文件中读入数据放在变量a1中。该函数有四个参数,说明如下:
第一个参数为是一个指针,是要将获取的数据写入到的地址。
第二个参数为要读取内容的单字节数。
第三个参数为要进行读取第二个参数中字节的数据项的个数。
第四个参数为目标文件指针。
上述代码中,以下代码:
- fread(&d1, sizeof(double), 1, fp);
使用fread函数从文件中读入数据放在变量d1中。
上述代码中,以下代码:
- int len1;
- fread(&len1, sizeof(int), 1, fp);
- fread(str1, sizeof(char), len, fp);
使用fread函数从文件中读入数据放在字符数组str中。在读取字符串前,先读取该字符串的长度,然后根据长度读取字符串的内容。
上述代码中,以下代码:
- printf("%d\n%lf\n%s\n", a1, d1, str1);
使用printf函数验证读取的内容是否正确。
上述代码中,以下代码:
- fclose(fp);
- fp=null;
使用函数fclose关闭打开的文件。
3.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- int a = 10;
- double d = 12345.6789;
- char str[1024] = "this is a string.";
- fwrite(&a, sizeof(int), 1, fp);
- fwrite(&d, sizeof(double), 1, fp);
- int len = strlen(str) + 1;
- fwrite(&len, sizeof(int), 1, fp);
- fwrite(str, sizeof(char), len, fp);
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- int a1;
- double d1;
- char str1[1024];
- fread(&a1, sizeof(int), 1, fp);
- fread(&d1, sizeof(double), 1, fp);
- int len1;
- fread(&len1, sizeof(int), 1, fp);
- fread(str1, sizeof(char), len, fp);
- printf("%d\n%lf\n%s\n", a1, d1, str1);
- fclose(fp);
- fp=null;
- return 0;
- }
4 使用fread()和fwrite()读写文件(续1)
4.1 问题
输入学生信息(学号、姓名、出生日期),然后用结构存储数据,并读写入文件中。
4.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:使用fread()和fwrite()读写文件(续1)
代码如下所示:
- #include
- #include
- struct student
- {
- int id;
- char name[20];
- char address[200];
- };
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- struct student stu = {10000, "zhangsan", "江苏南京"};
- fwrite(&stu, sizeof(struct student), 1, fp);
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- struct student stu1;
- fread(&stu1, sizeof(struct student), 1, fp);
- printf("%d %s %s\n", stu1.id, stu1.name, stu1.address);
- fclose(fp);
- fp=null;
- return 0;
- }
上述代码中,以下代码:
- file*fp=null;
定义一个file类型的指针fp。
上述代码中,以下代码:
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
使用函数fopen用w的方式打开一个文件file.c。
上述代码中,以下代码:
- struct student stu = {10000, "zhangsan", "江苏南京"};
定义一个结构体student的变量stu,并对它进行初始化。
上述代码中,以下代码:
- fwrite(&stu, sizeof(struct student), 1, fp);
使用fwrite函数将结构体student的变量stu写入文件。
上述代码中,以下代码:
- fclose(fp);
- fp=null;
使用函数fclose关闭打开的文件。
上述代码中,以下代码:
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
使用函数fopen用r的方式重新打开文件file.c。
上述代码中,以下代码:
- struct student stu1;
重新定义一个结构体student的变量stu1,但并不对它进行初始化。
上述代码中,以下代码:
- fread(&stu1, sizeof(struct student), 1, fp);
使用fread函数从文件中读入数据放在结构体student的变量stu1中。
上述代码中,以下代码:
- printf("%d %s %s\n", stu1.id, stu1.name, stu1.address);
使用printf函数验证读取的内容是否正确。
上述代码中,以下代码:
- fclose(fp);
- fp=null;
使用函数fclose关闭打开的文件。
4.3 完整代码
本案例的完整代码如下所示:
- #include
- #include
- struct student
- {
- int id;
- char name[20];
- char address[200];
- };
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w");
- if(null==fp)
- {
- return -1;
- }
- struct student stu = {10000, "zhangsan", "江苏南京"};
- fwrite(&stu, sizeof(struct student), 1, fp);
- fclose(fp);
- fp=null;
- fp=fopen("file.c","r");
- if(null==fp)
- {
- return -1;
- }
- struct student stu1;
- fread(&stu1, sizeof(struct student), 1, fp);
- printf("%d %s %s\n", stu1.id, stu1.name, stu1.address);
- fclose(fp);
- fp=null;
- return 0;
- }
5 fseek()的使用
5.1 问题
测试fseek()的效果,包括三个不同的起始位置。
5.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:fseek()的使用
代码如下所示:
- #include
- #include
- int main(void)
- {
- file*fp=null;
- fp=fopen("file.c","w+");
- if(null==fp)
- {
- return -1;
- }
- char buf[] = "abcdefghijklmnopqrstuvwxyz";
- fwrite(buf, sizeof(char), 26, fp);
- fseek(fp, 0, seek_set);
- memset(buf, 0, 26);
- fread(buf, sizeof(char), 10, fp);
- printf("%s\n", buf);
- fseek(fp, 5, seek_cur);
- memset(buf, 0, 26);
- fread(buf, sizeof(char), 10, fp);
- printf("%s\n", buf);
- fseek(fp, -10, seek_end);
- memset(buf, 0, 26);
- fread(buf, sizeof(char), 10, fp);
- printf("%s\n", buf);
- fclose(fp);
- fp=null;
- return 0;
- }
上述代码中,以下代码:
- file*fp=null;
定义一个file类型的指针fp。
上述代码中,以下代码:
- fp=fopen("file.c","w+");
- if(null==fp)
- {
- return -1;
- }
使用函数fopen用w+的方式打开一个文件file.c。
上述代码中,以下代码:
- char buf[] = "abcdefghijklmnopqrstuvwxyz";
定义一个字符数组buf,并初始化为一个字符串。
上述代码中,以下代码:
- fwrite(buf, sizeof(char), 26, fp);
使用fwrite函数将字符串buf写入文件。
上述代码中,以下代码:
- fseek(fp, 0, seek_set);
- memset(buf, 0, 26);
- fread(buf, sizeof(char), 10, fp);
- printf("%s\n", buf);
首先,使用函数fseek设置文件指针fp的位置为文件头开始的第一个字节。该函数有三个参数,说明如下:
第一个参数为目标文件指针。
第二个参数为从第三个参数开始的偏移量,为正数时向后偏移,为负数时向前偏移。
第三个参数为偏移的起始位置。
然后,使用memset函数将字符串buf清空。
下一步,使用fread函数从文件当前设定位置读入10个字符。
最后,使用printf函数验证读入的字符是从文件开头第一个字节开始的10个字符。
上述代码中,以下代码:
- fseek(fp, 5, seek_cur);
- memset(buf, 0, 26);
- fread(buf, sizeof(char), 10, fp);
- printf("%s\n", buf);
首先,使用函数fseek设置文件指针fp的位置为文件当前位置向后偏移5个字节的位置。
然后,使用memset函数将字符串buf清空。
下一步,使用fread函数从文件当前设定位置读入10个字符。
最后,使用printf函数验证读入的字符是从文件当前位置向后偏移5个字节开始的10个字符。
上述代码中,以下代码:
- fseek(fp, -10, seek_end);
- memset(buf, 0
下一篇: XML操作类