C语言 项目练习-家庭收支软件

目标

在这里插入图片描述

需求说明

在这里插入图片描述
在这里插入图片描述

界面说明

登记收入界面:
在这里插入图片描述
登记支出界面
在这里插入图片描述
收支明细界面
在这里插入图片描述
退出界面
在这里插入图片描述

项目代码改进要求

在这里插入图片描述

自己完成的代码

版本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;
};
结构体中使用char
name出现问题的解决方案:
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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446525.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ fmt 库安装和使用示例、clion配置

安装 git clone https://github.com/fmtlib/fmt.gitmake .mkae && make install CLion使用 使用和安装存在出入下载源码&#xff0c;可以先 clone 到你的项目中去&#xff0c;https://github.com/fmtlib/fmt &#xff0c;我放到的是项目的 dependencies 目录然后在…

C语言 项目 CRM系统(客户信息管理系统)

项目目标 项目需求说明 系统界面 1)添加客户界面 通过编号来区分客户 2)删除客户界面 对用户输入的编号进行核查,存在与否,合法与否 3)显示客户列表界面 4)修改客户信息的界面 项目设计 Customer结构体的设计 CRM系统结构框架图 案例代码 #include <stdio.h>…

代码重构 防火墙 相关知识

参考 依据Linux命令以及sysconf下现有的iptables命令&#xff0c;详见hsm_sysconf_server/src/sysconf_server.cpp中的firewall规则。 接口名称 firewall_manager 目的(现实) 根据网口直连获取当前eth0和eth1的各种信息保证设置的正确性 以及要针对管理口和服务口设计不…

C语言 文件的基本介绍

基本介绍 输入流与输出流 重点在C程序(内存)的数据移动方向 对于C程序(内存) 输入数据:输入流 输出数据:输出流 输入 和输出 C标准库 标准输入输出库 标准文件 getchar()&putchar()函数 代码 #include<stdio.h> #include<stdlib.h> //文件--getchar()和…

ubuntu修改字体 样式

使用 快捷键 ctrlaltt 打开终端安装gnome-tweaks桌面管理工具 sudo apt install gnome-tweaksaltf2 在运行窗口输入 gnome-tweaks 命令&#xff0c;然后回车打开优化窗口&#xff0c;选择第二个front字体选项ubuntu显示中文

C语言 文件的读写

引入 OS操作系统 打开文件fopen()函数 读写模式: r:读取已有文件 w:文件不存在,创建文件并写入文件.文件存在,内容清零,再写入文件 a: 文件不存在,创建文件并写入文件.文件存在,以追加的形式写入文件 r:读写已有文件 w:文件不存在,创建文件并读写文件.文件存在,内容清零,再…

StarWind V2V Image Converter:虚拟机镜像转换工具,可将 IMG 文件转换为 VMware VMDK 文件

操作流程 选择本地的需要转换的文件找到源文件的路径&#xff0c;img格式选择转化后的格式 第一个选择 第二个 速度快一些选择将转化后的文件的存储路径软件的下载链接 链接: https://pan.baidu.com/s/1Fe6yI42Zz9d_Q7aUhGe1FQ 提取码: 5vmv

数学建模基础知识

原型与模型 模型的分类 数学建模 数学建模的分类 成为建模大神 数学建模比赛 数学建模一般步骤 数学建模全过程 数学建模论文写作 1&#xff09;摘要:是决定最后获奖等级的关键 2&#xff09;问题重述:使用自己的语言将问题重述一次 3&#xff09;符号说明:对于常见的或…

数学建模 线性规划模型基本原理

线性规划问题 例1.1 可行解&可行域 matlab标准形式及软件求解 标准形式: C称为价值向量 如果是求max,加一个负号-c^T 如果是求Ax>b,加一个负号-Ax<b 使用matlab求线性规划例题 求解的是最大值:加上负号 y是求解的最优解 zeros()使用: zeros(n)&#xff1a;生…

接上文 ,解决 虚拟机VM,U盘(磁盘)装有系统,将其中系统安装到另外一块磁盘的具体操作

