C语言学习--项目

目录

前言

16.1 项目-家庭收支记账软件

16.1.1 实现基本功能

16.1.2 菜单显示

16.1.3 登记收入

16.1.4 登记支出

16.1.5 显示明细

16.1.6 退出系统

16.1.7 项目代码实现改进

16.1.8 实现代码版本 1-没有使用结构体和函数封装

16.1.9 实现代码版本 2-使用结构体+函数封装, 提供软件模块化编程,便于维护

16.2 项目-客户信息管理系统

16.2.1 项目需求说明

16.2.2 项目界面(看项目需求 PPT)

16.2.3 项目设计-程序框架图

16.2.4 项目功能实现-完成 Customer 结构体

16.2.5 项目功能实现-显示主菜单和完成退出软件功能

16.2.6 项目功能实现-完成显示客户列表的功能

16.2.7 项目功能实现-添加客户的功能

16.2.8 项目功能实现-完成删除客户的功能

16.2.9 项目功能实现-完善退出确认功能(课后作业)

16.2.10 项目功能实现-完成修改客户的功能(课后作业)

16.2.11 项目功能实现-完成根据 id 查找客户的功能(课后作业)

16.2.12 项目 2-客户关系系统的整体代码

总结

附录


前言

家庭收支记账软件和客户信息管理系统均采用文本界面,以简洁直观的方式提供给用户强大的功能,帮助用户更好地管理财务和客户信息。


16.1 项目-家庭收支记账软件

16.1.1 实现基本功能

编写文件 myAccount.c 完成功能

16.1.2 菜单显示

80d020c5af9e416cadedbdb6ce59b8ea.png

16.1.3 登记收入

a7419d792a134588ae29652ff7e4dada.png

16.1.4 登记支出

53be09ca0e164d5dbe1e0f4423f8f10d.png

16.1.5 显示明细

b02a9003627541889a07edd09a17c6e7.png

16.1.6 退出系统

4b7b77d6fee84c3599250881d25381b3.png

16.1.7 项目代码实现改进

1) 用户输入 4 退出时,给出提示"你确定要退出吗? y/n",必须输入正确的 y/n ,否则循环输入指令,直到输入 y 或者 n。

2) 当没有任何收支明细时,提示 "当前没有收支明细... 来一笔吧!"

3) 在支出时,判断余额是否够,并给出相应的提示。

4) 改成使用结构体完成 => 并且使用函数来提高项目的模块化编程, 利用今后项目的维护和扩展

16.1.8 实现代码版本 1-没有使用结构体和函数封装

#include <stdio.h>

#include <string.h>

