销售管理系统_手机销售信息管理系统 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

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签