销售管理系统_手机销售信息管理系统 c 语言-程序员宅基地

技术标签: 课设  C  c语言  销售系统  链表  

C语言-------销售管理系统

一.需求分析

A.功能需求
很多商品销售机构都需要用到销售管理系统,商品信息包含的字段很多,比如包括:商品编号、商品名称、商品类别(普通电视机、DVD、带DVD的电视机,带DVD的电视机的售价为普通电视机和DVD单价之和的80%)、商品进货价格、商品销售价格、商品数量、供应商名称等。对系统的具体要求如下:
 销售商品信息增删改查。
 销售商品退货管理。
 销售商品进货价格管理。
 销售商品销售价格管理。
 销售商品统计功能。
 销售商品排序(价格)功能。

B.技术要求:
(1)能够运用C语言知识和结构化编程思想,对实际问题进行分析,设计具有一定创新性的实现方案,并能够对相关方案进行筛选;
(2)必须遵守软件工程的相关职业道德和规范,培养良好的编码规范和习惯。例如变量、函数命名必须做到见名知义,代码必须有必要的注释等;
(3)所有的数据存储必须采用文件的形式,可以采用文本文件或者二进制文件;
(4)工程结构尽量采用多文件结构,且文件结构必须合理;
(5)必须采用标准的C语言输入输出;
(6)能够通过相应的软件测试保证所编写代码的质量。

二. 概要设计

⒈ 设计商品信息的抽象数据类型定义:struct woodinfo{}
⒉ 重要的基本函数模块:
基本操作                           操作结果
struct Node* list = NULL;  创建全局链表
struct Node* createHead()   创建表头
struct Node* createNode()   创建节点:为插入做准备
void printList()                      打印链表函数(仓库数据)
void printListSimple()           打印链表函数(商品数据)
void insertNodeByHead()     链表插入函数Push(&S,e)
struct Node* searchByName   指定位置查找
void deleteNodeByData        指定位置删除
void menu()                           菜单模块
void saveInforFormFile        文件存操作
void readInfoFromFile          文件读操作
void bubbleSortList()            冒泡排序法
void keyDown()                    交互模块
int main()                              主函数
⒊ 商品的抽象数据类型定义:
struct woodinfo
{
int num;//商品编号
char name[20];//商品名称
char type[20];//商品种类(DVD)
float inprice;//进价
float outprice;//售价
int many;//数量
char soldmane[20];//供应商
} ;
基本操作:
void saveInforFormFile--------------------------------文件存操作
初始条件:利用FILE函数在程序运行时自动创建出一个woodinfo(商品信息)的文档(.txt),之后在利用链表依次讲链表中的信息填入文档中,并实行保存。
操作结果:输入完毕后,文件夹中会自动生成一个woodinfo(.txt)文件,并存储着链表内信息。

void readInfoFromFile--------------------------------文件读操作
初始条件:已存储在FILE中的数据待读阅。
操作结果:利用遍历的方式依次输出链表中包含的内容,并打印出来。

void bubbleSortList()--------------------------------冒泡排序法
初始条件:利用冒泡排序法的算法对链表中的每件商品的价格进行排序,并储存在FILE文件内,实行实时更新。
操作结果:商品会因价格的高低排序表示出来。

struct Node* searchByName
操作结果:通过遍历自定义结构体中的商品名字进行查找,并将查找的结果反馈到桌面,如果找到则直接显示出商品的相关信息,为找到则输出“未找到该商品!”。

void deleteNodeByData-------------------------------指定位置删除
操作结果:过遍历自定义结构体中的商品名字进行查找,并将查找的结果从链表中删除并将删除后的信息保存于文档中。

三.详细设计

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//自定义结构体(商品信息)
struct woodinfo
{
    
	int num;//商品编号 
	char name[20];//商品名称 
	char type[20];//商品种类(DVD)
	float inprice;//进价 
	float outprice;//售价
	int  many;//数量
	char  soldmane[20];//供应商 
 } ; 
 
struct Node
{
    
	struct woodinfo data;
	struct Node* next;
};
struct Node* list = NULL;//创建全局链表 
//创建表头
struct Node* createHead()
{
    