void main() {

//完成 1: 显示菜单

//分析

//1. 使用 do-while 来显示菜单,如果用户输入 4 表示退出程序

//完成 2 : 登记收入

//分析

//1. 需要一个字符串来记录收入情况

//完成 3 : 登记支出

//分析

//1. 需要一个字符串来记录收入情况

//完成 4

/*

用户输入 4 退出时,给出提示"你确定要退出吗? y/n",必须输入正确的 y/n ,

否则循环输入指令,直到输入 y 或者 n

*/

//完成 5

/*

当没有任何收支明细时,提示 "当前没有收支明细... 来一笔吧!"

*/

//完成 6

/*

在支出时,判断余额是否够,并给出相应的提示

*/

//定义相关的变量

char key = ' '; //表示用户输入了哪个菜单

int loop = 1; // 控制是否退出菜单

char details[3000] = "-----------------当前收支明细记录-----------------\n 收支\t 收支金额\t 账户金额 \t 说 明 "; //

记录所有的收入和支出情况

char note[20] = ""; //对收入或者支出的说明

char temp[100] = ""; // 是用于格式化每次的收入或者支出,然后拼接到 details

double money = 0.0;

double balance = 1000.0; // 账号余额, 初始化为 1000.0

char choice = ' ';//表示用户选择的是 y/n

int flag = 0; //表示是否有至少一笔收入或者支出

do {

printf("\n\n---------家庭收支记账软件-----------------");

printf("\n 1 收支明细");

printf("\n 2 登记收入");

printf("\n 3 登记支出");

printf("\n 4 退 出");

printf("\n 请选择(1-4):");

scanf("%c", &key);

getchar();// 过滤回车

switch(key) {

case '1' :

if(flag) {

printf("%s", details);

} else {

printf("\n 当前没有收支明细... 来一笔吧!");

}

break;

case '2' :

printf("\n 本次收入金额:");

scanf("%lf", &money);

getchar();//过滤回车

balance += money; //更新余额

printf("\n 本次收入说明:");

scanf("%s", note);

getchar();//过滤回车

sprintf(temp, "\n 收入\t%.2f\t\t%.2f\t\t\t%s", money, balance, note); //将本次信息,写入到 temp 字符数

//将信息拼接到 details

strcat(details, temp);

flag = 1;

break;

case '3' :

printf("\n 本次支出金额:");

scanf("%lf", &money);

getchar();

//判断是否够支出

if(money > balance) { //不够

printf("\n 余额不足...");

break;

}

printf("\n 本次支出说明:");

scanf("%s", note);

getchar();

balance -= money;

sprintf(temp, "\n 支出\t%.2f\t\t%.2f\t\t\t%s", money, balance, note); //将本次信息,写入到 temp 字符数

//将信息拼接到 details

strcat(details, temp);

flag = 1;

break;

case '4' :

printf("\n 你确定要退出吗? y/n");

do {

scanf("%c", &choice);

getchar();

if(choice == 'y' || choice == 'n') {

break;

}

printf("\n 你的输入有误,请重新输入 y/n");

}while(1);

if ( choice == 'y') {

loop = 0;

}

}

}while(loop);

printf("你退出了家庭财务软件~~");

getchar();

}

 

 

16.1.9 实现代码版本 2-使用结构体+函数封装, 提供软件模块化编程,便于维护

#include <stdio.h>

#include <string.h>

//定义一个结构体

struct MyFamilyAccount {

int flag ; // 表示是否有至少一笔收入或者支出

char details[3000]; //明细

double balance; //余额

};

//定义相关的变量, 全局变量

char key = ' '; //表示用户输入了哪个菜单

int loop = 1; // 控制是否退出菜单

char note[20] = ""; //对收入或者支出的说明

char temp[100] = ""; // 是用于格式化每次的收入或者支出,然后拼接到 details

double money = 0.0;

char choice = ' ';//表示用户选择的是 y/n

//使用函数,完成退出

void myExit() {

printf("\n 你确定要退出吗? y/n");

do {

scanf("%c", &choice);

getchar();

if(choice == 'y' || choice == 'n') {

break;

}

printf("\n 你的输入有误,请重新输入 y/n");

}while(1);

if ( choice == 'y') {

loop = 0;

}

}

//使用函数,显示明细

void showDetails(struct MyFamilyAccount *myFamilyAccount) {

if((*myFamilyAccount).flag) {

printf("%s", (*myFamilyAccount).details);

} else {

printf("\n 当前没有收支明细... 来一笔吧!");

}

}

//使用函数,完成登记收入, 封装

void income(struct MyFamilyAccount *myFamilyAccount) {

printf("\n 本次收入金额:");

scanf("%lf", &money);

getchar();//过滤回车

(*myFamilyAccount).balance += money; //更新余额

printf("\n 本次收入说明:");

scanf("%s", note);

getchar();//过滤回车

sprintf(temp, "\n 收入\t%.2f\t\t%.2f\t\t\t%s", money, (*myFamilyAccount).balance, note); //将本次信息,写入到 temp

字符数组

//将信息拼接到 details

strcat((*myFamilyAccount).details, temp);

(*myFamilyAccount).flag = 1;

}

//完成一个登记支出

