C語言-超市倉庫管理系統的設計與實現

HJH0924發表於2020-11-02

C語言-超市倉庫管理系統的設計與實現

第一個部落格~
超市倉庫管理系統的設計與實現
問題描述:實現一個小型倉庫管理系統,完成商品的入庫,出庫,查詢等功能。
物品資訊說明:物品程式碼,物品名稱,物品總量,商品價格、保質期時間、入庫時間
具體功能說明:
(1)物品入庫:輸入物品資訊進入倉庫;
(2)物品出庫:輸入出庫資訊進行物品出庫;
(3)查詢:輸入商品程式碼或名稱查詢庫存資訊,輸入入庫日期查詢所有當天入庫商品資訊,輸入出庫日期查詢所有當天出庫商品資訊,範圍查詢;
(4)保質期查詢:顯示所有過保質期的商品,顯示快到保質期時間所有商品;
(5)資料的持久化操作:存檔案和讀檔案;
(6)在需求分析階段完成未盡功能需求,適當擴充功能(至少擴充3-5個功能)。1.管理員登入 2.新增 刪除管理員 3.商品資訊修改 4.商品資訊統計

系統需求分析

  1. 超市倉庫管理系統介紹
    隨著計算機技術的不斷髮展,為了方便超市倉庫管理人員對超市商品、供應商、入/出庫等進行高效的管理,本超市倉庫管理系統應運而生。本系統要求系統介面友好、使用簡單、提供對商品資訊、管理員資訊和商品流通情況的編輯、查詢、統計報表等全面的資料管理功能。
  2. 超市倉庫管理系統使用者說明
    本系統有兩類使用者:超級管理員和普通管理員。
    超級管理員可以進行登入並進行管理員賬號的新增和刪除。普通管理員可以進行登入,商品入/出庫資訊管理,商品資訊修改、查詢、排序,商品過期統計功能,商品庫存報警功能。
  3. 超市倉庫管理系統功能介紹
    在這裡插入圖片描述

系統主要功能包括管理員模組,商品入/出庫模組,商品資訊管理模組,具體說明如下:
1)管理員模組:超級管理員可以進行管理員的新增和刪除,普通管理員可以進行登入,商品入/出庫資訊管理,商品資訊修改、查詢、排序,商品過期統計功能,商品庫存報警功能。
2)商品入/出庫模組:主要完成物品資訊入出倉庫(從檔案中讀取入庫資料,出庫資料)。
3)商品資訊管理模組:
1.商品資料的讀寫:主要完成從檔案中讀取商品資料和向檔案中寫入最終商品資料。
2.查詢:主要完成輸入商品程式碼或名稱查詢庫存資訊,輸入入庫日期查詢所有當天入庫商品資訊,輸入出庫日期查詢所有當天出庫商品資訊,範圍查詢。保質期查詢:顯示所有過保質期的商品,顯示快到保質期時間所有商品。
3.修改:主要完成修改指定商品資訊的功能。
4.排序:主要完成對商品按商品庫存升序的功能。
5.統計:主要完成統計所有物品資訊的功能。
資訊的永久化處理:所有記憶體資料應儲存到檔案中,做永久化處理,以便資料不會丟失。

系統總體設計

  1. 資料結構設計
    (1)管理員物件:管理員賬號,管理員密碼,指向下一個管理員的指標
typedef struct admin
{
	int admin;						//管理員賬號
	int password;				    //管理員密碼
	struct admin* next;				//指向下一個管理員的指標
}Admin;

(2)商品生產日期物件:年,月,日

typedef struct date					//生產日期結構體
{
   int year;
   int month;
   int day;
}Date;

(3)商品物件:商品程式碼,商品名稱,商品庫存,商品價格,保質期時間,入庫數目,出庫數目,最終庫存,是否過期標誌,庫存是否小於警戒值標誌,指向下一個商品的指標,生產日期,入庫時間,出庫時間。

typedef struct goods
{
   int good_id;					    //商品程式碼
   char name[20];					//商品名稱
   int stock;						//商品庫存
   int price;						//商品價格
   int quality_time;				//保質期時間
   int in_warehouse;				//入庫數目
   int out_warehouse;				//出庫數目
   int sum_warehouse;				//最終庫存

   int state_over;					//是否過期標誌
   int state_warning;				//庫存是否小於警戒值標誌

   struct goods* next;				//指向下一個物品的指標
   struct date production_time;	    //生產日期
   struct date in_time;			    //入庫時間
   struct date out_time;		    //出庫時間
}Goods;

系統詳細設計與實現