	//动态内存申请
	struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
	headNode->next = NULL;
	return headNode; 
} 
//创建节点:为插入做准备
struct Node* createNode(struct woodinfo data)
{
    
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
	newNode->data= data;
	newNode->next= NULL;
	return newNode;
}
//打印链表函数(仓库数据)
void printList(struct Node* headNode)
{
    
	struct Node* pMove = headNode->next;
	printf("商品编号\t名称\t类别\t进价\t售价\t数量\t供应商名字:\n");
	while(pMove)
	{
    
		printf("%d\t\t%s\t%s\t%.1f\t%.1f\t%d\t%s\n",pMove->data.num,pMove->data.name,pMove->data.type,pMove->data.inprice,pMove->data.outprice,pMove->data.many,pMove->data.soldmane);
		pMove = pMove->next;
	}
 } 
//打印链表函数(商品数据) 
void printListSimple(struct Node* headNode)
{
    
	struct Node* pMove = headNode->next;
	printf("名称\t类别\t售价\t数量\t供货商\n");
	while(pMove)
	{
    
		printf("%s\t%s\t%.1f\t%d\t%s\n",pMove->data.name,pMove->data.type,pMove->data.outprice,pMove->data.many,pMove->data.soldmane);
		pMove = pMove->next;
	}
 } 
//链表插入函数
void insertNodeByHead(struct Node* headNode,struct woodinfo data)
{
    
	struct Node* newNode = createNode(data);
	newNode->next = headNode->next;
	headNode->next = newNode; 
} 
//指定位置查找
struct Node* searchByName(struct Node* headNode,char* woodname)
{
    
	struct Node* posNode = headNode->next;
	while(posNode!=NULL&&strcmp(posNode->data.name,woodname))
	{
    
		posNode=posNode->next;
	}
	return posNode;
}
 
//指定位置删除
void deleteNodeByData(struct Node* headNode,char *name)
{
    
	struct Node* posLeftNode = headNode;
	struct Node*posNode = headNode->next;
	//商品名称是字符串,字符串比较函数 
	while (posNode !=NULL && strcmp(posNode->data.name,name))
	{
    
		posLeftNode = posNode;
		posNode = posLeftNode->next;
	}
	if(posNode ==NULL)
		return;
	else//删除代码 
	{
    
		printf("删除成功!\n"); 
		posLeftNode->next = posNode->next;
		free(posNode);
		posNode = NULL;
	}
}

//菜单模块
void menu() 
{
    
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	printf("~~~~~~~~~~~~~销售管理系统~~~~~~~~~~~~~~~~~~~\n");
	printf("0.退出销售管理系统\n");
	printf("1.进货\n");
	printf("2.退货\n");
	printf("3.仓库详细信息展示\n");
	printf("4.商品列表\n");
	printf("5.商品列表2.0(按价格高低)\n");
	printf("6.查找商品\n");
	printf("请输入(0~6):");
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
}
//文件存操作
void saveInforFormFile(const char* fileName, struct Node* headNode)
{
    
		FILE* fp = fopen(fileName,"w");
		struct Node* pMove = headNode->next;
		while(pMove !=NULL)
		{
    
			fprintf(fp,"%d\t%s\t%s\t%.1f\t%.1f\t%d\t%s\n",pMove->data.num,pMove->data.name,pMove->data.type,pMove->data.inprice,pMove->data.outprice,pMove->data.many,pMove->data.soldmane); 
			pMove = pMove->next;
		}
		fclose(fp);
} 
//文件读操作
void readInfoFromFile(const char* fileName,struct Node* headNode)
{
    
	FILE* fp=fopen(fileName,"r");//第一次开始无文件创建文件
	if (fp==NULL)//创建文件
	{
    
		fp = fopen(fileName,"w+");
	} 
	struct woodinfo tempdata;
	while(fscanf(fp,"%d\t%s\t%s\t%f\t%f\t%d\t%s",tempdata.num,tempdata.name,tempdata.type,tempdata.inprice,tempdata.outprice,tempdata.many,tempdata.soldmane)!=EOF)
	{
    
		insertNodeByHead(list,tempdata);
	}
	fclose(fp);
	 
 } 
 //冒泡排序法
 void bubbleSortList(struct Node* headNode)
{
    
	for(struct Node* p = headNode->next;p!=NULL;p=p->next)
	{
    
		for(struct Node* q=headNode->next;q->next!=NULL;q=q->next)
		{
    
			if(q->data.outprice>q->next->data.outprice)
			{
    
				//交换值
				struct woodinfo tempdata = q->data; 
				q->data=q->next->data;
				q->next->data=tempdata;
				 
			}
		}
	}
	printListSimple(list); 
} 
//交互模块
void keyDown ()
{
    
	int userKey = 0;
	struct woodinfo tempwood;//产生一个临时的变量存储商品信息 
	struct Node* result =NULL;
	scanf("%d",&userKey);
	switch (userKey)
	{
    
	 case 0:
	 	printf("[退出]\n");
	 	printf("退出成功!\n");
	 	system("pause");
	 	exit(0);
	 	break;
	 case 1:
	 	printf("[进货ing]\n"); 
	 	printf("请依次输入:\n");
	 	printf("商品编号 名称	类别	进价	售价	数量	供应商名字:\n");
		scanf("%d%s%s%f%f%d%s",&tempwood.num,tempwood.name,tempwood.type,&tempwood.inprice,&tempwood.outprice,&tempwood.many,&tempwood.soldmane);
	 	insertNodeByHead(list, tempwood);
	 	saveInforFormFile("woodinfo.txt",list);
		break;
	 case 2:
	 	printf("[退货ing]\n");
	 	printf("请输入需要退货的商品名称:\n");
	 	scanf("%s",tempwood.name);
	 	deleteNodeByData(list,tempwood.name);
	 	saveInforFormFile("woodinfo.txt",list);
	 	printf("退货成功!\n");
		break;
	 case 3:
	 	printf("[仓库详细信息展示]\n");
	 	printList(list);
	 	break;
	 case 4:
	 	printf("[商品列表]\n");
	 	printListSimple(list);
	 	break;
	 case 5:
	    printf("[商品列表2.0(按价格高低)]\n");
	    bubbleSortList(list);
	 	break;	
	 case 6:
	 	printf("[查找商品ing]\n");
	 	printf("请输入需要查找的商品名称:\n");
		scanf("%s",tempwood.name);
		result = searchByName(list,tempwood.name);
		if(result==NULL)
		{
    
			printf("未找到相关商品!\n");
		}
		else
		{
    
			printf("商品编号	名称	类别	进价	售价	数量	供应商名字:\n");
			printf("%d\t\t%s\t%s\t%.1f\t%.1f\t%d\t%s\n",result->data.num,result->data.name,result->data.type,result->data.inprice,result->data.outprice,result->data.many,result->data.soldmane);
		}	
	} 
}

