首页 > 代码库 > 20170417-2

20170417-2

函数:

    在大规模的程序中需要对语句进行分组管理,把相互之间联系比较紧密的语句合并成一个分组。分组可以在多个不同层次上进行,最低一级的结果叫函数。任何函数一定包含多条语句。任何c语言程序都是由一个或多个函数构成的,绝大多数语句必须属于一个函数,在c语言中任何函数的名字都是唯一的。
 
 练习:编写一个多函数程序,用一个函数从键盘得到一个数字,主函数要拿到
 这个数字并打印在屏幕上。
  1 #include <stdio.h>
  2
  3 int getNumber() {
  4     int i;
  5     scanf("%d", &i);
  6     return i;
  7 }
  8 int main() {
  9     printf("%d\n", getNumber());
 10     return 0;
 11 }
exit标准函数可以立刻结束整个程序执行,需要包含文件stdlib.h。

练习:
1. 编写程序在屏幕上打印如下内容
1 X 9 = 9
2 X 8 = 16
...
5 X 5 = 25(每一行使用一个函数调用语句实现打印)
 1 #include <stdio.h>
  2 int getPrint() {
  3     int i = 0, j = 0;
  4     for(i = 1; i <= 5; i++) {
  5         printf("%d X %d = %d\n", i, 10 - i, i*(10-i));
  6     }
  7     return 0;
  8 }
  9 int main() {
 10     getPrint();
 11     return 0;
 12 }
2.编写函数判断某个给定数字是不是素数
  1 #include <stdio.h>
  2 int charge(int a) {
  3     int i = 0;
  4     for(i = 2; i <= a-1; i++) {
  5         if(a % i == 0) {
  6             return 1;
  7         }
  8     }
  9     return 0;
 10 }
 11 int main() {
 12     int a;
 13     scanf("%d", &a);
 14     a = charge(a);
 15     if(a == 1) {
 16         printf("不是素数");
 17     }
 18     else {
 19         printf("是素数");
 20     }
 21     return 0;
 22 }
 
 数组做函数的形参可以传递存储位置而不仅仅传递数据。
 函数对数组形参所做的修改会影响调用函数。
 
练习:编程一个函数把一个数组里的所有数字变成它的相反数。
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 void  setUnm(int a[]) {
  4     int i = 0;
  5     for(i = 0; i <= 4; i++) {
  6         a[i] = 0 - a[i];
  7         printf("%d ", a[i]);
  8     }
  9 }
 10 int main() {
 11     int a[5] = {0}, i = 0;
 12     for(i = 0; i <= 4; i++) {
 13         scanf("%d", &a[i]);
 14     }
 15     setUnm(a);
 16     return 0;
 17 }

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 void  setUnm(int a[], int size) {
  4     int num = 0;
  5     for(num = 0; num <= size - 1; num++) {
  6         a[num] = 0 - a[num];
  7     }
  8 }
  9 void setPrint(int a[], int size) {
 10     int num = 0;
 11     for(num = 0; num <= size; num++) {
 12         printf("%d ", a[num]);
 13     }
 14 }
 15 int main() {
 16     int a[7] = {1, -6, 34, 27, -8, -10, 99};
 17     setUnm(a, 5);
 18     setPrint(a, 6);
 19     return 0;
 20 }
 gcc在编译时如果先处理函数调用语句则会采用函数隐式声明猜测一个函数格式,
 隐式声明格式如下:
 int add();
 这表示函数的返回值是整数类型,函数可以接受任意数量任意类型的参数。
 不应该依赖函数的隐式声明,因为他有可能会错。
 显示函数声明: double add(double, double);
 把函数声明单独写成一条语句时可以省略参数的名称。
 
文件操作的相关标准函数
1. fopen标准函数用来打开一个文件
2. fclose标准函数用来关闭文件
3. fread/fwrite标准函数用来向文件中写数据或从文件中读数据

文本文件中记录的都是字符,可以给人看。
二进制文件中记录的是数据在内存中的二进制内容,给机器用的。
  1 #include <stdio.h>
  2 int main() {
  3     FILE *p_file = fopen("a", "w");//a当前目录下一个叫a的文件
  4     if(p_file) {
  5         //...
  6
  7         fclose(p_file);
  8         p_file = NULL;
  9     }
 10     return 0;
 11 }