3.1讀管理員檔案
Admin* Read_AdminFile(FILE* fp)
處理流程:傳入檔案指標fp,先申請頭結點,當fp不為空時,建立一個結點,讀入管理員賬號密碼,最後返回頭指標。
3.2寫管理員檔案
void Save_To_AdminFile(Admin* head)
處理流程:傳入連結串列頭指標,只讀方式開啟管理員檔案,當連結串列不為空時寫入管理員資料,最後關閉檔案,並顯示儲存成功,儲存了幾名管理員資料資訊。
3.3新增管理員
Admin* InsertAdmin(Admin* head)
處理流程:傳入連結串列頭指標,新建立一個結點,輸入管理員資料,將新結點鏈入連結串列頭(頭插法),最後顯示新管理員新增成功資訊。
3.4刪除管理員
Admin* DeleteAdmin(Admin* head, int admin)
處理流程:傳入連結串列頭指標和管理員賬號,搜尋是否有此管理員,若有則free()刪除結點,若無則顯示無此管理員資訊。
3.5銷燬管理員連結串列釋放記憶體
void DestroyAdminLine(Admin* head)
處理流程:傳入檔案頭指標,若頭指標不為空逐個結點銷燬釋放記憶體。
3.6判斷是否為閏年
int isPrime(int year)
處理流程:傳入一個年份,若為閏年返回1,否則返回0。
3.7計算兩個日期相差天數
int dateDiff(Date mindate, Date maxdate)
處理流程:先將兩個日期設定為前小後大,再計算年份,mindate到maxdate中的年份為閏年則加366,否則加365,再計算月份,若年份為閏年,則呼叫閏年月份天數陣列,否則呼叫非閏年月份天數陣列,最後返回兩個日期相差天數。
3.8判斷商品庫存是否低於警戒值
int pan_goods_warning(Goods* p)
處理流程:傳入商品指標,若商品庫存大於庫存警戒值則返回false,否則返回true。
3.9判斷商品庫存是否低於警戒值
int pan_goods_warning(Goods* p)
處理流程:傳入商品指標,若商品庫存大於庫存警戒值則返回false,否則返回true。
3.10顯示錶頭
void printhead()
處理流程:顯示商品資訊表頭。
3.11顯示錶體
void printgoods(Goods* p)
處理流程:傳入商品指標,計算商品最終庫存,計算商品庫存是否低於警戒值,計算商品是否過期,顯示商品資訊。
3.12分頁顯示指定頁面商品資訊
void getpage(Goods* head, int page)
處理流程:傳入連結串列頭指標,頁碼,設定行號計數器row為0,起始行start,結束行end,當連結串列不為空時,若row在start與end之間,則顯示商品資訊。
3.13分頁顯示全部商品資訊
void GoodsShow(Goods* head)
處理流程:傳入連結串列頭指標,先計算顯示總頁數,呼叫getpage()函式顯示當前頁,根據當前頁的頁碼設定分頁選單並顯示。
3.14查詢商品庫存
Goods* GoodsStock_Query(Goods* head)
處理流程:傳入商品頭指標,函式提供2種查詢方式(按商品程式碼查詢,按商品名稱查詢)。如果選擇按商品程式碼查詢,對商品程式碼進行檢索,若找到則輸出該商品的全部資訊;按商品名稱查詢類似。。
3.15查詢當天入/出庫商品
Goods* GoodsInOut_Query(Goods* head)
處理流程:傳入商品頭指標,函式提供2種查詢方式(按入庫日期查詢,按出庫日期查詢)。根據所輸入的日期遍歷連結串列,若查詢成功則輸出該商品的全部資訊。
3.16查詢商品保質期
void GoodsQualityTime(Goods* head)
處理流程:傳入商品頭指標,函式提供2種查詢方式(1-顯示所有過保質期的商品,2-顯示所有快到保質期的商品)。1-呼叫判斷商品過期函式,遍歷連結串列,若過期則顯示該商品資訊。2-呼叫計算兩日期相差天數函式,遍歷連結串列,若相差天數小於10則視為快過期並顯示該商品資訊。
3.17商品資訊修改
Goods* Goods_Edit(Goods* head)
處理流程:傳入商品頭指標,先呼叫商品資訊查詢函式,若有該商品,則輸入該商品的修改資訊,若無,則顯示無該商品記錄資訊。
3.18商品資訊排序(按商品庫存升序排序)
void Goods_Sort(Goods* head)
處理流程:傳入商品頭指標,用氣泡排序將商品按商品庫存排序。
3.19商品入庫
Goods* In_WareHouse(Goods* head)
處理流程:傳入商品頭指標,當檔案指標不為空時,讀入商品入庫資料鏈入連結串列,返回商品連結串列頭指標。
3.20商品出庫
Goods* Out_WareHouse(Goods* head)
處理流程:傳入商品頭指標,當檔案指標不為空時,讀入商品出庫資料鏈入連結串列,返回商品連結串列頭指標。
3.21判斷商品在入庫時間是否過期
int pan_goodsIn_over(Goods* head)
處理流程:傳入商品頭指標,呼叫dateDiff()函式計算商品生產日期到入庫日期的相差天數與保質期相比較,若大於則過期返回1,否則返回0。
3.22判斷商品在出庫時間是否過期
int pan_goodsOut_over(Goods* head)
處理流程:傳入商品頭指標,呼叫dateDiff()函式計算商品生產日期到出庫日期的相差天數與保質期相比較,若大於則過期返回1,否則返回0。
3.23讀商品檔案
Goods* Read_GoodsFile(FILE* fp)
處理流程:傳入檔案指標fp,先申請頭結點,當fp不為空時,建立一個結點,讀入商品資訊,最後返回連結串列頭指標。
3.24寫商品檔案
void Save_To_GoodsFile(Goods* head)
處理流程:傳入連結串列頭指標,只讀方式開啟商品檔案,當連結串列不為空時寫入商品資料,最後關閉檔案,並顯示儲存成功,儲存了幾項商品資料資訊。
3.25銷燬商品連結串列釋放記憶體
void DestroyGoodsLine(Goods* head)
處理流程:傳入檔案頭指標,若頭指標不為空逐個結點銷燬釋放記憶體。
3.26讀商品檔案
Goods* Read_GoodsFile(FILE* fp)
處理流程:傳入檔案指標fp,先申請頭結點,當fp不為空時,建立一個結點,讀入商品資訊,最後返回連結串列頭指標。

