学习导航
一、前言
[设计难度 : ★★☆☆☆]
[主要涉及知识:结构体 + 文件操作 + 动态内存开辟 + 函数设计与封装]
[程序运行效果图:]
①基本功能
- 初始登录时自动从文件中读取先前的仓库数据到程序中
- Add函数作用是添加新的一条文件信息
- Del函数作用是删除一条文件信息
- Find函数的作用是根据id值进行查找
- Sort函数的作用是按照某一指标进行排序,这个指标是一个可自选项
- Show函数的作用是展现仓库中的所有数据
- Exit函数的作用是退出程序,并把数据写入文件中保存
代码都很常规,但如果你基础不够扎实,建议先巩固一下结构体 + 文件操作 + 动态内存开辟的相关知识
1.一篇搞定结构体
2.C语言文件操作0基础保姆级教程
3.6000字总结动态内存管理
这里不再就知识点做详细赘述,直接贴代码供大家参考学习。有问题欢迎老家留言区留言,来进行交流讨论
二、实现代码
①head.h文件
[注释]:存放头文件和结构体定义
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <windows.h>
#define DafaultSize 4
typedef struct time //储存年月日
{
int year;
int month;
int day;
}time;
typedef struct Data
{
char id[10]; // id
char type[20]; // 种类
char name[20]; // 名字
int num; // 数量
float price; // 价格
int guaranteeTime; // 保质期
time importTime; // 进货期
}Data;
typedef struct warehouse
{
Data* arr; // 存储数据
int capacity; // 数组的容量
int sz; // 当前数据的个数
}house;
void menu();
void InitHouse(house* ph);
void CheckCapacity(house* ph);
void Add(house* ph);
int Search(house* ph, char* id);
void Del(house* ph);
void Find(house* ph);
void Sort(house* ph);
void Show(house* ph);
②func.c文件
[注释]:存放具体功能的实现模块
#include "head.h"
void InitHouse(house* ph) //初始化仓库
{
assert(ph);
ph->arr = (Data*)malloc(sizeof(Data) * DafaultSize);
ph->capacity = 4;
ph->sz = 0;
}
void CheckCapacity(house* ph)
{
assert(ph);
if (ph->sz == ph->capacity) // 说明
{
int newcapacity = 2 * ph->capacity;
Data* tmp = (Data*)realloc(ph->arr, newcapacity * sizeof(Data));
assert(tmp); //tmp为空则表示扩容失败,直接退出
ph->arr = tmp;
ph->capacity = newcapacity;
}
}
void Add(house* ph)
{
assert(ph);
CheckCapacity(ph);
int sz = ph->sz;
printf("请依次输入以下基本信息:>
");
printf("id: ");
scanf("%s", ph->arr[sz].id);
printf("种类: ");
scanf("%s", ph->arr[sz].type);
printf("名称: ");
scanf("%s", ph->arr[sz].name);
printf("价格: ");
scanf("%f", &ph->arr[sz].price);
printf("数量: ");
scanf("%d", &ph->arr[sz].num);
printf("进货时间/年 月 日 (提示:中间空格间隔, 依次输入): ");
scanf("%d %d %d", &ph->arr[sz].importTime.year,
&ph->arr[sz].importTime.month,
&ph->arr[sz].importTime.day);
printf("保质期(天): ");
scanf("%d", &ph->arr[sz].guaranteeTime);
ph->sz++;
printf("信息录入成功! 即将跳转回主界面
");
Sleep(1000);
system("cls");
}
int Search(house* ph, char* id)
{
assert(ph);
for (int i = 0; i < ph->sz; i++)
{
if (strcmp(id, ph->arr[i].id) == 0)
return i;
}
return -1; // 说明没有找到
}
void Del(house* ph)
{
printf("请输入待删除商品的id值:>");
char id[10];
scanf("%s", id);
int ret = Search(ph, id);
if (ret == -1)
printf("目标商品不存在,删除失败!");
else
{
for (int i = ret; i < ph->sz - 1; i++)
{
ph->arr[i] = ph->arr[i + 1];
}
ph->sz--;
printf("删除成功!即将返回主菜单!");
}
Sleep(2000);
system("cls");
}
void Find(house* ph)
{
printf("请输入待查找商品id值:");
char tmp[10] = {0};
scanf("%s", tmp);
int ret = Search(ph, tmp);
if (ret == -1)
printf("该商品不存在!即将跳转回主菜单
");
else
{
printf("id 种类 名字 数量 价格 保质期 进货日期
");
printf("%s %s %s %d %.2lf¥ %d天 %d年%d月%d日
",
ph->arr[ret].id, ph->arr[ret].type, ph->arr[ret].name,
ph->arr[ret].num, ph->arr[ret].price, ph->arr[ret].guaranteeTime,
ph->arr[ret].importTime.year, ph->arr[ret].importTime.month, ph->arr[ret].importTime.day);
printf("查找成功! 按任意键跳转回主界面
");
system("pause");
}
system("cls");
}
int CmpPrice(void* a, void* b)
{
Data* aa = (Data*)a;
Data* bb = (Data*)b;
return aa->price > bb->price;
}
int CmpNum(void* a, void* b)
{
Data* aa = (Data*)a;
Data* bb = (Data*)b;
return aa->num > bb->num;
}
int CmpImport(void* a, void* b)
{
Data* aa = (Data*)a;
Data* bb = (Data*)b;
if (aa->importTime.year > bb->importTime.year)
return 1;
else if (aa->importTime.year == bb->importTime.year)
{
if (aa->importTime.month > bb->importTime.month)
return 1;
else if (aa->importTime.month == bb->importTime.month)
return aa->importTime.day > bb->importTime.day;
}
return 0;
}
int CmpGuaranteeTime(void* a, void* b)
{
Data* aa = (Data*)a;
Data* bb = (Data*)b;
return aa->guaranteeTime > bb->guaranteeTime;
}
void Sort(house* ph)
{
printf("********************
");
printf("**[请选择排序依据]**
");
printf("**----------------**
");
printf("** 0.价格 **
");
printf("** 1.数量 **
");
printf("** 2.进货时间早晚 **
");
printf("** 3.距离过期时间 **
");
printf("********************
");
int input = 0;
while (1)
{
scanf("%d", &input);
if (input >= 0 && input <= 3)
break;
else
printf("输入错误请重新输入:
");
}
int(*arr[4])(void*, void*) = {CmpPrice, CmpNum, CmpImport, CmpGuaranteeTime }; //函数指针数组,觉得不理解的可以用其他办法
qsort(ph->arr, ph->sz, sizeof(Data), arr[input]);
printf("排序成功! 即将跳转回主界面
");
Sleep(1000);
system("cls");
}
void Show(house* ph)
{
printf("id 种类 名字 数量 价格 保质期 进货日期
");
for (int i = 0; i < ph->sz; i++)
printf("%s %s %s %d %.2lf¥ %d天 %d年%d月%d日
",
ph->arr[i].id, ph->arr[i].type, ph->arr[i].name,
ph->arr[i].num, ph->arr[i].price, ph->arr[i].guaranteeTime,
ph->arr[i].importTime.year, ph->arr[i].importTime.month, ph->arr[i].importTime.day);
system("pause");
system("cls");
}
main.c文件
#include "head.h"
void menu()
{
printf("***********************
");
printf("** 仓库管理系统 **
");
printf("**-------------------**
");
printf("** 1. Add **
"); // 增加数据
printf("** 2. Del **
"); // 删除数据
printf("** 3. Find **
"); // 排序数据
printf("** 4. Sort **
"); // 查找数据
printf("** 5. Show **
"); // 展示所有数据
printf("** 0. Exit **
"); // 退出程序
printf("**-------------------**
");
printf("***********************
");
}
void Login(house* ph) // 从文本中读出之前的仓库货物数据
{
printf("原数数据加载中...
");
FILE* fr = fopen("warehouse.txt", "ab+"); //使用a是为了防止原先该文件不存在
fseek(fr, 0, SEEK_SET); //是文件指针指向开头
int ret = 1;
while (1)
{
CheckCapacity(ph);
ret = fread(ph->arr + ph->sz, sizeof(Data), 1, fr); //返回值为0表示读取结束
if (ret == 0)
{
break;
}
ph->sz++;
}
Sleep(1000); // 为什么延时1s呢?因为好玩^_^
printf("原始数据加载成功!
");
system("pause");
system("cls");
}
void SaveData(house* ph)
{
printf("文件保存中...
");
FILE* fw = fopen("warehouse.txt", "w");
fwrite(ph->arr, sizeof(Data), ph->sz, fw);
Sleep(1000);
printf("文件保存成功!
");
}
int main()
{
house* ph = (house*)malloc(sizeof(house));
InitHouse(ph);
Login(ph);
int input = 0;
do
{
menu();
printf("请选择即将执行的操作:>
");
scanf("%d", &input);
switch(input)
{
case 0: SaveData(ph); break;
case 1: Add(ph); break;
case 2: Del(ph); break;
case 3: Find(ph); break;
case 4: Sort(ph); break;
case 5: Show(ph); break;
}
}while(input);
return 0;
}