Discuz教程网

C语言案例教程 - 第七章 程序的模块结构和C函数

[复制链接]
authicon 09927306 发表于 2011-1-8 18:01:07 | 显示全部楼层 |阅读模式
本帖最后由 09927306 于 2011-1-8 18:34 编辑

第7章:程序的模块结构和C函数

【例7-1】
计算组合的公式为:
这里需要求出3个阶乘,于是我们可以编制一个通用的阶乘函数factor(),通过使用不同的参数调用实现一个函数被多次使用的目的。程序如下:


  1. main()
  2.           { int m,n;
  3.             long cmn,temp;
  4.             long factor(int);          /* 被调用的函数类型说明 */
  5.             void print();              /* 被调用的函数类型说明 */
  6.             printf("Input m and n:");
  7.             scanf("%d%d",&m,&n);
  8.             cmn=factor(m);             /* 函数名调用,计算m! */
  9.             temp=factor(n);            /* 函数名调用,计算n! */
  10.             cmn=cmn/temp;              /* 函数名调用,计算m!/n! */
  11.             cmn=cmn/factor(m-n);  /* 函数名调用,计算m!/n!/(m-n)! */
  12.             print(cmn);                /* 函数名调用,打印结果 */
  13.           }

  14.         long factor(int x)             /* 定义阶乘函数 */
  15.           { long y;
  16.             for(y=1;x>0;x--)
  17.               y=y*x;
  18.             return (y);
  19.           }
  20.   
  21.         void print(long x)             /* 定义打印函数 */
  22.           { printf("The combinations:%d\\n",x);
  23.           }
复制代码


main()函数接收了m和n的值后,要通过3次调用factor()函数来分别求得m!、n!和(m-n)!,最后调用print()函数输出结果。
【例7-2】
考察下面的程序,mian()函数能否通过调用函数swap()用来实现变量x和y的交换。


  1. main()
  2.           { int x,y,swap(int a,int b);
  3.             scanf("%d,%d",&x,&y);
  4.             printf("output in main before calling swap:x=%d,y=%d\\n",x,y);
  5.             swap(x,y);               /* 函数调用 */
  6.             printf("output in main after calling swap:x=%d,y=%d\\n",x,y);
  7.           }

  8.         swap(int a,int b)
  9.           { int t;
  10.             t=a,a=b,b=t;             /* 变量交换 */
  11.             printf("output in swap:a=%d,b=%d\\n",a,b);
  12.           }
复制代码

函数swap()的功能是实现a、b的交换。当main()调用swap()时,通过虚实结合将实参x、y的值复制到swap()的形参a、b中,使a和b所在的存储单元中分别得到了x和y的值。在swap()执行时,由于a、b、x、y各自占有自己的存储单元,当a、b的值发生了交换后,不会被复制到x和y中,因此,x和y不受a和b的影响,并未发生交换,参见图7-3。程序的运行情况如下:


1234
5678↙

output in main before calling swap:x=1234,y=5678

output in swap:a=5678,b=1234

output in main after calling swap:x=1234,y=5678
【例7-3】
考察下面的程序,mian()函数能否通过调用函数swap()用来实现变量x和y的交换。


  1. main()
  2.           { int x,y,swap(int *,int *);
  3.             scanf("%d%d",&x,&y);
  4.             printf("output in main before calling swap:x=%d,y=%d\\n",x,y);
  5.             swap(&x,&y);
  6.             printf("output in main after calling swap:x=%d,y=%d\\n",x,y);
  7.           }

  8.         swap(int *a,int *b)
  9.           { int t;
  10.             t=*a,*a=*b,*b=t;         /* 指针所指的存储单元的内容交换 */
  11.             printf("output in swap:a=%d,b=%d\\n",*a,*b);
  12.           }
复制代码