原始碼

原始檔包含admin.h,date.h,goods.h,超市倉庫管理系統的設計與實現.c,admin.txt,goods.txt,stockin.txt,stockout.txt

//admin.h
#pragma once

#include <stdio.h>
#include <malloc.h>
#pragma warning(disable:6031)
int admin_length = 0;				//管理員連結串列的長度
#define Super_Admin 123             //超級管理員賬號
#define Super_Password 456			//超級管理員密碼

typedef struct admin
{
   int admin;						//管理員賬號
   int password;				    //管理員密碼
   struct admin* next;				//指向下一個管理員的指標
}Admin;

//讀管理員檔案
Admin* Read_AdminFile(FILE* fp)
{
   int i = 1;
   Admin* head = NULL, * newadmin, * p2 = NULL;
   head = (Admin*)malloc(sizeof(Admin));
   head->next = NULL;

   while (!feof(fp)) {
   	newadmin = (Admin*)malloc(sizeof(Admin));
   	newadmin->next = NULL;
   	fscanf(fp, "%d%d", &newadmin->admin, &newadmin->password);
   	admin_length++;
   	if (i == 1) head->next = newadmin;
   	else p2->next = newadmin;
   	p2 = newadmin; i++;
   }
   return head;
}

//寫管理員檔案
void Save_To_AdminFile(Admin* head)
{
   FILE* fp;
   int num = 0;
   Admin* p;
   p = head->next;
   if ((fp = fopen("admin.txt", "w")) == NULL) {
   	printf("無法開啟資料檔案!\n");
   	return;
   }
   while (p != NULL) {
   	fprintf(fp, "%d %d\n", p->admin, p->password);
   	num++;
   	p = p->next;
   }
   fclose(fp);
   printf("儲存結束,共儲存了%d名管理員資料!\n", num);
}

//新增管理員
Admin* InsertAdmin(Admin* head)    
{
   Admin* p, * pnew;
   p = head;
   while (p->next != NULL) { p = p->next; }
   pnew = (Admin*)malloc(sizeof(Admin));
   if (pnew == NULL) { printf("不能成功分配到儲存塊!\n"); exit(0); }
   pnew->next = NULL;
   printf("請輸入新管理員的賬號:\n");
   scanf("%d", &pnew->admin);
   printf("請輸入新管理員的密碼:\n");
   scanf("%d", &pnew->password);
   p->next = pnew;
   admin_length++;
   printf("新管理員新增成功!\n");
   return head;
}

//刪除管理員
Admin* DeleteAdmin(Admin* head, int admin)
{
   Admin* p1 = head, * p2 = head;
   while ((p1->admin != admin) && p1->next != NULL) { p2 = p1; p1 = p1->next; }
   if (p1->admin == admin) {
   	if (p1 == head) head = p1->next;
   	else p2->next = p1->next;
   	free(p1);
   	printf("刪除成功!\n");
   }
   else {
   	printf("無此管理員!\n");
   }
   return head;
}

//銷燬管理員連結串列釋放記憶體
void DestroyAdminLine(Admin* head)
{
   Admin* p, * q1, * q2;
   p = head;
   q1 = p->next;
   if (q1 == NULL) return;
   q2 = q1->next;
   while (q1->next)
   {
   	free(q1);
   	q1 = q2;
   	q2 = q2->next;
   }
}
//date.h
#pragma once

typedef struct date					//生產日期結構體
{
   int year;
   int month;
   int day;
}Date;

//判斷是否為閏年
int isPrime(int year)
{
   if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
   	return 1;
   }
   else
   	return 0;
}

//計算兩個日期相差天數
int dateDiff(Date mindate, Date maxdate)
{
   int days = 0, flag = 1;
   int primeMonth[12] = { 31,29,31,30,31,30,31,31,30,31,30,31 };
   int notPrimeMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

   Date tmp;
   if ((mindate.year > maxdate.year) || (mindate.year == maxdate.year && mindate.month > maxdate.month) || (mindate.year == maxdate.year && mindate.month == maxdate.month && mindate.day > maxdate.day))
   {
   	tmp = mindate;
   	mindate = maxdate;
   	maxdate = tmp;
   }

   int maxmonth, minmonth;

   if (maxdate.month < mindate.month)
   {
   	maxmonth = mindate.month;
   	minmonth = maxdate.month;
   	flag = -1;
   }
   else
   {
   	maxmonth = maxdate.month;
   	minmonth = mindate.month;
   	flag = 1;
   }

   for (int j = mindate.year;j < maxdate.year;++j)
   {
   	if (isPrime(j) == 1)
   	{
   		days += 366;
   	}
   	else
   		days += 365;
   }

   int day;
   if (isPrime(maxdate.year) == 1)
   {

   	for (int i = minmonth;i < maxmonth;i++)
   	{
   		day = primeMonth[i - 1] * flag;
   		days = days + day;
   	}
   	days = days + maxdate.day - mindate.day;
   }
   else
   {
   	for (int i = minmonth;i < maxmonth;i++)
   	{
   		day = notPrimeMonth[i - 1] * flag;
   		days = days + day;
   	}
   	days = days + maxdate.day - mindate.day;
   }
   return days;
}
//goods.h
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "date.h"
#pragma warning(disable:6031)
#pragma warning(disable:4996)

