一、模块化设计
二、几个小例子
一、模块化设计思想和方法
模块化设计方法:自顶向下设计,自下向上编程实现的设计方法。
学生成绩管理系统,若所有功能都在主函数中实现,程序的可读性、可修改性都很差,因此我们每个功能分别用一个函数来实现,主函数方便快捷的调用这些函数即可(模块化)。
先分析问题——每个问题都是由若干个子问题构成——子问题也可能由若干个小问题构成——细分下去,直至每个小问题独立并且足够小——编程实现每个小问题——将小问题组合(自顶向下设计,自下向上编程实现)
模块化的优点:复用。(1. 函数+函数构成程序。 2. 成熟软构件+修订=新软件。 3. 成熟软构件1+成熟软构件2+…=新软件系统(复用性最佳))
二、几个小例子
例1:以身份证号为参数比较年龄大小。
这是我写的程序:
问题在于:
1. 身份证号不仅仅只有数值,有时候会有字母,因此应用字符数组串表示。
2. scanf_s获取字符串时,应该指明字符串长度,否则可能会出错!
3. 主函数中调用函数,不应该是int 函数名(),而是返回值=函数名()
正确的程序如下:
/* 以身份证号为参数,比较年龄大小 */
#include<stdio.h>
#include<stdlib.h>
#define IDLEN 19 // 定义一个长度:身份证号码长为18,加上结束符共19个
int AgeCompare(char *p1,char *p2); // 函数声明有分号!
int main()
{
char id1[IDLEN],id2[IDLEN]; // 长度为18+1
int r; // 存储函数返回值
printf("请输入两个18位的身份证号:\n");
scanf_s("%s%s",id1,IDLEN,id2,IDLEN);
r=AgeCompare(id1,id2);
printf("比较结果是:%d\n",r);
system("pause");
return 0;
}
int AgeCompare(char *p1,char *p2) // 函数定义没有分号!
{
int y1=0,y2=0,m1=0,m2=0,d1=0,d2=0; // 初始化!提取年、月、日
int i;
// 计算年份
for(i=0;i<4;i++)
{
y1=y1*10+p1[6+i]-'0'; // 把字符串转化为数值,需要减去字符零'0'!!!
y2=y2*10+p2[6+i]-'0'; // 使用前在等号右面使用了,因此使用前必须初始化!
}
// 计算月份
for(i=0;i<2;i++)
{
m1=m1*10+p1[10+i]-'0';
m2=m2*10+p2[10+i]-'0';
}
// 计算天数
for(i=0;i<2;i++)
{
d1=d1*10+p1[12+i]-'0';
d2=d2*10+p2[12+i]-'0';
}
// 比较大小
if(y1!=y2)
{
if(y1>y2)
return 1;
else
return -1;
}
else
{
if(m1>m2)
return 1;
else if(m1<m2)
return -1;
else
{
if(d1>d2)
return 1;
else if(d1<d2)
return -1;
else
return 0;
}
}
}
下述错误原因:没有定义函数就调用。
进行调试时的技巧:
1. 加断点:看输入函数之前的数据是否正确;看参数传递是否正确;看函数输出数据是否正确。(因此断点加三处:进入函数前,进入函数后第一行,从函数中出来)
2. 用监视:看参数传递是否正确;看获取数据是否正确;看指针是否正确;看返回值是否正确。(监视加几处:y, m, d, id, p, r)
测试时的技巧:
为避免反复输入数据可能会造成错误,我们将scanf_s注释掉,直接输入数据,测试完成再取消注释。