问题原因&#xff1a;接上文&#xff0c;将生成的vsdk格式的磁盘导入VM创建镜像&#xff0c;相关于U盘装载系统镜像&#xff0c;将U盘其中的镜像导入到磁盘里边&#xff0c;U盘是引导&#xff0c;会将系统最终装载到磁盘出错原因是因为 没有新建第二块磁盘 解决 新增一块磁盘如…

数学建模 层次分析法

简介 针对多目标,多准则或无结构特性的复杂决策问题 步骤 解决评价类问题 评价类问题: 资料查找: 1)查找相关文献 2)如果没有找到相关文献 3)搜索 通过上述步骤后得到的结果 构建层次结构模型 举例: 成对比较矩阵 标度表: 奇数:越大越重要 偶数:上述两相邻判断的中值…

接上文 VM安装的ubuntu系统,配置双网卡

点击编辑 进入虚拟网络编辑器 点击更改设置 补充&#xff1a;如何判定桥接至哪张网卡&#xff1f;进入win&#xff0c;winr 输入cmd&#xff1b;输入 systeminfo选中系统&#xff0c;点击右键&#xff0c;选中设置 重启系统使用 ifconfig查看&#xff0c;发现有eth0和eth1…

数学建模 趣味数模问题(数模入门)

狼羊人菜渡河问题 解答 试探法 因为有4个变量,所以一共有222*216种状态 找出其中不安全的状态:无人看守的状态下:狼羊一起,羊菜一起 人 狼 羊 菜(0是在对面,1是在这边) 狼羊一起:(0,1,1,0) (0,1,1,1) (1,0,0,0) (1,0,0,1) 羊菜一起:(0,0,1,1) (1,1,0,0) 其余的10个都是安全状态…

数学建模 整数规划的基本原理和标准形式

整数规划模型 变量限制为整数 一般解决运输问题和整数问题 分类: 研究的是纯整数规划问题 整数规划特点 实数的解不能直接四舍五入为整数,因为此时可能不满足约束条件 举例-合理下料问题 模型: 题目: 这是在使用材料 1)使用零件A1-Am毛胚,就是使用零件 2)下料方式B1-Bn就…

程序员 面试笔记 C++ 程序设计的基础 第10章

10.1.1 程序的编译和执行 以#开头的代码都属于预处理器处理的步骤#include 将头文件的内容包含进入当前源文件中#define 展开宏定义#ifdef 处理条件编译指令(#ifdef、ifndef、#if、#else、#elif、#endif)#other 处理其他宏指令(#error、#warning、#line、#pragma) 预…

数学建模 分支限界算法求解整数规划原理以及编程实现

引入 线性规划问题(松弛问题) 图解法: 使用图解法求出最优解,再使用四舍五入求出的整数解不满足条件 完全枚举法(穷举法):找出集合内所有满足条件的整数点,再带入不等式中,看是否有最优解 分支限界法 说明: 松弛问题:线性规划问题 ILP:整数规划,在线性规划的基础上对决策…

数学建模 割平面算法求解整数规划基本原理与编程实现

基本思想 松弛问题:线性规划 割掉一块全部都是小数的区域(这一部分取不到整数) 案例 1)横坐标x1,纵坐标x2 2)蓝色小三角形的区域:x2:(1,7/4) x1:(0,3/4) 这块区域,x1与x2完全取不到整数,所以直接切去 所以,此时取值范围变化了: x2<1把此约束条件带入,得到x11,x21,z2 3…

数学建模 匈牙利算法求解整数规划基本原理与编程实现

投资问题(0-1规划) 匈牙利算法求解0-1规划问题 解答: 项目之间是互斥关系,所以使用x1x2x31; 项目5是以项目1为先验条件,所以x5<x1,意味着x11时,x51或0 ,但x10时,x50 案例- 互斥约束问题 1)当两个约束条件是互斥时,新建立一个约束条件y(0-1) 2)如果M取无穷大的数,此时就…

Ubuntu通过可视化界面配置 查找IP地址不存在的解决办法

命令行用ifconfig eno0 up&#xff0c;启用网卡&#xff0c;没有问题&#xff0c;硬件ok&#xff0c;但是配置里面还是找不到。之前修改了 /etc/network/interfaces&#xff0c;去掉配置。由于图形界面使用的是 network-manager&#xff0c;所以需要修改重启sudo service netwo…