#define pagesize 10                 //頁長度 10
#define warning_warehouse 100       //庫存警戒值
#define true 1
#define false 0
int goods_length = 0;				//商品連結串列的長度

typedef struct goods
{
   int good_id;					//商品程式碼
   char name[20];					//商品名稱
   int stock;						//商品庫存
   int price;						//商品價格
   int quality_time;				//保質期時間
   int in_warehouse;				//入庫數目
   int out_warehouse;				//出庫數目
   int sum_warehouse;				//最終庫存

   int state_over;					//是否過期標誌
   int state_warning;				//庫存是否小於警戒值標誌

   struct goods* next;				//指向下一個物品的指標
   struct date production_time;	//生產日期
   struct date in_time;			//入庫時間
   struct date out_time;			//出庫時間
}Goods;

//判斷商品庫存是否低於警戒值
int pan_goods_warning(Goods* p)
{
   if (p->stock >= warning_warehouse)
   	return false;
   else
   	return true;
}

//顯示錶頭
void printhead()
{
   printf("商品程式碼  商品名稱  商品價格  原始庫存  生產日期  入庫數目  入庫日期  出庫數目  出庫日期  最終庫存  保質期時間  是否低於警戒值  入庫時是否過期  出庫時是否過期  (0-否 1-是)\n");
}

//顯示錶體
void printgoods(Goods* p)
{
   int in = 0, out = 0;
   p->sum_warehouse = p->stock + p->in_warehouse - p->out_warehouse;
   p->state_warning = pan_goods_warning(p);
   in = pan_goodsIn_over(p);
   out = pan_goodsOut_over(p);
   printf("%5d %5s %5d元 %5d %d-%d-%d %5d %d-%d-%d %5d %d-%d-%d %5d %5d %5d %5d %5d\n", p->good_id, p->name, p->price, p->stock, p->production_time.year, p->production_time.month, p->production_time.day, p->in_warehouse, p->in_time.year, p->in_time.month, p->in_time.day, p->out_warehouse, p->out_time.year, p->out_time.month, p->out_time.day, p->sum_warehouse, p->quality_time, p->state_warning, in, out);
}

//分頁顯示指定頁面商品資訊
void getpage(Goods* head, int page)
{
   int row = 0;                                  //行號計數器:初值為0
   int start = (page - 1) * pagesize + 1;        //頁行號下限:開始行
   int end = start + pagesize - 1;               //頁行號上限:結束行
   Goods* p;
   p = head->next;
   printhead();
   while (p != NULL) {
   	row++;
   	if (row >= start && row <= end) {
   		printgoods(p);
   	}
   	else if (row > end) 
   		break;
   	p = p->next;
   }
}

//分頁顯示全部商品資訊
void GoodsShow(Goods* head)
{
   int page = 1, total_page, error, t;
   if (goods_length == 0) {
   	printf("沒有商品資訊資料!\n");
   }
   if (goods_length % 10 == 0) {
   	total_page = goods_length / 10;
   }
   else {
   	total_page = goods_length / 10 + 1;
   }
   while (1) {
   	fflush(stdin);											//清空輸入緩衝區
   	if (goods_length == 0) break;
   	printf("\n當前第%d頁,總共%d頁\n", page, total_page);
   	getpage(head, page);
   	if (total_page == 1) break;
   	else if (page == 1)
   	{
   		printf("分頁選單:3-下一頁  4-尾頁  5-返回\n請輸入選單編號(3-5):");
   		do {
   			fflush(stdin);
   			scanf("%d", &t);
   			switch (t) {
   			case 3:page++; error = 0; system("cls"); break;
   			case 4:page = total_page; error = 0; system("cls"); break;
   			case 5:return;
   			default:error = 1; printf("選單編號輸入錯誤,請輸入選單編號(3-5):"); break;
   			}
   		} while (error);
   	}
   	else if (page == total_page) {
   		printf("分頁選單:1-首頁  2-上一頁  5-返回\n請輸入選單編號(1、2、5):");
   		do {
   			scanf("%d", &t);
   			switch (t) {
   			case 1:page = 1; error = 0; system("cls"); break;
   			case 2:page--; error = 0; system("cls"); break;
   			case 5:return;
   			default:error = 1; printf("選單編碼輸入錯誤,請輸入選單編號(1、2、5):"); break;
   			}
   		} while (error);
   	}
   	else {
   		printf("分頁選單:1-首頁  2-上一頁  3-下一頁  4-尾頁  5-返回\n");
   		printf("請輸入選單編號:");
   		do {
   			fflush(stdin);
   			scanf("%d", &t);
   			switch (t) {
   			case 1:page = 1; error = 0; system("cls"); break;
   			case 2:page--; error = 0; system("cls"); break;
   			case 3:page++; error = 0; system("cls"); break;
   			case 4:page = total_page; error = 0; system("cls"); break;
   			case 5:return;
   			default:error = 1; printf("選單編碼輸入錯誤,請輸入選單編號(1-5):"); break;
   			}
   		} while (error);
   	}
   }
}