当main()调用swap()时,实参变量x和y的地址被复制到形参a和b(a和b是指针变量)中,使a和b分别指向x和y。在swap()执行时,由于*a和x等价,*b和y等价,*a和*b的交换实际上是在x和y的存储单元中进行的,所以,*a和*b的交换实际就是变量x和y的交换
【例7-4】
调用函数通过指针传递不仅可以将数据传递到被调用函数中,还能从被调用函数获得所需要的数据。下面的程序将2个加数传递给被调用函数,并从被调用函数获得两数之和。


  1. main()
  2.           { float a,b,c,*pa=&a,*pb=&b;
  3.             void plus(float *,float *,float *);
  4.             printf("Input a and b:");
  5.             scanf("%f%f",pa,pb);
  6.             plus(pa,pb,&c);
  7.             printf("%.1f+%.1f=%.1f\\n",a,b,c);
  8.           }

  9.         void plus(float *x,float *y,float *z)
  10.           {
  11.             *z=*x+*y;
  12.           }
复制代码


程序执行时,main()将变量a、b的指针pa、pb及变量c的地址&c分别复制到plus()的形参x、y和z中,因此*x和*y分别表示取a和b值,二者相加后的结果保存在*z中,而*z与c是等价的,即c中存放的是a+b的值。程序运行情况如下:

20 30↙

20.0+30.0=50.0
【例7-5】
编制子函数mean()用来求虚拟一维数组各元素的平均值。主函数main()中提供一维数组的数据,并调用mean()获得实际数组的平均值。
主函数用数组名作为实参,子函数用数组名作为形参。程序如下:


  1. main()
  2.           { int i,a[10];
  3.             float mean(int *),mv;
  4.             for (i=0;i<10;i++)
  5.               scanf("%d",&a[i]);
  6.             mv=mean(a);
  7.             printf("MEAN=%f\\n",mv);
  8.           }

  9.         float mean(int d[10])          /* 计算平均值 */
  10.           { int i;
  11.             float avg;
  12.             for (avg=0,i=0;i<10;i++)
  13.               avg+=d[i];
  14.             avg/=10;
  15.             return avg;
  16.           }
复制代码


函数mean()的形参虽然被说明为int d[10],但在虚实结合时,数组名d被转换成数组指针*d并接收实参数组a的首地址。由于d变成了指向数组a的指针,因此,虚参数组d[10]并没有自己的存储单元,而是共享实参数组a的存储单元,见图7-5所示。


    a[0]    a[1]      a[2]       a[3]     a[4]      a[5]     a[6]     a[7]      a[8]     a[9]










   d[0]    d[1]      d[2]      d[3]    d[4]       d[5]     d[6]     d[7]     d[8]     d[9]
图7-5
一维数组传递时,形参和实参的共享
② 由于形参数组在虚实结合时被转换成数组指针,因此形参数组的说明中,维界的大小无关紧要,通常都写成隐含尺寸数组或指针的形式。即在例7-5中,被调用函数mean()可以定义成以下形式之一:

float mean(int d[10])
其中,维界的大小无关紧要

float mean(int d[])
float mean(int *d)


上一章:C语言案例教程 - 第六章:指 针
下一章:C语言案例教程 - 第八章 复合数据类型






上一篇:2011杭电软件工程 考试相关图片
下一篇:C语言案例教程 - 第八章 复合数据类型
authicon  楼主| 09927306 发表于 2011-1-8 18:01:37 | 显示全部楼层
本帖最后由 09927306 于 2011-1-8 18:30 编辑

