目標
需求說明
界面說明
登記收入界面:
登記支出界面
收支明細界面
退出界面
項目代碼改進要求
自己完成的代碼
版本1
#include<stdio.h>
#include<string.h>
void choose(int button,int i);
//項目--家庭收支軟件
static double total=10000;//總金額
#define SIZE 100
//用來接收收支信息
struct Count{char *name;double money;char info[100];
}count[100];
int main()
{int d=0;char c='0';int i=0;//統計記錄個數printf("---------家庭收支軟件--------\n");printf(" 1.收支明細\n 2.登記收入\n 3.登記支出\n 4.退出\n");while(1){printf("請選擇(1-4):");scanf("%d",&d);getchar();//接收回車enterif(d==4){printf("是否確認退出(y/n):");//輸入的是字符串scanf("%c",&c);getchar();//接收回車enter,一定要記得接收回車符if(c=='y'){break;//退出while循環}}else{choose(d,i);if(d==2||d==3){i++;}}}fflush(stdin);//刷新getchar();return 0;
}
void choose(int button,int i)
{int k;if(button==1)//收支明細{printf("---------當前收支明細記錄--------\n");printf("收支\t\t收支金額\t\t總金額\t\t說明\n");if(i==0){printf("無\t\t0.00\t\t\t%.2f\t無\n",total);}else{for(k=0;k<i;k++){printf("%s\t\t%.2f\t\t\t%.2f\t%s\n",count[k].name,count[k].money,total,count[k].info);}}printf("\n---------------------------------\n");}else if(button==2)//登記收入{count[i].name="收入";printf("本次收入金額:");scanf("%lf",&count[i].money);printf("本次收入說明:");scanf("%s",count[i].info);total+=count[i].money;}else if(button==3)//登記支出{count[i].name="支出";printf("本次支出金額:");scanf("%lf",&count[i].money);printf("本次支出說明:");scanf("%s",count[i].info);total-=count[i].money;}}
版本2
#include<stdio.h>
#include<string.h>
void choose(int button,int i);
//項目--家庭收支軟件
static double total=10000;//總金額
//用來接收收支信息
struct Count{char *name;//每一次收支的名稱:收入or支出double money;//每一次收支的金額char info[100];//每一次收支的信息double all;//每一次收支后的總金額
}count[100];
int main()
{int d=0;char c='0';int i=0;//統計記錄個數printf("---------家庭收支軟件--------\n");printf(" 1.收支明細\n 2.登記收入\n 3.登記支出\n 4.退出\n");while(1){printf("請選擇(1-4):");scanf("%d",&d);getchar();//接收回車enterif(d==4){printf("是否確認退出(y/n):");//輸入的是字符串scanf("%c",&c);getchar();//接收回車enter,一定要記得接收回車符if(c=='y'){break;//退出while循環}else if(c=='n'){continue;}else{printf("輸入錯誤\n");} }else{choose(d,i);if(d==2||d==3){i++;}}}fflush(stdin);//刷新getchar();return 0;
}
void choose(int button,int i)
{int k;if(button==1)//收支明細{printf("---------當前收支明細記錄--------\n");printf("收支\t\t收支金額\t\t總金額\t\t說明\n");if(i==0){printf("無\t\t0.00\t\t\t%.2f\t無\n",total);printf("當前沒有收支明細...來一筆吧!\n");}else{for(k=0;k<i;k++){printf("%s\t\t%.2f\t\t\t%.2f\t%s\n",count[k].name,count[k].money,count[k].all,count[k].info);}}printf("\n---------------------------------\n");}else if(button==2)//登記收入{count[i].name="收入";printf("本次收入金額:");scanf("%lf",&count[i].money);printf("本次收入說明:");scanf("%s",count[i].info);total+=count[i].money;count[i].all=total;}else if(button==3)//登記支出{count[i].name="支出";printf("本次支出金額:");double temp=0;//臨時存儲支出金額scanf("%lf",&temp);getchar();//過濾enterif(temp>total){printf("當前余額不足,不能支出\n");}else{count[i].money=temp;printf("本次支出說明:");scanf("%s",count[i].info);total-=count[i].money;count[i].all=total;} }}
案例代碼
案例代碼版本1
#include<stdio.h>
#include<string.h>
//項目--家庭收支軟件(teacher)--代碼版本1
int main()
{//所有的局部變量在使用前要初始化int loop=1;//控制最外層do--while循環int num=0;//用戶選擇的數字char quit='0';//用戶選擇是否退出的操作:y/ndouble total=1000;//總金額double money=0;//每次收支金額char detail[100];//每次收支說明char info[3000]="";//要顯示的所有明細char s[1000]="";//每次收支明細的臨時數組int n=0;//統計是否有至少一筆收支明細記錄,1為有,0為無//初始化detail數組memset(detail,0,sizeof(detail));do{printf("------家庭收支軟件--------\n");printf("--------1.收支明細--------\n--------2.登記收入--------\n--------3.登記支出--------\n--------4.退出-----------\n");printf("請選擇(1-4):");scanf("%d",&num);getchar();//過濾enterswitch(num){//使用switch對每種選擇結果做出反應case 1://收支明細printf("收支\t\t收支金額\t總金額\t說明\n");printf("%s",info);if(!n){printf("當前沒有收支明細..來一筆吧!\n");}break;case 2://登記收入printf("本次收入金額:");scanf("%lf",&money);getchar();//enterprintf("本次收入說明:");scanf("%s",detail);getchar();//entertotal+=money;sprintf(s,"收支\t\t%.2f\t\t%.2f\t%s\n",money,total,detail);strcat(info,s);n=1;//有一筆明細記錄break;case 3://登記支出printf("本次支出金額:");scanf("%lf",&money);getchar();//enterif(money>total){printf("能夠支出的金額不夠\n");}else{printf("本次支出說明:");scanf("%s",detail);getchar();//entertotal-=money;sprintf(s,"收支\t\t%.2f\t\t%.2f\t%s\n",money,total,detail);strcat(info,s);n=1;//有一筆明細記錄}break;case 4://退出do{printf("確認是否退出(y/n):");scanf("%c",&quit);getchar();//enterif(quit=='y'||quit=='n'){break;//跳出此do-while循環}else{printf("輸入錯誤!\n");}}while(1);//循環執行退出詢問if(quit=='y'){loop=0;//結束最外層do-while循環}break;}}while(loop);//循環輸出getchar();return 0;
}
案例代碼版本2
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//項目--家庭收支軟件(teacher)--代碼版本2--結構體+函數
//所有的局部變量在使用前要初始化
int loop=1;//控制最外層do--while循環
char info[3000]="";//要顯示的所有明細
char s[1000]="";//每次收支明細的臨時數組
int num=0;//用戶選擇的數字
char quit='c';//用戶選擇是否退出的操作:y/n//家庭賬戶結構體
struct Account{double total;//總金額double money;//每次收支金額char detail[100];//每次收支說明int n;//統計是否有至少一筆收支明細記錄,1為有,0為無};//支出
void pay(struct Account*count)
{printf("本次支出金額:");scanf("%lf",&(*count).money);getchar();//enterif((*count).money>(*count).total){printf("能夠支出的金額不夠\n");}else{printf("本次支出說明:");scanf("%s",(*count).detail);getchar();//enter(*count).total-=(*count).money;sprintf(s,"收支\t\t%.2f\t\t%.2f\t%s\n",(*count).money,(*count).total,(*count).detail);strcat(info,s);(*count).n=1;//有一筆明細記錄}
}
//收入
void income(struct Account*count)
{printf("本次收入金額:");scanf("%lf",&(*count).money);getchar();//enterprintf("本次收入說明:");scanf("%s",(*count).detail);getchar();//enter(*count).total+=(*count).money;sprintf(s,"收支\t\t%.2f\t\t%.2f\t%s\n",(*count).money,(*count).total,(*count).detail);strcat(info,s);(*count).n=1;//有一筆明細記錄}
//所有明細
void show(struct Account*count)
{printf("收支\t\t收支金額\t總金額\t說明\n");printf("%s",info);if(!(*count).n){printf("當前沒有收支明細..來一筆吧!\n");}}
//退出
void esc()
{do{printf("確認是否退出(y/n):");scanf("%c",&quit);getchar();//enterif(quit=='y'||quit=='n'){break;//跳出此do-while循環}else{printf("輸入錯誤!\n");}}while(1);//循環執行退出詢問if(quit=='y'){loop=0;//結束最外層do-while循環}
}
//顯示菜單
void menu(struct Account*count)
{do{printf("------家庭收支軟件--------\n");printf("--------1.收支明細--------\n--------2.登記收入--------\n--------3.登記支出--------\n--------4.退出-----------\n");printf("請選擇(1-4):");scanf("%d",&num);getchar();//過濾enterswitch(num){//使用switch對每種選擇結果做出反應case 1://收支明細show(count);break;case 2://登記收入income(count);break;case 3://登記支出pay(count);break;case 4://退出esc();break;}}while(loop);//循環輸出
}
int main()
{struct Account*count;//在使用指針時要為指針分配內存空間 struct Account*count=(struct Account*)malloc(20*sizeof(struct Account*));//初始化結構體成員(*count).n=0;//初始化detail數組memset((*count).detail,0,sizeof((*count).detail));(*count).money=0;(*count).total=1000; menu(count);getchar();return 0;
}
寫代碼時遇到的知識點
1.使用memset()去初始化局部變量
C語言中系統只會自動初始化全局變量
定義變量時一定要進行初始化,尤其是數組和結構體這種占用內存大的數據結構。在使用數組的時候經常因為沒有初始化而產生“燙燙燙燙燙燙”這樣的野值,俗稱“亂碼”
memset() 函數可以說是初始化內存的“萬能函數”,通常為新申請的內存進行初始化工作。它是直接操作內存空間
使用# include <string.h>
void *memset(void *s, int c, unsigned long n);
memset(s,0,3000);
函數的功能是:將指針變量 s 所指向的前 n 字節的內存單元用一個“整數” c 替換,注意 c 是 int 型。s 是 void* 型的指針變量,所以它可以為任何類型的數據進行初始化。
memset(s,0,3000);
將數組s的前3000個字節的內存單元全部初始化為0,即對數組進行清0
記憶: memset(s,0,sizeof(s));
結構體中的字符數組和字符指針
1)
C語言只有在定義字符數組的時候才能用“=”來初始化變量,其它情況下是不能直接用“=”來為字符數組賦值的,要為字符數組賦值可以用string.h頭文件中的strcpy函數來完成。
例如:
char a[10] = “123”; /正確,在定義的時候初始化/
char a[10];
a = “123”; /錯誤,不能用“=”直接為字符數組賦值/
strcpy(a, “123”); /正確,使用strcpy函數復制字符串/
所以這里不能使用myFamilyAccout.details=”xx”;
補充:
用char c[20]定義的,用strcpy拷貝來賦值, strcpy(c, “123”);
用char *p定義的,用=來賦值,p=”iio”;(記得分配地址給指針)
struct mem
{
char name[20];
char name;
};
結構體中使用charname出現問題的解決方案:
char name[20];是有著自己連續的一塊內存空間的
char *name;僅僅是個指針,是一個標記,沒有分配用來保存字符串的空間
要使用指針,記得分配空間,不然肯定各種錯誤
有2種解決方案:
1、
char *name;
char n[20];
name=n;
2、
char *name;
name=(char *)malloc(sizeof(char)*20);
由于大小為20個字節,所以除了最后一位字符串結束標記外還可以存放19個字節。
前者效率高些,后者用完后可以用free()釋放空間
案例
#include<stdio.h>
#include<stdlib.h>
#define NUM 2
struct mem
{char *name;char phone[10];
};
void main()
{struct mem man[NUM];char c[20];int i;for(i=0;i<NUM;i++){man[i].name=(char*)malloc(20*sizeof(char));//為結構體指針動態分配地址//方式2:新建立一個數組,讓指針指向數組地址//man[i].name=c;printf("input name:\n");gets(man[i].name);printf("input phone:\n");gets(man[i].phone);}printf("name\t\t\tphone\n\n");for(i=0;i<NUM;i++){printf("%s\t\t\t%s\n",man[i].name,man[i].phone);free(man[i].name);//釋放指針內存空間}getchar();
}