//查詢商品庫存
Goods* GoodsStock_Query(Goods* head)
{
   int choice, id;
   char name[20];
   Goods* p;
   p = head;
   printf("*          1-按商品程式碼查詢          2-按商品名稱查詢          *\n");
   scanf("%d", &choice);
   if (choice == 1) {
   	printf("請輸入要查詢商品的商品程式碼:\n");
   	scanf("%d", &id);
   	while ((p->good_id != id) && (p->next != NULL))  p = p->next;
   	if (p->good_id != id) p = NULL;
   	else {
   		printhead();
   		printgoods(p);
   	}
   	return p;
   }
   else if (choice == 2) {
   	printf("請輸入要查詢商品的商品名稱:\n");
   	scanf("%s", name);
   	while ((strcmp(name, p->name) != 0) && (p->next != NULL))  p = p->next;
   	if (strcmp(name, p->name) != 0) p = NULL;
   	else {
   		printhead();
   		printgoods(p);
   	}
   	return p;
   }
   return head;
}

//查詢當天入/出庫商品
Goods* GoodsInOut_Query(Goods* head)
{
   int choice;
   int year, month, day;
   Goods* p;
   p = head;
   printf("*            1-輸入入庫日期查詢當天所有入庫商品資訊            *\n");
   printf("*            2-輸入出庫日期查詢當天所有出庫商品資訊            *\n");
   scanf("%d", &choice);
   if (choice == 1) {
   	printf("請輸入入庫日期(輸入格式2001 2 3):\n");
   	scanf("%d%d%d", &year, &month, &day);
   	printhead();
   	while (p->next != NULL) {
   		if (p->in_time.year == year && p->in_time.month == month && p->in_time.day == day)
   			printgoods(p);
   		p = p->next;
   	}
   }
   else if (choice == 2) {
   	printf("請輸入出庫日期(輸入格式2001 2 3):\n");
   	scanf("%d%d%d", &year, &month, &day);
   	printhead();
   	while (p->next != NULL) {
   		if (p->out_time.year == year && p->out_time.month == month && p->out_time.day == day)
   			printgoods(p);
   		p = p->next;
   	}
   }
   return head;
}

//查詢商品保質期
void GoodsQualityTime(Goods* head)
{
   int choice;
   Date d;
   Goods* p;
   p = head->next;
   printf("*  1-顯示所有過保質期的商品     2-顯示快到保質期時間所有商品   *\n");
   scanf("%d", &choice);
   if (choice == 1) {
   	printhead();
   	while (p != NULL) {
   		if ((pan_goodsIn_over(p) == 1) || (pan_goodsOut_over(p) == 1)) {
   			printgoods(p);
   		}
   		p = p->next;
   	}
   }
   else if (choice == 2) {
   	printf("請輸入當天日期:\n");
   	scanf("%d%d%d", &d.year, &d.month, &d.day);
   	printhead();
   	while (p != NULL) {
   		if ((dateDiff(p->production_time, d) - p->quality_time) <= 10) {
   			printgoods(p);
   		}
   		p = p->next;
   	}
   }
}

//商品資訊修改
Goods* Goods_Edit(Goods* head)
{
   Goods* p;
   p = head;
   p = GoodsStock_Query(p);
   if (p == NULL) printf("無商品記錄!\n");
   else {
   	printf("請輸入商品修改資料:\n");
   	printf("商品程式碼  商品名稱  商品庫存  商品價格  商品保質期時間  商品入庫數目  商品出庫數目:\n");
   	scanf("%d%s%d%d%d%d%d", &p->good_id, p->name, &p->stock, &p->price, &p->quality_time, &p->in_warehouse, &p->out_warehouse);
   	getchar();
   	printf("請輸入生產日期(輸入格式2001 2 3):\n");
   	scanf("%d%d%d", &p->production_time.year, &p->production_time.month, &p->production_time.day);
   	getchar();
   	printf("請輸入入庫日期(輸入格式2001 2 3):\n");
   	scanf("%d%d%d", &p->in_time.year, &p->in_time.month, &p->in_time.day);
   	getchar();
   	printf("請輸入出庫日期(輸入格式2001 2 3):\n");
   	scanf("%d%d%d", &p->out_time.year, &p->out_time.month, &p->out_time.day);
   	getchar();
   	if (dateDiff(p->production_time, p->in_time) > p->quality_time) {
   		p->state_over = 1;
   	}
   	else if (dateDiff(p->production_time, p->out_time) > p->quality_time) {
   		p->state_over = 1;
   	}
   	else
   		p->state_over = 0;
   	p->sum_warehouse = p->stock + p->in_warehouse - p->out_warehouse;
   	p->state_warning = pan_goods_warning(p);
   	printf("資料修改成功!\n");
   }
   return head;
}

