重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
项目8的实现,main函数太臃肿,不便于阅读和维护。
目前创新互联建站已为超过千家的企业提供了网站建设、域名、雅安服务器托管、网站托管、服务器租用、企业网站设计、蕉城网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
用函数来优化。
#include
#include
#include
FILE *file;
void init(void) {
//打开文件
file = fopen("users.txt", "r");
if (!file) { //等效于 file == NULL
printf("文件打开失败");
//return 1;
exit(1);
}
}
void login(void) {
char name[32];
char password[16];
char line[128];
char name_tmp[32];
char password_tmp[16];
char *ret;
//输入用户名和密码
while (1) {
system("cls");
// 输入用户名和密码
printf("请输入用户名:");
scanf("%s", name);
printf("请输入密码:");
scanf("%s", password);
//从文件中读取账号,并进行判断!
while (1) {
//读一行
ret = fgets(line, sizeof(line), file); //line: "admin 123456\n"
if (!ret) {
break;
}
sscanf(line, "%s %s", name_tmp, password_tmp);
if (!strcmp(name, name_tmp) && !strcmp(password, password_tmp)) {
break;
}
}
if (ret) { //用户名和密码匹配成功
break;
} else {
printf("用户名或密码错误!\n");
system("pause");
system("cls");
fseek(file, 0, SEEK_SET); //把文件内部的位置指针设置到文件头
}
}
}
void create_user(void) {
system("cls");
printf("\n\n---创建账号---\n\n");
printf("待实现...\n\n");
printf("\n\n按任意键返回主菜单");
fflush(stdin);
getchar();
}
void ip_admin(void) {
system("cls");
printf("\n\n---IP管理---\n\n");
printf("待实现...\n\n");
printf("\n\n按任意键返回主菜单");
fflush(stdin);
getchar();
}
void logout(void) {
system("cls");
fclose(file);
exit(0);
}
void input_error(void) {
system("cls");
printf("\n\n输入错误!\n\n");
printf("\n\n按任意键后,请重新输入\n\n");
fflush(stdin);
getchar();
}
void show_memu(void) {
system("cls");
// 打印功能菜单
printf("---交换机后台管理---\n");
printf("1. 创建账号\n");
printf("2. IP管理\n");
printf("3. 退出\n");
printf("请选择: ");
}
int main(void) {
char n; //用户选择的菜单编号
init(); //初始化
login(); //登录
while (1) {
show_memu();
fflush(stdin);
scanf("%c", &n);
switch (n) {
case '1':
create_user();
break;
case '2':
ip_admin();
break;
case '3':
logout();
break;
default:
input_error();
break;
}
}
return 0;
}
已经有main函数,为什么还要自定义函数?
1)“避免重复制造轮子”,提高开发效率
2)便于维护
函数的设计方法:
1)先确定函数的功能
2)确定函数的参数
是否需要参数,参数的个数,参数的类型
3)确定函数的返回值
是否需要返回值,返回值的类型
函数的声明
函数的使用
调用函数时,形参被赋值为对应的实参,
实参本身不会受到函数的影响!
要避免栈空间溢出。
当调用一个函数时,就会在栈空间,为这个函数,分配一块内存区域,
这块内存区域,专门给这个函数使用。
这块内存区域,就叫做“栈帧”。
demo1
#include
#include
void test(void) {
//运行时将因为栈帧空间溢出,而崩溃
char buff[1024*1024*2];
memset(buff, 0, sizeof(buff));
}
int main(void) {
test();
return 0;
}
demo2
#include
#include
void test(int n) {
char buff[1024*256];
memset(buff, 0, sizeof(buff));
if (n==0) {
return;
}
printf("n=%d\n", n);
test(n-1);
}
int main(void) {
//test(5);
//因为每个栈帧有256K以上, 10个栈帧超出范围
test(10);
return 0;
}
定义:在函数的内部,直接或者间接的调用自己。
要点:
再定义递归函数时,一定要确定一个“结束条件”!!!
使用场合:
处理一些特别复杂的问题,难以直接解决。
但是,可以有办法把这个问题变得更简单(转换成一个更简单的问题)。
盗梦空间
例如:
1)迷宫问题
2)汉诺塔问题
斐波那契数列
1,1, 2, 3, 5, 8, 13, 21, ....
计算第n个数是多少?
f(n)
当n >2时,f(n) = f(n-1) + f(n-2)
当n=1或n=2时, f(n)就是1
int fib(int n) {
int s;
if (n == 1|| n == 2) {
return 1;
}
s = fib(n-1) + fib(n-2);
return s;
}
递归函数的缺点:
性能很低!!!
独立完成项目9
定义一个函数,实现1+2+3+...+n
#include
int sum(int n) {
int i;
int s = 0;
for (i=1; i<=n; i++) {
s += i;
}
return s;
}
int main(void) {
int value;
printf("请输入一个整数: ");
scanf("%d", &value);
if (value < 0) {
printf("需要大于0\n");
return 1;
}
printf("%d\n", sum(value));
return 0;
}
打印指定类型的金字塔,用自定义函数实现。
效果如下:
代码:
#include
void show(char c, int n) {
int i;
int j;
for (i=1; i<=n; i++) {
for (j=0; j
#include
int sum(int n) {
int s;
if (n == 1) {
return 1;
}
s = n + sum(n-1);
return s;
}
int main(void) {
int value;
printf("请输入一个整数: ");
scanf("%d", &value);
if (value < 0) {
printf("需要大于0\n");
return 1;
}
printf("%d\n", sum(value));
return 0;
}
#include
void hanoi(int n, char pillar_start[], char pillar_mid[], char pillar_end[]) {
if (n == 1) {
printf("从%s移动到%s\n", pillar_start, pillar_end);
return;
}
hanoi(n-1, pillar_start, pillar_end, pillar_mid);
printf("从%s移动到%s\n", pillar_start, pillar_end);
hanoi(n-1, pillar_mid, pillar_start, pillar_end);
}
int main(void) {
char name1[] = "A柱";
char name2[] = "B柱";
char name3[] = "C柱";
int n = 3; //盘子数
hanoi(3, name1, name2, name3);
return 0;
}