void pay(struct MyFamilyAccount *myFamilyAccount) {

printf("\n 本次支出金额:");

scanf("%lf", &money);

getchar();

//判断是否够支出

if(money > (*myFamilyAccount).balance) { //不够

printf("\n 余额不足...");

return;

}

printf("\n 本次支出说明:");

scanf("%s", note);

getchar();

(*myFamilyAccount).balance -= money;

sprintf(temp, "\n 支出\t%.2f\t\t%.2f\t\t\t%s", money, (*myFamilyAccount).balance, note); //将本次信息,

写入到 temp 字符数组

//将信息拼接到 details

strcat((*myFamilyAccount).details, temp);

(*myFamilyAccount).flag = 1;

}

//函数专门显示菜单

void mainMenu(struct MyFamilyAccount *myFamilyAccount) {

do {

printf("\n\n---------家庭收支记账软件-----------------");

printf("\n 1 收支明细");

printf("\n 2 登记收入");

printf("\n 3 登记支出");

printf("\n 4 退 出");

printf("\n 请选择(1-4):");

scanf("%c", &key);

getchar();// 过滤回车

switch(key) {

case '1' :

showDetails(myFamilyAccount);

break;

case '2' :

income(myFamilyAccount);

break;

case '3' :

pay(myFamilyAccount);

break;

case '4' :

myExit();

}

}while(loop);

printf("你退出了家庭财务软件~~");

getchar();

}

void main() {

//创建一个结构体变量

struct MyFamilyAccount myFamilyAccount;

//初始化

myFamilyAccount.flag = 0;

myFamilyAccount.balance = 1000.0;

//使用拷贝的方式赋值

memset(myFamilyAccount.details, 3000, 0);

strcpy(myFamilyAccount.details, "-----------------当前收支明细记录-----------------\n 收支\t 收支金额\t 账户金额 \t

说 明");

//调用 mainMenu 显示菜单

mainMenu(&myFamilyAccount);

getchar();

}

//程序的结构示意图

09b744cff03e490f80ba5bad9c237690.png

 

16.2 项目-客户信息管理系统

16.2.1 项目需求说明

模拟实现基于文本界面的《客户信息管理软件》。

该软件能够实现对客户对象的插入、修改和删除(用数组实现),并能够打印客户明细表。

16.2.2 项目界面(看项目需求 PPT)

b623d198536b4fd2b777a717524a338d.png

e75c3f6ae1434e9ba98742f1f1d9f143.png

e33e00347b9f45afaac891933b62e052.png

c1b737ba3e154f5c819b0eec8c64a376.png

16.2.3 项目设计-程序框架图

程序框架图: 描述该项目包含多少个文件/函数,明确文件与文件之间的调用关系。

84c85da49fbb4b659ed9523d5f1f3f49.png

16.2.4 项目功能实现-完成 Customer 结构体

Ø 思路

1) Customer 结构体含有的成员,应该从给出的界面来分析

2) 分析出有 6 个成员, 数据类型有可以分析

3) 编写一个函数,输出给出的某个 Customer 变量的信息

Ø 代码

#include <stdio.h>

//定义结构体数据类型

struct Customer {

int id; //编号

int age; //年龄

char name[10]; //名字

char gender; // 'f' 女 'm' 男

char phone[16]; //电话号码

char email[20]; //邮箱

};

//显示一个 Customer 变量的信息

//这里我们接收的是结构体指针,提高效率

void getCustomerInfo(struct Customer *customer) {

printf("\n%d\t%s\t%c\t%d\t%s\t%s", (*customer).id, (*customer).name, (*customer).gender,(*customer).age,

(*customer).phone,(*customer).email);

}

16.2.5 项目功能实现-显示主菜单和完成退出软件功能

Ø 功能说明:

用户打开软件, 可以看到主菜单,输入 5 退出软件。

Ø 思路分析:

在 customerManage.c 中,编写一个函数 mainMenu,显示菜单, 在 main 函数中调用

Ø 代码实现:

//在原来的 customerManage.c 增加了代码

int loop = 1; //控制是否退出主菜单

char key;

//显示主菜单