fopen("a", "w");
第二个参数表示文件打开模式:
"r"    :只能读文件内容,读操作从文件头开始,文件必须事先已经存在
"r+"   :在前一个模式的基础上增加修改能力
"w"    :只能修改文件内容,修改操作从文件头开始,如果文件事先不存在,则新创建文件,
如果文件事先已经存在,则删除文件中原有内容。
"w+"   :在前一个模式的基础上增加读能力。
"a"    :只能修改文件内容,如果文件事先不存在,则创建新文件,
如果文件事先已经存在,则在源文件内容后面追加新内容。
"b" 也是一种打开模式,这个模式可以和前面的任何模式混合使用。
"b"模式表示以二进制方式对文件进行操作。
fopen标准函数在返回值变量中记录一个数字,这个数字可以用来代表被打开的文件
fopen标准函数有可能失败,如果失败则返回值变量中记录的数字作为布尔值使用时是假
每当结束对一个文件的所有操作后都必须使用fclose标准函数关闭这个文件
fread/fwrite参数
1.数组(fread会把从文件中得到的内容放在数组的存储位置中fwrite会把数组中
存储位置中的内容写入到文件中)
2.数组中单个存储位置的大小
3.希望使用的存储位置的个数
4.要操作的文件
返回值表示实际使用的存储位置的个数

      FILE *p_file = fopen("a", "wb");
      if(p_file) {
      size = fwrite(arr, sizeof(int), 4, p_file);
         fclose(p_file);
         p_file = NULL;
     }

练习:
1  2  3  4  5
6  7  8  9  10
。。。
21 22 23 24 25 1.存放到二维数组,然后写入到文件中
               2.从文件中读取,放入一个二维数组
               读出的数据
               21 22 23 24 25
               。。。
               1  2  3  4  5
  1 #include <stdio.h>
  2 int main() {
  3     int arr[5][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15},{    16, 17, 18, 19, 20},{21, 22, 23, 24, 25}};
  4     int size = 0;
  5
  6     FILE *p_file = fopen("a", "wb");
  7     if(p_file) {
  8         for(size = 0; size <= 4; size++) {
  9             fwrite(arr[size], sizeof(int), 5, p_file);
 10         }
 11         fclose(p_file);
 12         p_file = NULL;
 13     }
 14     return 0;
 15 }

               
  1 #include <stdio.h>
  2 int main() {
  3     int arr[5][5] = {0};
  4     int size = 0, i = 0, j = 0;
  5     FILE *p_file = fopen("a", "rb");
  6     if(p_file) {
  7         for(i = 4; i >= 0; i--) {
  8             fread(arr[i], sizeof(int), 5, p_file);
  9         }
 10         for(i = 0; i <= 4; i++) {
 11             for(j = 0; j <= 4; j++) {
 12                 printf("%2d ", arr[i][j]);
 13             }
 14             printf("\n");
 15         }
 16         printf("\n");
 17         fclose(p_file);
 18         p_file = NULL;
 19     }
 20     return 0;
 21 }      

练习:编写人员信息管理系统
每个人员信息包含三部分(id,姓名和工资)(int, char[20], float)
从键盘得到多个人员信息,并记录到文件中(多次运行程序,文件中人员信息越来越多,可以出现重复id
,每次得到一个人员信息后提问是否还需要输入下一个人员信息)
可以使用scanf从键盘得到多个字符数据并记录在字符数组中(应该使用%s作为占位符)
姓名中不应该出现空格,不能有中文,长度不能超过20个字符。和%s配对的数据是数组名称。
  1 #include <stdio.h>
  2 int main() {
  3     int id = 0;
  4     char name[20] = {};
  5     float salary = 0.0f;
  6     FILE *p_file = fopen("a.bin", "ab");
  7     int flag = 0;
  8     if(p_file) {
  9         do {
 10             printf("请输入id:");
 11             scanf("%d", &id);
 12             printf("请输入姓名:");
 13             scanf("%s", name);
 14             printf("请输入工资:");
 15             scanf("%f", &salary);
 16             fwrite(&id, sizeof(int), 1, p_file);
 17             fwrite(name, sizeof(char), 20, p_file);
 18             fwrite(&salary, sizeof(float), 1, p_file);
 19             printf("是否需要输入下一个?");
 20             scanf("%d", &flag);
 21         } while(flag);
 22         fclose(p_file);
 23         p_file = NULL;
 24     }
 25     return 0;
 26 }
