getchar 可以防止闪退 但是有时候会失效
原因是因为输入时候“缓冲区”没有清除的原因 可以在
前面加上
fflush(stdin);
重回helloworld
上编译链接过程中 手动生成了exe文件程序
那么其中的
# include"stdio.h"
其实他的作用就是
- 找到stdio.h文件
- 粘贴复制过来
工程上的模块化
判断用户输入的数字是偶数还是奇数
- UI
- 算法
- 业务逻辑
C语言是面向过程的语言,面向过程就是使用使用函数,将程序模块化
所谓高内聚低耦合就是出于此
可以将代码划分,各司其事
#include <stdio.h>
int UI_ShowMsgGetNumber()
{
int nNumber = 0;
printf("请输入一个数字\n");
scanf("%d", &nNumber);
return nNumber;
}
void UI_ShowResult(int nIsEven)
{
if(nIsEven == 1)
{
printf("Even Number\n");
}
else
{
printf("Odd Number\n");
}
}
int Math_IsEvenNumber(int nNumber)
{
if(nNumber % 2 == 0)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int number = UI_ShowMsgGetNumber();
int result = Math_IsEvenNumber(number);
UI_ShowResult(result);
return 0;
}
可以把上面分模块
- main.c
- UI_Show.c
- Math.c
操作流程 是
/c main.c
cl /c UI_Show.c
cl /c Math.c
分别得到三个obj,接着使用连接器将3个obj拼接为exe文件
link main.obj Math.obj UI_Show.boj
可以得到exe,功能与之前一样
但是进行了文件的划分
- 函数与函数直接,单纯又简单的依靠函数接口进行交互
- 当工程中的多个.c文件中的某一个.c文件发生了改动之后,不需要重新编译所有.c
文件,而只需要重新编译发生改动的那个.c文件,得到新的obj,然后再重新链
接。
头文件和c文件的划分
以上的代码中,还有一点弊端,就是我们在使用自定义函数时,并没有写函数声明,
而直接使用,这其实是非常危险的,甚至在一些老编译器上,是编译不通过的。正确
做法应该是:将函数声明写在函数调用之前,使得编译器,可以根据你的函数声明,
来检查你调用函数的方式是否正确:修改后的main.c
int UI_ShowMsgGetNumber();
void UI_ShowResult(int nIsEven);
int Math_IsEvenNumber(int nNumber);
int main()
{
int number = UI_ShowMsgGetNumber();
int result = Math_IsEvenNumber(number);
UI_ShowResult(result);
return 0;
}
不过,在实际工作中,我们还剩下最后一个问题没有解决:那就是,按照常理,函数
的接口(也就是函数声明),其提供方应该是功能实现者本人,比如以下的例子,那
几个函数(UI_ShowMsgGetNumber等),它们的声明,应该是ui.c的作者提供,而
不应该是main.c的作者自己写。
我们如何解决这个矛盾呢?答案是:头文件。
事实上,一般而言,.c文件的作者应该配套地提供函数接口的头文件,这样,其它.c文
件的作者,可以直接通过包含头文件,来获取对应的函数接口。
所以,我们的项目接口最终,变成了以下的情况:
- 美工提供: ui.h ui.c
- 算法提供:mymath.h mymath.c
- 项目经理: main.c 并且在其中包含ui.h和mymath.h
其实每个模块的作者,只需要提供自身的obj文件及对应
的头文件即可。