void mainMenu() {

do {

printf("\n-----------------客户信息管理软件-----------------");

printf("\n 1 添 加 客 户");

printf("\n 2 修 改 客 户");

printf("\n 3 删 除 客 户");

printf("\n 4 客 户 列 表");

printf("\n 5 退 出");

printf("\n 请选择(1-5):");

scanf("%c", &key);

getchar(); //过滤回车

switch(key) {

case '1':

printf("添加客户");

break;

case '2':

printf("修 改 客 户");

break;

case '3':

printf("删 除 客 户");

break;

case '4':

printf("客 户 列 表");

break;

case '5':

loop = 0;

break;

default :

printf("\n 你输入有误, 请重新输入...");

break;

}

}while(loop);

printf("\n 你退出了客户管理系统");

getchar();

}

void main() {

mainMenu(); //调用函数,显示菜单

}

 

16.2.6 项目功能实现-完成显示客户列表的功能

Ø 功能说明

80aba836fc3b46dd85905de0d3ed2923.png

Ø 思路分析

1) 因为我们需要将多个客户保存起来,因此我们需要使用结构体数组-Customer 结构体数组

2) 编写一个函数 listCustomers 来显示客户信息

3) 在主菜单调用 listCustomers 函数即可

Ø 代码实现

在 customerManage.c 中增加代码

int customerNum = 1; //表示当前有多少个客户

//客户结构体数组

struct Customer customers[100]; //最多有 100 个客户, 超过 100 个,可以扩展

//显示客户信息列表

void listCustomers() {

int i = 0;

printf("---------------------------客户列表---------------------------");

printf("\n 编号\t 姓名\t 性别\t 年龄\t 电话\t 邮箱");

for ( i = 0; i < customerNum; i++) {//表示客户的编号

getCustomerInfo(&customers[i]);

}

}

case '4':

listCustomers();

//void main() {

//为了测试显示客户信息,我们可以先初始化一个客户, 后面我们是通过界面来添加

customers[0].id = 1;

customers[0].age = 10;

strcpy(customers[0].email, "yy@sohu.com");

customers[0].gender = 'f';

strcpy(customers[0].name, "zs");

strcpy(customers[0].phone, "110");

mainMenu(); //调用函数,显示菜单

}

 

16.2.7 项目功能实现-添加客户的功能

Ø 功能说明

3c2c80a12aff4d869d58113492d5abba.png

Ø 思路分析

1) 编写一个 add 函数,在该函数中完成添加客户的功能

2) 在 mainMenu 调用即可

Ø 代码实现

核心代码

//添加客户

void add() {

customers[customerNum].id = customerNum + 1;//编号按照自增规则

printf("\n---------------------添加客户---------------------");

printf("\n 姓名:");

scanf("%s", customers[customerNum].name);

getchar();

printf("\n 性别:");

scanf("%c", &(customers[customerNum].gender));

getchar();

printf("\n 年龄:");

scanf("%d", &(customers[customerNum].age));

getchar();

printf("\n 电话:");

scanf("%s", customers[customerNum].phone);

getchar();

printf("\n 邮箱:");

scanf("%s", customers[customerNum].email);

getchar();

printf("\n---------------------添加完成---------------------");

customerNum++; // 自增,必须

}

//在 mainMenu 调用 add 即可

 

16.2.8 项目功能实现-完成删除客户的功能

Ø 功能说明

5a75c05508174695b4d89cc2f4077341.png

Ø 思路分析

1) 先编写一个函数 findIndex , 根据用户输入的 id ,去查找 该 id 是否存在 customers 结构体数组中,如果存在,就返回该 id 对应的 index , 因为 id 和 index 不是对应的关系, 如果 id 存在,则返回对应的 index, 否则返回 -1

2) 编写一个函数 del , 该函数根据接收的 index 来判断是否可以删除, 如果接收到的 index 是 -1 ,就不删除,否则就删除该 index 对应的客户

3) 编写 delView 函数,让用户可以输入要删除的 id ,并再 mainMenu 函数中调用

Ø 代码实现

//根据输入的 id, 返回 index ,如果没有,就返回-1

int findIndex(int id) {

int index = -1;

int i;

for( i = 0; i < customerNum ; i++ ){

if(customers[i].id == id) {//找到

index = i;

}

}

return index;

}

//说明