//主函数
int main() 
{
    
	list = createHead();//初始化全局链表 
	readInfoFromFile("woodinfo.txt",list);
	while(1)
	{
    
		menu(); 
		keyDown();
		system("pause");//防止闪屏 
		system("cls");//清屏 
	}
	system("pause");
	return 0;
 }

四.调试分析

⒈. 开始输入代码写为scanf(“%.1f”,&a),发现程序运行到该步骤总是自动退出,最后得知scanf的用法这样用会引起错误,修改为(“%f”),输出格式可以为printf(“%.f”)。

⒉. 自定义函数名在引用该函数时引用名发生错误,导致编译器无法识别,并提示需要定义改该函数,修改后即可正确运行。

⒊. 进行数据输出运用了格式符依旧无法进行数据的对齐,直到在未对齐的数据后多加了了个\t才实现数据的对齐。

⒋.Scanf()输入的%s时不需要取地址符&;

⒌.一开始引用FILE文件时,第一次运行皆正常,而一旦txt内存有数据后,再运行程序时会导致程序无法打开,无法正常运行。多次检测后发现为文档写操作中的fscanf中非字符未加取地址符号&,导致光标无法到达EOF,进入了死循环。重新加入&后,一切正常。

⒍.自定义函数放在了该函数调用的后面,导致从上而下的程序编译时报错显示未声明该函数,将自定义函数放在所有调用函数之前,即可正常编译运行。

五.总结分析

1.采用自定义函数按照模块的方式,一个模块一个模块的逐个针对,使整个程序会显得更加简洁,并会让主函数变得十分简洁,其余的步骤交个各个小函数模块进行操作。
2. 采用链表进行数据的储存可以使文件的删除更加方便,这是链表相较于数组的优越性,同时对于查找删除的操作也是更加方便,无需数组的逐个遍历。
3. 采用File文件对链表中的数据进行存储可以使得程序对于已填入的数据可更加方便的进行后续操作,无需重新输入,并可在原来存储的数据中进行增删查改的操作,使得程序的简便性更加强大。
4. 采用system(“pause”);语句可以防止闪屏,使得程序进行更加流畅;
5. 采用system(“cls”);语句可以在一次交互操作后清空屏幕(但会保留菜单项),使得程序的界面更加简洁明了,便于操作。

六.运行展示

详细信息展示功能:
菜单界面
在这里插入图片描述查找商品演示
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_52381232/article/details/114162863

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法