項目8的實現,main函數太臃腫,不便於閱讀和維護。ide
用函數來優化。函數
#include <stdio.h> #include <string.h> #include <stdlib.h> 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)肯定函數的返回值
是否須要返回值,返回值的類型設計
函數的聲明3d
函數的使用指針
調用函數時,形參被賦值爲對應的實參,
實參自己不會受到函數的影響!code
要避免棧空間溢出。
當調用一個函數時,就會在棧空間,爲這個函數,分配一塊內存區域,
這塊內存區域,專門給這個函數使用。
這塊內存區域,就叫作「棧幀」。blog
demo1遞歸
#include <stdio.h> #include <string.h> void test(void) { //運行時將由於棧幀空間溢出,而崩潰 char buff[1024*1024*2]; memset(buff, 0, sizeof(buff)); } int main(void) { test(); return 0; }
demo2
#include <stdio.h> #include <string.h> 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 <stdio.h> 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 <stdio.h> void show(char c, int n) { int i; int j; for (i=1; i<=n; i++) { for (j=0; j<n-i; j++) { printf(" "); } for (j=0; j<2*i-1; j++) { printf("%c", c); } printf("\n"); } } int main(void) { char c; int n; printf("請輸入金字塔的組成字符: "); scanf("%c", &c); if (c == '\n' || c == ' ' || c == '\t') { printf("請輸入一個非空白字符\n"); return 1; } printf("請輸入金字塔的層數: "); scanf("%d", &n); if (n < 1) { printf("層數須要大於0\n"); return 1; } show(c, n); return 0; }
#include <stdio.h> 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 <stdio.h> 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; }