//商品資訊排序(按商品庫存升序排序)
void Goods_Sort(Goods* head)
{
   Goods* p1;
   Goods* p2;
   p1 = NULL;
   p2 = head->next;
   int i, temp_id, temp_stock, temp_price, temp_quality_time, temp_in_warehouse, temp_out_warehouse, temp_sum_warehouse;
   char temp_name[20];
   if (p2 != NULL) {
   	for (i = 0; i < goods_length-1; i++) {
   		p1 = head->next;
   		p2 = head->next->next;
   		while (p2 != NULL) {
   			if (p1->stock > p2->stock) {
   				temp_id = p1->good_id; temp_stock = p1->stock; temp_price = p1->price; temp_quality_time = p1->quality_time; temp_in_warehouse = p1->in_warehouse; temp_out_warehouse = p1->out_warehouse; temp_sum_warehouse = p1->sum_warehouse; strcpy(temp_name, p1->name);
   				p1->good_id = p2->good_id; p1->stock = p2->stock; p1->price = p2->price; p1->quality_time = p2->quality_time; p1->in_warehouse = p2->in_warehouse; p1->out_warehouse = p2->out_warehouse; p1->sum_warehouse = p2->sum_warehouse; strcpy(p1->name, p2->name);
   				p2->good_id = temp_id; p2->stock = temp_stock; p2->price = temp_price; p2->quality_time = temp_quality_time; p2->in_warehouse = temp_in_warehouse; p2->out_warehouse = temp_out_warehouse; p2->sum_warehouse = temp_sum_warehouse; strcpy(p2->name, temp_name);
   			}
   			p1 = p1->next; p2 = p2->next;
   		}
   	}
   }
   p1 = head->next;
   //判斷商品是否過期 庫存是否低於警戒值
   while (p1 != NULL) {
   	if (dateDiff(p1->production_time, p1->in_time) > p1->quality_time) {
   		p1->state_over = 1;
   	}
   	else if (dateDiff(p1->production_time, p1->out_time) > p1->quality_time) {
   		p1->state_over = 1;
   	}
   	else p1->state_over = 0;
   	p1->state_warning = pan_goods_warning(p1);
   	p1 = p1->next;
   }
}

//商品入庫
Goods* In_WareHouse(Goods* head)
{
   FILE* fp;
   Goods* p;
   p = head->next;
   fp = fopen("stockin.txt", "r");
   if (fp == NULL) { printf("商品入庫檔案開啟錯誤!\n"); exit(0); }
   while (!feof(fp)) {
   	fscanf(fp, "%d%d%d%d%d", &p->good_id, &p->in_warehouse, &p->in_time.year, &p->in_time.month, &p->in_time.day);
   	p->sum_warehouse = p->stock + p->in_warehouse;
   	p->state_over = pan_goodsIn_over(p);
   	p = p->next;
   }
   return head;
}

//商品出庫
Goods* Out_WareHouse(Goods* head)
{
   FILE* fp;
   Goods* p;
   p = head->next;
   fp = fopen("stockout.txt", "r");
   while (!feof(fp)) {
   	fscanf(fp, "%d%d%d%d%d", &p->good_id, &p->out_warehouse, &p->out_time.year, &p->out_time.month, &p->out_time.day);
   	p->sum_warehouse = p->stock - p->out_warehouse;
   	p->state_over = pan_goodsOut_over(p);
   	p = p->next;
   }
   return head;
}

//判斷商品在入庫的時間是否過期
int pan_goodsIn_over(Goods* head)
{
   Goods* p;
   p = head;
   int state;
   if (dateDiff(p->production_time, p->in_time) > p->quality_time)
   	state = 1;
   else
   	state = 0;//0-商品未過期,1-商品已過期
   return state;
}

//判斷商品在出庫的時間是否過期
int pan_goodsOut_over(Goods* head)
{
   Goods* p;
   p = head;
   int state;
   if (dateDiff(p->production_time, p->out_time) > p->quality_time)
   	state = 1;
   else
   	state = 0;//0-商品未過期,1-商品已過期
   return state;
}

//讀商品檔案
Goods* Read_GoodsFile(FILE* fp)
{
   int i = 1;
   Goods* head = NULL, * newgoods, * p2 = NULL;
   head = (Goods*)malloc(sizeof(Goods));
   
   head->next = NULL;
   while (!feof(fp)) {
   	newgoods = (Goods*)malloc(sizeof(Goods));
   	newgoods->next = NULL;
   	//讀入商品程式碼,商品名稱,商品庫存,商品價格,商品保質期時間,商品入庫數目,商品出庫數目,最終庫存,商品生產日期,商品是否過期標誌,商品庫存是否低於警戒值標誌
   	fscanf(fp, "%d%s%d%d%d%d%d%d%d%d%d%d%d",
   		&newgoods->good_id, newgoods->name, &newgoods->stock, &newgoods->price,
   		&newgoods->quality_time, &newgoods->in_warehouse, &newgoods->out_warehouse, &newgoods->sum_warehouse,
   		&newgoods->production_time.year, &newgoods->production_time.month, &newgoods->production_time.day,
   		&newgoods->state_over, &newgoods->state_warning);
   	if (newgoods->stock <= warning_warehouse) {
   		newgoods->state_warning = 1;
   	}
   	goods_length++;
   	if (i == 1) head->next = newgoods;
   	else p2->next = newgoods;
   	p2 = newgoods; i++;
   }
   return head;
}

//寫商品檔案
void Save_To_GoodsFile(Goods* head)
{
   FILE* fp;
   int num = 0;
   Goods* p;
   p = head->next;
   if ((fp = fopen("goods.txt", "w")) == NULL) {
   	printf("無法開啟資料檔案!\n");
   	return;
   }
   while (p != NULL) {
   	fprintf(fp, "%d %s %d %d %d %d %d %d %d %d %d %d %d\n", 
   		p->good_id, p->name, p->stock, p->price, 
   		p->quality_time, p->in_warehouse, p->out_warehouse, p->sum_warehouse,
   		p->production_time.year, p->production_time.month, p->production_time.day, 
   		p->state_over, p->state_warning);
   	num++;
   	p = p->next;
   }
   fclose(fp);
   printf("儲存結束,共儲存了%d項商品資料!\n", num);
}