//1. 返回 int ,如果 1 就说明删除成功

//2. 返回 0, 表示删除失败

//3. 接收的是要删除的客户 id

int del(int id) {

int index = findIndex(id);

int i;

if(index == -1) {//说明不存在 id 这个客户

return 0; //表示删除失败

} else {

//说明存在,就要删除, 删除的本质就是将编号为 id 的这个客户移除

//1. customers 数组从 index +1 位置 开始,整体前移

for( i = index + 1; i < customerNum; i++) {

customers[i-1] = customers[i];

}

//2. customerNum - 1

customerNum--;

return 1;

}

}

//显示删除客户的界面,然后调用

/*

---------------------删除客户---------------------

请选择待删除客户编号(-1 退出):1

确认是否删除(Y/N):y

---------------------删除完成---------------------

*/

void delView() {

int id = 0;

char choice = ' ';

printf("\n---------------------删除客户---------------------");

printf("\n 请选择待删除客户编号(-1 退出):");

scanf("%d", &id);

getchar();

if(id == -1) {

printf("\n---------------------你放弃删除了---------------------");

return;

}

printf("\n 确认是否删除(Y/N):");

scanf("%c", &choice);

getchar();

if(choice == 'Y') {

if(!del(id)) {

printf("\n---------------------删除失败,id 不存在---------------------");

} else {

printf("\n---------------------删除成功!!---------------------");

}

}

}

//在 mainMenu 调用 delView 函数

case '3':

delView();

break;

 

16.2.9 项目功能实现-完善退出确认功能(课后作业)

Ø 功能说明

要求用户在退出时提示 " 确认是否退出(Y/N):",用户必须输入 Y/N, 否则循环提示。

Ø 思路分析

1) 使用 do-while 循环,提示用户输入 Y/N ,如果输入的不是 Y/N ,就反复提示

2) 需要在增加一个全局变量 choice ,表示用户的一个选择

Ø 代码实现

核心代码

增加一个全局变量

char choice = ' ';

case '5':

do {

printf("\n 确认是否退出(Y/N):");

scanf("%c", &choice);

getchar();

} while(choice != 'Y' && choice != 'N'); //如果输入的不是'Y' , 并且不是'N'

if(choice == 'Y') {

loop = 0;

} // 如果输入的是 N ,不做处理,进行显示菜单

break;

 

16.2.10 项目功能实现-完成修改客户的功能(课后作业)

16.2.11 项目功能实现-完成根据 id 查找客户的功能(课后作业)

Ø 功能说明

66ff54958080468cb366846bd262696a.png

Ø 思路分析

提示:修改客户时,需要先查找该用户 , 如果该用户不存在,就需要提示,并结束修改.

,如果找到该用户,就先显示该用户信息,然后提示输入新的信息, id 不能修改

Ø 代码实现

16.2.12 项目 2-客户关系系统的整体代码

#include <stdio.h>

#include <string.h>

//定义结构体数据类型

struct Customer {

int id; //编号

int age; //年龄

char name[10]; //名字

char gender; // 'f' 女 'm' 男

char phone[16]; //电话号码

char email[20]; //邮箱

};

int loop = 1; //控制是否退出主菜单

char key;

int customerNum = 1; //表示当前有多少个客户

char choice = ' '; //表示用户选择的是 Y/N

//客户结构体数组

struct Customer customers[100]; //最多有 100 个客户, 超过 100 个,可以扩展

//显示一个 Customer 变量的信息

//这里我们接收的是结构体指针,提高效率

void getCustomerInfo(struct Customer *customer) {

printf("\n%d\t%s\t%c\t%d\t%s\t%s", (*customer).id, (*customer).name, (*customer).gender,(*customer).age,

(*customer).phone,(*customer).email);

}

//添加客户