【例7-6】
编制子函数sort()将一个虚拟数组按降序排序,主函数提供一维数组a的数据,并调用该子函数sort()只将实参数组a的前5个元素排序。
因为要求子函数能按指定数量的数组元素排序,在定义该函数时就要提供2个形参,一个用来接收实参数组的首地址;另一个用来接收要排序的元素个数。程序如下:


  1. main()
  2.           { static int a[10]={2,8,7,5,9,12,10,3,1,6};
  3.             int i;
  4.             for (i=0;i<10;i++)
  5.               printf("%d ",a[i]);
  6.             printf("\n");
  7.             sort(a,5);
  8.             for (i=0;i<10;i++)
  9.               printf("%d ",a[i])
  10.             printf("\n");
  11.          

  12.         void sort(int b[],int n) /* 对指定数组中前n个元素排序 */
  13.           { int i,j,t;
  14.             for (i=0;i<n-1;i++)
  15.               for (j=i+1;j<n;j++)
  16.                 if (b[i]<b[j])
  17.                   { t=b[i],b[i]=b[j],b[j]=t;}
  18.           }
复制代码


在进行虚实结合时,形参数组b是隐含尺寸数组。和上例一样,b和实参数组a共享存储单元。函数sort()采用选择法对数组中的前n个元素按从大到小的顺序排序
【例7-7】
编制程序求二维数组中的最大元素。
主函数中定义一个二维数组a[3][4]及指向它的行指针(*p)[4],用行指针调用子函数sort()。在sort()中,用array[3][4]作为形参以接收主函数传递过来的实参数组首地址。程序如下:


  1. main()
  2.          { static int a[3][4],(*p)[4]=a;
  3.            int i,j,amax,max_value();
  4.            for (i=0;i<3;i++)
  5.              for (j=0;j<4;j++)
  6.                scanf("%d",*(p+i)+j);
  7.            amax=max_value(p);
  8.            printf("MAX=%d\n",amax);
  9.          }

  10.       max_value(int array[3][4]) /* 求二维数组各元素中的最大值 */
  11.          { int i,j,max;
  12.            max=array[0][0];
  13.            for (i=0;i<3;i++)
  14.              for (j=0;j<4;j++)
  15.                if (max<array[i][j])
  16.                   max=array[i][j];
  17.            return (max);
  18.          }
复制代码


【例7-8】
编制程序将给定的10个字符串中的字母转换成大写。
子函数Upper()用来将传送过来的各字符串中的所有字母全部转换成大写(其中用到标准函数库中的toupper(),它的功能是将指定的字母转换成大写字母。该函数定义在标题文件ctype.h中),main()中定义了一个二维字符型数组存放10个字符串,并定义了指向该数组的指针数组st[10],通过该指针数将10个字符串整体传递给Upper函数中的形参(也是字符型指针数组),由Upper函数对其进行转换处理。程序如下:


  1. #include <ctype.h>
  2.         void Upper(char *str[]);
  3.         main()
  4.           { char s[10][80],*st[10];
  5.             int i;
  6.             for(i=0;i<10;i++)
  7.               st[i]=s[i];
  8.             for(i=0;i<10;i++)
  9.               gets(st[i]);
  10.             Upper(st);
  11.             printf("original string has been altered:\n");
  12.             for(i=0;i<10;i++)
  13.               puts(st[i]);
  14.           }

  15.         void Upper(char *str[10])
  16.           { int i,j;
  17.             for(i=0;i<10;i++)
  18.               for(j=0;str[i][j];j++)
  19.             str[i][j]=toupper(str[i][j]);/* 将指定字符转换成大写 */
  20.           }
复制代码


【例7-9】
编制一个子函数abs()求任意一个整数的绝对值,在主函数中用函数指针的方式调用该子函数。


  1. int abs(int x)  /* 求绝对值 */
  2.           { if (x>=0)
  3.               return (x);
  4.             else
  5.               return (-x);
  6.           }
  7.         main()
  8.           { int a,b,(*f)()=abs; /*定义函数指针*/
  9.             scanf("%d",&a);
  10.             b=f(a);      /* 函数指针调用,也可以用b=(*f)(a); */
  11.             printf("absolution value of %d is %d\n",a,b);
  12.           }
复制代码


【例7-10】
通过函数指针嵌套调用函数示例。


  1. funa(int a, int b)
  2.       { return a+b; }

  3.     funb(int a, int b)
  4.       { return a*b; }

  5.     sub(int (*p)(), int a, int b)
  6.      { return (*p)(a,b); }

  7.     main()
  8.       { int x,y,z,(*p1)()=funa;
  9.         scanf("%d%d",&x,&y);
  10.         z=sub(p1,x,y)+sub(funb,x,y);
  11.         printf("%d\n",z);
  12.       }
复制代码


【例7-11】
不使用strcpy()函数,自行编制函数char *fun(),其功能是从调用函数接收2个字符串,然后将第二个字符串连接到第一个字符串的末尾。
函数char *fun()用两个字符型指针接受来自调用函数的字符串,先通过空while循环将指针p1移到第一个字符串的末尾,再通过第二个while循环将第二个字符串连接到第一个字符串的末尾,最后通过字符型指针f将连接后的字符串的首地址返回。程序如下:


  1.     #include <stdio.h>
  2.     char *fun(char *p1, char *p2)
  3.       { char *f=p1;
  4.         while(*p1++);
  5.         p1--;                      /*移动到字符串p1的末尾*/
  6.         while(*p1++=*p2++);    /*将字符串p2追加到p1的末尾*/
  7.         *p1='\0';
  8.         return f;
  9.       }

  10.     main()
  11.           { char s1[80],s2[80],*p;
  12.             gets(s1);
  13.             gets(s2);
  14.             p=fun(s1,s2);
  15.             puts(p);
  16.           }
复制代码


【例7-12】
编制求n!的递归调用程序。
根据n!的递归定义:

1
(n=0或n=1)

n!=
n×(n–1)!
(n>1)
很容易编写出如下递归函数和主程序:


  1. long factor(int n)
  2.           { if (n==0||n=1)
  3.               return (1);
  4.             else
  5.               return (n*factor(n-1));
  6.           }

  7.         main()
  8.           { int x;
  9.             long factor();
  10.             scanf("%d",&x);
  11.             printf("%d!=%ld\n",i,factor(i)); /* %ld用于long型数的输出 */
  12.           }
复制代码


【例7-13】
用递归的方法将输入的任意十进制整数按相反的顺序把各位数字打印出来。设计思路如下。
① 如果一个整数n只有1位,就可以将它直接打印出来。要确定这个整数只有1位,只要满足n/10=0的条件,这就是基始条件。
② 对超过1位的整数,可以先取出它的最低位,方法是用n=n%10实现。在取出最低位的同时,用n=n/10来降低该数的位数。于是,就可以容易地编写出递归程序prind():


  1.   #include <stdio.h>
  2.         void prind(long n)
  3.          {  if (n<0)
  4.              { n=-n;putchar('-'); }    /*处理负数*/
  5.             putchar(n%10+'0');         /*输出最低位*/
  6.             if ((n/=10)!=0)
  7.               prind(n);                /*递归调用*/
  8.          }
复制代码


【例7-14】
编一个名为slink的程序,其功能是将若干个指定的字符串连接成一个字符串。要求将文件名及各要连接的字符串作为命令行参数。


  1. #include <string.h>
  2.         main(int argc,char *argv[])
  3.           { int i;
  4.             for (i=1;i<argc-1;i++)
  5.             strcat(argv[1],argv[i+1]);
  6.             printf("%s\n",argv[1]);
  7.           }
复制代码


将上面的程序以slink.c为文件名,编译后将生成可执行文件slink.exe。当用命令行的形式运行该程序时,首先要进入DOS操作系统(在Turbo C环境中用Alt+FO可进入DOS命令状态)在DOS操作系统提示符“C>”下,键入如下命令行:

C>slink abcd efgh ijklm↙
【例7-15】
修改例7-14程序,当用户输入的命令行参数个数少于2时,屏幕显示“未送入要连接的字符串”,并返回操作系统;否则,将命令行中的各个参数(文件名除外)连接成一个字符串并显示出来。
若用户输入的命令行参数不足,main()的返回值为–1;若正确输入,则返回0。程序如下:


  1. #include <string.h>
  2.         main(int argc,char *argv[])
  3.           { int i;
  4.             if (argc<2)
  5.               { printf("未送入要连接的字符串\n");
  6.                 return -1; }
  7.             for (i=1;i<argc-1;i++)
  8.               strcat(argv[1],argv[i+1]);
  9.             printf("%s\n",argv[1]);
  10.             return 0;
  11.           }
复制代码


authicon 苦笑这年华 发表于 2012-5-31 20:32:44 | 显示全部楼层
这个还不错,好帖子,大家谈谈












长沙十佳摄影工作室
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-2 10:57

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表