//銷燬商品連結串列釋放記憶體
void DestroyGoodsLine(Goods* head)
{
   Goods* p, * q1, * q2;
   p = head;
   q1 = p->next;
   if (q1 == NULL) return;
   q2 = q1->next;
   while (q1->next)
   {
   	free(q1);
   	q1 = q2;
   	q2 = q2->next;
   }
}

//超市倉庫管理系統的設計與實現.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "date.h"
#include "admin.h"
#include "goods.h"
#pragma warning(disable:6031)
#pragma warning(disable:4996)


//主函式
int main()
{
   int choice;
   int admin, password;
   FILE* fp1;
   FILE* fp2;

   fp1 = fopen("goods.txt", "r");
   if (fp1 == NULL) { printf("商品檔案開啟錯誤!\n"); exit(0); }
   fp2 = fopen("admin.txt", "r");
   if (fp2 == NULL) { printf("管理員檔案開啟錯誤!\n"); exit(0); }

   Goods* goods_head = NULL;
   Admin* admin_head = NULL;
   Admin* p = NULL;
   goods_head = Read_GoodsFile(fp1);							//從資料檔案中逐行讀取商品資訊生成商品連結串列
   admin_head = Read_AdminFile(fp2);						    //從資料檔案中逐行讀取管理員資訊生成管理員連結串列

   if (fclose(fp1)) { printf("關閉商品檔案錯誤!\n"); exit(0); }		 //關閉商品檔案
   if (fclose(fp2)) { printf("關閉管理員檔案錯誤!\n"); exit(0); }      //關閉管理員檔案

   while (1)
   {
   	system("cls");													//清屏
   	printf("********************歡迎使用超市倉庫管理系統********************\n");
   	printf("\n");
   	printf("                  1-超級管理員 2-管理員 0-退出                  \n");
   	printf("請選擇您的身份:");
   	scanf("%d", &choice);
   	if (choice == 0) break;
   	getchar();//讀回車符
   	switch (choice)
   	{
   	case 1: {
   		system("cls");
   		printf("********************歡迎使用超市倉庫管理系統********************\n");
   		printf("\n");
   		printf("請輸入賬號:\n");
   		scanf("%d", &admin);
   		printf("請輸入密碼:\n");
   		scanf("%d", &password);
   		if (admin == Super_Admin && password == Super_Password)
   		{
   			system("cls");
   			printf("********************歡迎使用超市倉庫管理系統********************\n");
   			printf("\n");
   			printf("*1-新增管理員           2-刪除管理員           0-退出          *\n");
   			scanf("%d", &choice);
   			if (choice == 0) break;
   			switch (choice)                                                                 
   			{
   			case 1:admin_head = InsertAdmin(admin_head); system("pause"); break;
   			case 2:printf("請輸入要刪除的管理員的賬號:\n"); scanf("%d", &admin); admin_head = DeleteAdmin(admin_head, admin); system("pause"); break;
   			}
   		}
   		else if (admin != Super_Admin) {
   			printf("賬號輸入錯誤!\n");
   			system("pause");
   			break;
   		}
   		else if (password != Super_Password) {
   			printf("密碼輸入錯誤!\n");
   			system("pause");
   			break;
   		}
   		else
   			break;

   	}break;
   	case 2: {
   		system("cls");
   		printf("********************歡迎使用超市倉庫管理系統********************\n");
   		printf("\n");
   		printf("請輸入賬號:\n");
   		scanf("%d", &admin);
   		printf("請輸入密碼:\n");
   		scanf("%d", &password);
   		p = admin_head;
   		choice = 1;
   		while ((p->admin != admin) && (p->password != password)) { p = p->next; }
   		if (p->admin != admin)
   			printf("賬號輸入錯誤!\n");
   		else if (p->password != password)
   			printf("密碼輸入錯誤!\n");
   		else while(choice){
   			system("cls");
   			printf("********************歡迎使用超市倉庫管理系統********************\n");
   			printf("\n");
   			printf("*                                                              *\n");
   			printf("*       1-入庫            2-出庫            3-查詢             *\n");
   			printf("*                                                              *\n");
   			printf("*       4-排序            5-修改            6-統計             *\n");
   			printf("*                                                              *\n");
   			printf("*                         0-退出                               *\n");
   			printf("請輸入你的選擇:\n");
   			scanf("%d", &choice);
   			if (choice == 0) break;
   			switch (choice)
   			{
   			case 1: {
   				system("cls");
   				printf("********************歡迎使用超市倉庫管理系統********************\n");
   				printf("\n");
   				goods_head = In_WareHouse(goods_head); 
   				printf("商品入庫完成!\n");
   			}system("pause"); break;
   			case 2: {
   				system("cls");
   				printf("********************歡迎使用超市倉庫管理系統********************\n");
   				printf("\n");
   				goods_head = Out_WareHouse(goods_head); 
   				printf("商品出庫完成!\n");
   			}system("pause"); break;
   			case 3: {
   				system("cls");
   				printf("********************歡迎使用超市倉庫管理系統********************\n");
   				printf("\n");
   				printf("*1-查詢商品庫存     2-查詢當天入/出庫商品      3-查詢商品保質期*\n");
   				printf("*                                                              *\n");
   				printf("*                          0-退出                              *\n");
   				scanf("%d", &choice);
   				if (choice == 0) break;
   				switch (choice) 
   				{
   				case 1: {
   					system("cls");
   					printf("********************歡迎使用超市倉庫管理系統********************\n");
   					printf("\n");
   					goods_head = GoodsStock_Query(goods_head);
   				}system("pause"); break;
   				case 2: {
   					system("cls");
   					printf("********************歡迎使用超市倉庫管理系統********************\n");
   					printf("\n");
   					goods_head = GoodsInOut_Query(goods_head);
   				}system("pause"); break;
   				case 3: {
   					system("cls");
   					printf("********************歡迎使用超市倉庫管理系統********************\n");
   					printf("\n");
   					GoodsQualityTime(goods_head);
   				}system("pause"); break;
   				default: printf("輸入錯誤!!!\n\n"); break;
   				}
   			}break;
   			case 4: {
   				system("cls");
   				printf("********************歡迎使用超市倉庫管理系統********************\n");
   				printf("\n");
   				Goods_Sort(goods_head);
   				printf("排序完成!\n");
   				GoodsShow(goods_head);
   			}system("pause"); break;
   			case 5: {
   				system("cls");
   				printf("********************歡迎使用超市倉庫管理系統********************\n");
   				printf("\n");
   				goods_head = Goods_Edit(goods_head);
   			}system("pause"); break;
   			case 6: {
   				system("cls");
   				printf("********************歡迎使用超市倉庫管理系統********************\n");
   				printf("\n");
   				GoodsShow(goods_head);
   			}system("pause"); break;
   			default: printf("輸入錯誤!!!\n\n"); break;
   			}

   		}
   	}system("pause"); break;
   	default: printf("輸入錯誤!!!\n\n"); break;
   	}

   }

   Save_To_GoodsFile(goods_head);//將商品資料寫入商品檔案
   DestroyGoodsLine(goods_head);//銷燬商品單連結串列釋放記憶體

   Save_To_AdminFile(admin_head);//將管理員寫入管理員檔案
   DestroyAdminLine(admin_head);//銷燬管理員單連結串列釋放記憶體

   printf("\n\n******************歡迎再次使用超市倉庫管理系統******************\n\n");


   return 0;
}
//admin.txt
222 456
333 789
444 444
//goods.txt
1001 a1 468 200 60 15 30 438 2020 9 1 0 0
1002 a2 123 100 90 16 31 92 2020 9 24 0 0
1003 a3 92 38 30 17 32 60 2020 8 29 1 1
1004 a4 234 48 35 18 33 201 2020 7 26 1 0
1005 a5 789 28 60 19 34 755 2020 1 1 1 0
1006 a6 72 88 60 20 35 37 2020 3 1 1 1
1007 a7 48 8 20 21 36 12 2020 3 2 1 1
1008 a8 101 59 30 22 37 64 2020 5 1 1 0
1009 a9 213 1999 180 23 38 175 2020 6 1 0 0
1010 a10 512 654 30 24 39 473 2020 6 2 1 0
1011 b1 12 5 5 25 20 -8 2020 9 30 1 1
1012 b2 22 7 5 26 41 -19 2020 10 1 1 1
1013 b3 158 6 10 27 42 116 2020 9 1 1 0
1014 b4 352 8 8 28 43 309 2020 9 20 1 0
1015 b5 258 9 30 29 44 214 2020 9 30 0 0
1016 b6 147 10 60 30 45 102 2020 9 28 0 0
1017 b7 369 11 30 31 46 323 2020 9 27 0 0
1018 b8 357 12 30 32 47 310 2020 9 27 0 0
1019 b9 162 13 30 33 48 114 2020 9 27 0 0
1020 b10 263 14 30 34 49 214 2020 9 27 1 0
1021 c1 111 56 35 35 50 61 2020 9 1 1 0
1022 c2 222 23 60 36 51 171 2020 9 1 0 0
1023 c3 333 45 60 37 52 281 2020 9 1 0 0
//stockin.txt
1001 15 2020 10 1 
1002 16 2020 10 1
1003 17 2020 10 1
1004 18 2020 10 1
1005 19 2020 10 1
1006 20 2020 10 1
1007 21 2020 10 1
1008 22 2020 10 1
1009 23 2020 10 1
1010 24 2020 10 1
1011 25 2020 10 2
1012 26 2020 10 2
1013 27 2020 10 2
1014 28 2020 10 2
1015 29 2020 10 2
1016 30 2020 10 2
1017 31 2020 10 2
1018 32 2020 10 2
1019 33 2020 10 2
1020 34 2020 10 2
1021 35 2020 10 3
1022 36 2020 10 3
1023 37 2020 10 3
//stockout.txt
1001 30 2020 10 25
1002 31 2020 10 26
1003 32 2020 10 15
1004 33 2020 10 17
1005 34 2020 10 13
1006 35 2020 10 14
1007 36 2020 10 15
1008 37 2020 10 16
1009 38 2020 10 17
1010 39 2020 10 18
1011 20 2020 10 19
1012 41 2020 10 8
1013 42 2020 10 21
1014 43 2020 10 22
1015 44 2020 10 23
1016 45 2020 10 24
1017 46 2020 10 25
1018 47 2020 10 26
1019 48 2020 10 27
1020 49 2020 10 28
1021 50 2020 10 29
1022 51 2020 10 30
1023 52 2020 10 31

相關文章