void add() {

customers[customerNum].id = customerNum + 1;//编号按照自增规则

printf("\n---------------------添加客户---------------------");

printf("\n 姓名:");

scanf("%s", customers[customerNum].name);

getchar();

printf("\n 性别:");

scanf("%c", &(customers[customerNum].gender));

getchar();

printf("\n 年龄:");

scanf("%d", &(customers[customerNum].age));

getchar();

printf("\n 电话:");

scanf("%s", customers[customerNum].phone);

getchar();

printf("\n 邮箱:");

scanf("%s", customers[customerNum].email);

getchar();

printf("\n---------------------添加完成---------------------");

customerNum++; // 自增,必须

}

//根据输入的 id, 返回 index ,如果没有,就返回-1

int findIndex(int id) {

int index = -1;

int i;

for( i = 0; i < customerNum ; i++ ){

if(customers[i].id == id) {//找到

index = i;

}

}

return index;

}

//说明

//1. 返回 int ,如果 1 就说明删除成功

//2. 返回 0, 表示删除失败

//3. 接收的是要删除的客户 id

int del(int id) {

int index = findIndex(id);

int i;

if(index == -1) {//说明不存在 id 这个客户

return 0; //表示删除失败

} else {

//说明存在,就要删除, 删除的本质就是将编号为 id 的这个客户移除

//1. customers 数组从 index +1 位置 开始,整体前移

for( i = index + 1; i < customerNum; i++) {

customers[i-1] = customers[i];

}

//2. customerNum - 1

customerNum--;

return 1;

}

}

//显示删除客户的界面,然后调用

/*

---------------------删除客户---------------------

请选择待删除客户编号(-1 退出):1

确认是否删除(Y/N):y

---------------------删除完成---------------------

*/

void delView() {

int id = 0;

char choice = ' ';

printf("\n---------------------删除客户---------------------");

printf("\n 请选择待删除客户编号(-1 退出):");

scanf("%d", &id);

getchar();

if(id == -1) {

printf("\n---------------------你放弃删除了---------------------");

return;

}

printf("\n 确认是否删除(Y/N):");

scanf("%c", &choice);

getchar();

if(choice == 'Y') {

if(!del(id)) {

printf("\n---------------------删除失败,id 不存在---------------------");

} else {

printf("\n---------------------删除成功!!---------------------");

}

}

}

//显示客户信息列表

void listCustomers() {

int i = 0;

printf("---------------------------客户列表---------------------------");

printf("\n 编号\t 姓名\t 性别\t 年龄\t 电话\t 邮箱");

for ( i = 0; i < customerNum; i++) {//表示客户的编号

getCustomerInfo(&customers[i]);

}

}

//显示主菜单

void mainMenu() {

do {

printf("\n\n\n-----------------客户信息管理软件-----------------");

printf("\n 1 添 加 客 户");

printf("\n 2 修 改 客 户");

printf("\n 3 删 除 客 户");

printf("\n 4 客 户 列 表");

printf("\n 5 退 出");

printf("\n 请选择(1-5):");

scanf("%c", &key);

getchar(); //过滤回车

switch(key) {

case '1':

add();

break;

case '2':

printf("修 改 客 户");

break;

case '3':

delView();

break;

case '4':

listCustomers();

break;

case '5':

do {

printf("\n 确认是否退出(Y/N):");

scanf("%c", &choice);

getchar();

} while(choice != 'Y' && choice != 'N'); //如果输入的不是'Y' , 并且不是'N'

if(choice == 'Y') {

loop = 0;

} // 如果输入的是 N ,不做处理,进行显示菜单

break;

default :

printf("\n 你输入有误, 请重新输入...");

break;

}

}while(loop);

printf("\n 你退出了客户管理系统");

getchar();

}

void main() {

//为了测试显示客户信息,我们可以先初始化一个客户, 后面我们是通过界面来添加

customers[0].id = 1;

customers[0].age = 10;

strcpy(customers[0].email, "yy@sohu.com");

customers[0].gender = 'f';

strcpy(customers[0].name, "zs");

strcpy(customers[0].phone, "110");

mainMenu(); //调用函数,显示菜单

}


总结

随着本项目文档的结束,我们希望大家能够学会并实际应用。

附录

参考:【尚硅谷C语言零基础快速入门教程-哔哩哔哩】 https://b23.tv/vS3vTDp

 

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值