练习:1.编写函数把一个数组中所有存储位置的内容从前到后颠倒顺序
  1 #include <stdio.h>
  2 void reverse(int arr[], int n);
  3 int main() {
  4     int i = 0;
  5     int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
  6     reverse(arr, 10);
  7     for(i = 0; i <= 9; i++) {
  8         printf("%d ", arr[i]);
  9     }
 10     printf("\n");
 11     return 0;
 12 }
 13
 14 void reverse(int arr[], int n) {
 15     int i = 0, temp = 0;
 16     for(i = 0; i <= n/2 - 1; i++) {
 17         temp = arr[i];
 18         arr[i] = arr[n - i - 1];
 19         arr[n - i - 1] = temp;
 20     }
 21 }

      2.编写函数交换主函数中两个变量的内容
  1 #include <stdio.h>
  2 void swap(int arr[], int brr[]) {
  3     int temp = arr[0];
  4     arr[0] = brr[0];
  5     brr[0] = temp;
  6 }
  7 int main() {
  8     int a = 3, b = 7;
  9     swap(&a, &b);
 10     printf("%d, %d\n", a, b);
 11     return 0;
 12 }

      3.编写程序把b.out文件复制一份并命名为c.out
  1 #include <stdio.h>
  2 int main() {
  3     int size = 0;
  4     char buf[100] = {};//每次从b中读取100字节先放到buf然后放到c
  5     FILE *p_src = http://www.mamicode.com/fopen("b.out", "rb");
  6     if(!p_src) {
  7         return 0;
  8     }
  9     FILE *p_dest = fopen("c.out", "wb");
 10     if(!p_dest) {
 11         fclose(p_src);
 12         p_src = http://www.mamicode.com/NULL;
 13         return 0;
 14     }
 15     while(size = fread(buf, sizeof(char), 100, p_src)) {
 16         fwrite(buf, sizeof(char), size, p_dest);
 17     }
 18     fclose(p_dest);
 19     p_dest = NULL;
 20     fclose(p_src);
 21     p_src = http://www.mamicode.com/NULL;
 22     return 0;
 23 }

      4.把生成的人员信息文件中的所有内容打印在屏幕上
  1 #include <stdio.h>
  2 int main() {
  3     int id = 0;
  4     char name[20] = {};
  5     float salary = 0.0f;
  6     FILE *p_file = fopen("a.bin", "rb");
  7     if(p_file) {
  8         while(fread(&id, sizeof(int), 1, p_file)) {
  9             fread(name, sizeof(char), 20, p_file);
 10             fread(&salary, sizeof(float), 1, p_file);
 11             printf("%d %s %g\n", id, name, salary);
 12         }
 13         fclose(p_file);
 14         p_file = NULL;
 15     }
 16     return 0;
 17 }
自己调用自己的函数叫做递归函数
递归函数会在计算机里同时存在多个,其中最后一个是当前正在工作的那个。

递归函数编写原则
1.首先要在递归函数中编写语句描述问题的拆分方式
2.在递归函数的开始编写分支解决不再拆分的情况(这种情况必须保证函数可以结束)
练习:从1开始到用户给定数字之间所有整数之和
  1 #include <stdio.h>
  2
  3 int sum(int num) {
  4     if(num == 1) {
  5         return 1;
  6     }
  7     return num + sum(num - 1);
  8 }
  9
 10 int main() {
 11     int i = 0;
 12     printf("请输入给定数字:");
 13     scanf("%d", &i);
 14     i = sum(i);
 15     printf("%d\n", i);
 16     return 0;
 17 }

 
 菲式数列
  1 /*
  2     菲式数列
  3  */
  4 #include <stdio.h>
  5
  6 int f(int num) {
  7     if(num <= 1) {
  8         return 1;
  9     }
 10     return  f(num-1) + f(num-2);
 11 }
 12
 13 int main() {
 14     int num = 0;
 15     printf("请用户输入一个编号:");
 16     scanf("%d", &num);
 17     printf("编号为%d的数字是%d\n", num, f(num));
 18     return 0;
 19 }计算速度慢,因为如果算40的,要算 38,39的,38的要算37,36, 39要算37,38
 有重复计算的。

20170417-2