课设背景


随着当代科学社会的不断发展,我们所需要接收和处理的信息越来越多,很多东西逐渐难以通过单纯的人力劳动来解决。在信息过载的时代,由于计算机网络和人工智能的迅猛发展,越来越多的智能化设备、操作系统完成了对单调重复的劳动力的替代,使得众多行业领域的工作效率大大提高。

现在人们的社会需求越来越大,小型超市的规模不断的发展扩大,商品数量和种类也在不断地扩大和增加,和商品有关的商品信息也在不断地成倍增长。超市员工每天不断地记录有关商品的大量信息,工作量非常的大。

然而大型的超市和小型超市的系统之间不能相互通用,大型超市的管理系统由于功能强大操作也变得复杂多变,这样不仅减慢了小型超市员工的操作效率,对于超市人员录用这一方面要求也更加高,加大了超市的成本。超市管理系统是在超市行业里比较流行的管理软件,它主要由以下几个部分组成:用户登录、原始商品信息数据的录入、商品数据的总结和不同信息的查询等。

以往,超市的员工只能通过繁杂单调的手工劳动去记录客户的相关信息,凭借自身的记忆力和语言交谈,去为客户推荐一些商品。这种操作还不易实现,也容易给客户留下不好的印象。因此,超市智能商品推荐系统就显得尤为重要。

它能够联系用户和信息,帮助用户发现对自己有价值的信息,同时让信息能够展现在对它感兴趣的用户面前,从而实现信息消费者和信息生产者的双赢,是一种十分人性化的高效社会经济手段。


系统功能模块组成图及其说明


超市代码java 超市代码解析过度_c++

一个完整的系统,既需要能够独立完整、稳定地实现各项功能,又要做到安全的保存。根据以往实现模块化程序的经验,各个功能的实现不是最大的难题。难点在于如何将各个功能组成一个完整的系统,并实现人机之前的友好交互,这个友好,是指界面的稳定和纯净,不能出现bug,随即消失或者乱码的情况,要能够让人机进行有好的交流。

于是,经过多番的思考,我将流程分为了3大块,第一块是各项信息在文件中的读写初始化,第二块便是核心功能——商品个性化推荐,最后一块便是人机交互功能。为了使得图片更加美观、清晰,层次更加分明,我改变了一下3大块的顺序。

初始化信息模块包括结构体数组、用户登录信息、商品选购和信息查询的初始设定。而核心功能模块则包含了根据用户的购买习惯和历史建立商品兴趣度模型、实现排名推荐、分类推荐和多用户独立的商品个性化推荐。


系统主要数据结构及函数列表


数据结构:内部排序(冒泡排序)
原因:冒泡排序的特点是通过数去找位置,代入到这个系统来说,在建立简单的数学模型之后,能够通过一个权值(商品兴趣度)大小的比较和排序,为每一位客户进行商品的智能化推荐。冒泡排序相对于其他排序来说,比较简单,空间复杂度较低,排序稳定,虽然时间复杂度比较高,效率也比较慢,但是课题要求中的数据量并不大,故而瑕不掩瑜。

函数列表

void Initialize(Commodity[][10],Customer&); //初始化结构体数组
 void LogIn(Customer& customer); //用户登录
 void Recommend(Commodity[][10],Customer&); //冒泡排序实现3类商品推荐
 void Buy(Commodity[][10],Customer&); //用户购买某商品
 void See(Commodity[][10],Customer&); //用户查看某商品
 void Interaction(Commodity[][10],Customer&); //交互界面
 void SaveCustomer(Customer&,FILE *); //用户信息存储


系统7大功能模块详细说明


模块1:信息初始化

一般而言,信息的初始化意味着数据、文字和图像的初始化,信息的初始化是后续工作的必要准备。数据需要一个初始的值和一个限定的浮动范围,也就是说,它需要一个初值,最小上限和最大上限,在编程语言中,这主要体现在数据的定义赋值、数据量大小的设置和数组范围的大小上。

题目要求至少具备10个类别的商品,100种不同的商品。这可以用一个二维数组来实现,定义一个Commodity[10][10]二维数组,一重循环表示类别,二重循环表示每件商品(10*10=100),符合题目的数据量要求。

在初始化商品结构体变量时,便利用了二维数组的存储特性,一重循环实现种类的初始化定义,二重循环实现每件商品编号的初始化定义。并且用strcpy这一字符串复制函数,实现对每件商品名称的初始化定义。在后期进行输入名称时再用字符串函数进行名称覆盖。同理,在后面的Buy函数中,新的类别和编号的输入直接用一个数值进行给原来对应的初始值进行覆盖就行了。

初始化客户结构体变量时,用字符串复制函数对客户的账号(id)和密码(password)进行初始化赋值,以达到初始化界面中有初始数据显示的目的。再同上利用二维数组的存储特性,分别对查看、购买、交互函数中的商品种类和编号进行初始化定义、赋值。在购买函数Buy中便可以根据要求,进行新的赋值。
为了避免数据的类型输入错误,导致程序无法正常运行,必须有合理准确的文字提示。这一点是很容易疏忽的,以前写代码,习惯用行注释来提醒自己,但是在多功能界面的实现中,行注释的效果大打折扣,界面中必须有直接、醒目、精准、合理的文字提示,一方面,方便自己对程序的效果进行检验,对对应的代码块进行定位、修改;另一方面也方便读者在对代码没有太多了解的情况下,也可以进行便捷的操作,十分灵活方便。

由于.cpp文件是需要通过文件进行存储的,因此必须设立一个读取商品信息文件的函数模块, fp = fopen(“Commodity.txt”, “r+”) 实现为了读写,打开一个文本文件。有了可以进行读写的文件之后,还要求能符合要求的进行读写,也就是要能够读到文件尾停止。于是想到了while循环读入语句while(fscanf(fp, “…”) != EOF)在二重循环中实现这一目的,每个i对应10个j,实现10类、100种商品信息的读写。

模块2:用户登录

超市的服务对象就是消费者,也就是客户,为了能够使得超市有更好的信誉,更受客户的欢迎,就必须进行合理创新,努力让客户有更好的购物体验。

而现代社会是一个信息膨胀和消息便达的社会了,不再那么封闭、安全。个人的空间和隐私更加容易受到侵犯。这就使得个人对有关自己隐私和私密空间的事变得十分敏感,如果在这个时候,有人能够在这些方面给予他们安全感,那将会获得对方极大的好感。

因此,隐私的保护变得尤为重要。那么,怎么来解决这个问题呢?我们可以通过设立独立安全的个人账户来保证客户的信息安全,不会外泄,避免造成不必要的困扰、人生安全问题和经济损失。

这个客户登录的模块较为复杂,需要考虑:客户是否是首次登录?首次登录咋么办?非首次登录咋么办?还需要考虑:密码是否正确?正确了如何操作?不正确又如何操作? 经过多番思考、尝试和模拟,我得到了如下可行的解决方案:

首先,为了维护界面,用system(“cls”)进行清屏。分别设立一个id(账号)数组和password(密码)数组来临时存储账号信息。进行下列操作的文字提示并且进行id和password的输入。生成文件名并打开用户文件。

接着,通过if—else语句进行分类处理,最外层的if判断用户文件是否存在,即用户是否是首次登陆。是的话,就读取密码到用户结构体变量。不是的话,为首次使用,就创建用户文件并保存文件。

最后,在上一个if内嵌套一个if—else语句进行分类处理,判断密码是否正确。如果正确,就写入查看种类次数和查看商品次数。如果错误,就进行文字提示,再递归执行登录操作,直到登录成功为止。

模块3:商品选购

对于消费者和商家,在这里就是对客户和超市来说,最重要的一点便是“买卖”俩字。因此,购买商品的过程要遵循一定的规则。

首先要注意到的是,商品选购是一个单独的选购功能分支,需要创建一个新的文本文件方便读和写,还需要清屏,“创建”一个新的界面。

其次,分别按照商品的类别、编号和名称进行输入,记录下商品的各项信息,与前面Initialize的初始化步骤保持一致。每次输入前需要进行文字提示,以免变量类型输入错误,导致程序无法继续正常运行。

在记录用户购买的种类和商品时,将商品的种类和id分别向后移动一位,使得初始的0->1,1->2…9->0,和初始的情况区别开来。

最后,保存用户的购物记录并让界面静止稳定。

模块4:查询情况

为了方便客户了解自己的购物习惯和历史记录,及时查看自己购买的商品信息,需要设立一个单独的查询功能分支,创建一个新的文本文件方便读和写,还还需要清屏,“创建”一个新的界面。

先对购买的商品的种类和编号进行初始化,再分别按照商品的类别、编号和名称进行输入,根据要求进行随机查询。每次输入前需要进行文字提示,以免变量类型输入错误,导致程序无法继续正常运行。

在记录用户购买的种类和商品时,将商品的种类和id分别向后移动一位,使得初始的0->1,1->2…9->0,和初始的情况区别开来。

最后,保存用户的购物记录并让界面静止稳定。

模块5:商品推荐

超市智能商品推荐系统,不言而喻,推荐功能是重中之重,根据要求,需要根据用户购买商品的习惯和历史,设计商品兴趣度简单的数学模型,应用排序算法实现商品的排名推荐,分类推荐,并实现多用户不同商品兴趣度个性化推荐。

有3大点需要考虑,1.用哪一种排序方法进行排序;2.排序之前需要做什么准备;3.排序过程中需要注意什么。对于第1点,由于符合要求的数据量并不大,最大数量级为10^2级,用简单的冒泡排序就可以实现。此外,选择冒泡排序也基于了其他的优点:

首先,建立两个结构体,分别用来临时存储用户喜欢的商品(数组元素大小为101)和用户喜欢的种类(数组元素大小为11),多设一位,防止数组元素溢出。

接着,建立商品兴趣度简单的数学模型(购买的权值为7,查看的权值为3),
在二重循环中计算感兴趣度,第一层循环中计算用户对不同类别的兴趣度,公式: customer.interCategory[i] = (float)( 7.0* customer.buyCategory[i] + 3.0 * customer.seeCategory[i]);第二层循环中计算用户对不同商品的兴趣度, 公式:customer.interCommodity[i][j] = (float)(7.0 customer.buyCommodity[i][j] + 3.0 customer.seeCommodity[i][j]);

最后,应用冒泡排序算法实现商品的排名推荐和分类推荐,但在冒泡排序之前,需要给temCommodity赋值。两次冒泡排序分别进行文字显示提示。

模块6:用户信息存储

为了方便用户了解自己的信息、方便计算机为顾客进行商品个性化推荐,必须先将用户的各项独立信息分别存储,包括账号密码的保存,购物历史和购物习惯的保存。用一个fprintf语句保存账号密码,再分别用for循环语句写入查看和购买的种类次数、商品次数(注意种类是一重循环,商品是二重循环)。

模块7:人机交互界面

各项功能需要一个实现的集合载体——界面,使得人的需要和计算机的回应达到一一对应,并且能够让计算机正确、稳定地显示各项信息。这个界面的稳定性和结构就显得尤为重要。稳定性可以通过每个功能实现后的清屏指令和数据量的最值的设定来保证。

而这个结构的设定着实让人费了一些脑子,本来是想每个模块单独设立一个功能选项,然后人为进行操作选择。但是经过一番思考和权衡之后,结合课设的主题,发现智能推荐才是最重要的核心功能,为了凸显出这一功能,我去除了推荐功能的选项指令,直接在初始界面显示。对于每一个用户,如果尚未购买商品,推荐的商品类别和编号就为初始值,名称为初始单词“no”。

经由一番思考,这个界面的结构是这样的:直接在上方显示商品个性化和分类推荐,再在下方设立其他功能选项,人为进行功能选择。而这一功能选择分支指令就由switch语句来执行,一个选项功能结束后,就进行递归,按任意键回到功能选择界面。


初始化界面图


超市代码java 超市代码解析过度_c++_02


总结与体会


总结:
通过这一次课程设计,我明白了计算机系统的诸多裨益,清晰的了解到了计算机设计的系统在现在科技社会中不可或缺的地位以及重要性,就这一“超市智能商品推荐系统”而言,它有着如下的优势:

①减轻劳动强度、提高工作效率、增加超市市场管理的透明度。超市智能商品推荐系统可以发挥计算机的强大功能,让管理人员从大量繁琐的手工劳动中解放出来,将单调枯燥的纸张涂写变成灵活的电子信息操作。并充分利用网络优势,加快市场内部信息的发布、传送和获取,改善和优化服务工作,使各个部门之间的工作联系紧密、井然有序、清楚明晰,大大减轻工作负担,提高工作效率,增加超市管理的透明度。

②降低管理成本,由于采用本系统的原因,使相关人员的管理工作一改往日埋在各种表格中的被动局面,基本实现了无纸化办公,根除了很多日常管理中的浪费现象,体现出现代化超市管理的优势。

③规范化管理,由于采用了计算机统计分析客户信息,一些原始信息在录入时就必须要求准确录入,这就要求管理人员在提供信息时要准确,同时要求在录入时也要十分认真,这样做是为了将错误降到最低,提高系统工作的准确率,从而实现学生管理工作规范化。

体会:
在这一课程的实践操作中,模块化程序之间的联系显得尤为重要,一个完整的系统,各个模块之间要相互承接,它们之间既不能出现数据的误差,也不能出现语法的错误,否则很容易导致整个系统程序瘫痪,它们需要在相互协调的同时,共同为系统服务。这就需要我有分化处理与结合处理的能力,心怀纵观全局的理念,着眼于每个模块的细节,对人的耐心和能力的考验是极其之大,充分体现了这一课程设计对于学生综合能力的考核与提高。

而这一报告书是对这一产品的直接说明与形象体现,为我们日后想公司和客户进行产品说明做了很好的铺垫,打下了良好的基础。

最难之出并不在于代码的调试和图文的结合说明,虽然很多程序在写完之后很容易出现问题,运行时会遇到各种各样、五花八门的错误,需要细心、耐心的品质与强大的代码能力和扎实的基础功底,在图文说明的思路方面也要下很多心思去构造。

但是更难的是成果的叙述和价值的呈现。这个过程可谓用心良苦,精益求精啊,为了能让读者有更好的体验,符合自我的不懈追求,我经历了无数次的失败,并从中吸取了教训,汲取了经验,在老师的指导下,一步步地将自己的努力和成果的价值更好地呈现了出来。

最后,这一课程设计真的让我受益颇多,让我在辛苦劳碌和不断的尝试、调试和修改之中,实现了知识的迁移与应用,强化了自己的综合技能,开拓了自己的视野,促进了交流。


代码


#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;


struct Commodity	//商品结构体
{
    int Category;   //商品的种类
    int id; //商品id
    char name[12];    //商品名称
};

struct Customer	//用户结构体
{
    char id[10];    //用户ID
    char password[10];   //用户密码
    int seeCategory[10];    //记录用户查看种类次数
    int buyCategory[10];    //记录用户购买种类次数
    int seeCommodity[10][10];   //记录用户查看商品的次数
    int buyCommodity[10][10];   //记录用户购买商品的次数
    float interCategory[10];    //记录用户对种类的感兴趣度
    float interCommodity[10][10];   //记录用户对商品感兴趣度
};

void Initialize(Commodity[][10],Customer&); //初始化结构体数组
void LogIn(Customer& customer);   //用户登录
void Recommend(Commodity[][10],Customer&);   //推荐商品
void Buy(Commodity[][10],Customer&); //用户购买某商品
void See(Commodity[][10],Customer&); //用户查看某商品
void Interaction(Commodity[][10],Customer&); //交互界面
void SaveCustomer(Customer&,FILE *);    //用户信息存储

char pathName[20];	//存储用户文件
int main()
{   
    Commodity com[10][10];//假设一共10类商品,每类有10个商品
    Customer customer; //用户
    Initialize(com,customer);	//初始化 
    LogIn(customer);	//登录
    Interaction(com,customer);	//人机交互界面
    system("pause");
    return 0;
}

void Initialize(Commodity com[10][10],Customer& customer)//初始化结构体数组
{
    int i ,j;
    FILE * fp;
    //初始化商品结构体数组

    //初始化客户结构体变量
    
    //读取商品信息文件
   
}  

void LogIn(Customer& customer)
{
    system("cls");//清屏
    int i,j;
    char id[10],password[10];	//临时存储输入的账号密码
    FILE * fp;

    printf("初始化输入的ID和密码:\n");
    scanf("%s",id);
    scanf("%s",password);
    strcpy(pathName,id);
    strcat(pathName,".txt");//生成文件名
    fp = fopen(pathName,"r+");//打开用户文件

    if (fp)//如果用户文件存在,即用户非首次登陆
    {
       //...
    }
    else    //如果为首次使用,创建用户文件
    {
        fp = fopen(pathName,"w+");
		strcpy(customer.id,id);	
		strcpy(customer.password, password);
        SaveCustomer(customer,fp);	//保存文件
        fclose(fp);
    }
    
} 

void Buy(Commodity com[10][10],Customer& customer)
{
	FILE* fp = NULL;
	int category = 0, id = 0;

	fp = fopen(pathName,"w+");
	system("cls");

    
    printf("请输入您要购买的商品的类别:\n");
        scanf("%d",&category);
    printf("请输入您要购买的商品的编号:\n");   
        scanf("%d",&id);
    printf("请输入您要购买的商品的名称:\n");
        cin>>com[category][id].name;
    printf("谢谢您的选购!\n");

    customer.buyCategory[category] += 1;   //记录用户购买的种类
    customer.buyCommodity[category][id] += 1;   //记录用户购买的商品
	SaveCustomer(customer, fp);	//保存用户的购物记录
    system("pause");
} 

void See(Commodity com[10][10],Customer& customer)
{
	system("cls");
	FILE* fp = NULL;
	int category = 0, id = 0;

	fp = fopen(pathName, "w+");
    
    printf("请输入您要查看的商品的类别:\n");
        scanf("%d",&category);
    printf("请输入您要查看的商品的编号:\n");   
        scanf("%d",&id);
    printf("您要查看的商品名称是:%s。\n",com[category][id].name);

    customer.seeCategory[category] += 1;   //记录用户查看的种类
    customer.seeCommodity[category][id] += 1;   //记录用户查看的商品
	SaveCustomer(customer,fp);	//保存用户浏览记录
    system("pause");
} 

void Recommend(Commodity commodity[10][10],Customer&customer)
{
  int i, j, m = 0;
  struct		//临时存储用户喜欢的商品
  {
      int category;
      int id;
      float interCommodity;
  } temCommodity[101];
  struct		//临时存储用户喜欢的种类
  {
	  int category;
	  float interCategory;
  }temCategory[11];
  
    //计算感兴趣度。购买的权值为7,查看的权值为3
    for ( i = 0; i < 10; i++)
    {
        for ( j = 0; j < 10; j++)
        {
            customer.interCommodity[i][j] = (float)(7.0 * customer.buyCommodity[i][j] + 3.0* customer.seeCommodity[i][j]);
        }
            customer.interCategory[i] = (float)( 7.0* customer.buyCategory[i] + 3.0 *customer.seeCategory[i]);
    }

   /**************************************应用冒泡排序算法实现商品的排名推荐**************************************************************/
    for ( i = 0; i < 10; i++)	//给temCommodity赋值
    {
        for ( j = 0; j < 10; j++)
        {
            temCommodity[m].category = i;
            temCommodity[m].id = j;
            temCommodity[m].interCommodity =  customer.interCommodity[i][j];
            m++;
        }
    }

    for ( i = 0; i < 100 - 1; i++)	//冒泡排序,商品排名推荐
    {
        for ( j = 0; j < 100 - 1 -i; j++)
        {
            if (temCommodity[j + 1].interCommodity  > temCommodity[j].interCommodity)
            {
                temCommodity[100]  = temCommodity[j+1];
                temCommodity[j +1] = temCommodity[j];
                temCommodity[j] = temCommodity[100];
            }
        }
    }
    
    printf("\n\n");
    printf("\t \t \t      根据您的购物习惯和购物历史,小旭竭诚为您推荐以下商品:     \n");
    printf("\n");
    for ( i = 0; i < 10; i++)
    {
        printf("\t \t \t             ******<  类别:%d,编号: %d,名字:%s  >******\n",commodity[temCommodity[i].category][temCommodity[i].id].Category, commodity[temCommodity[i].category][temCommodity[i].id].id, commodity[temCommodity[i].category][temCommodity[i].id].name);
    }

	/*******************************************实现商品分类推荐***********************************************************/
	for (i = 0; i < 10; i++)//给temCategory赋值
	{
		temCategory[i].category = i;
		temCategory[i].interCategory = customer.interCategory[i];
	}

	for ( i = 0; i < 10 - 1; i++)		//冒泡法排序,实现商品分类推荐
	{
		for (j = 0; j< 10 - 1 -i; j++) 
		{
			if (temCategory[j + 1].interCategory > temCategory[j].interCategory)
			{
				temCategory[10] = temCategory[j];
				temCategory[j] = temCategory[j + 1];
				temCategory[j + 1] = temCategory[10];
			}
		}
	}
    
    printf("\n\n");
	printf("\t \t \t    根据您的购物习惯和购物历史,小旭竭诚为您推荐以下类别商品:\n\n");
	for (i = 0; i < 3; i++)
	{
		printf("\t\t\t\t\t    ******<  类别:%d  >******\n", temCategory[i].category);
	}

}

void SaveCustomer(Customer&customer,FILE *fp)
{
    int i, j;
    fprintf(fp,"%s %s ",customer.id,customer.password);	//保存账号密码

    for ( i = 0; i < 10; i++)	//写入查看种类次数
    {
        fprintf(fp, "%d ", customer.seeCategory[i]);
    }

    for (i = 0; i < 10; i++)	//写入购买种类次数
    {
        fprintf(fp, "%d ", customer.buyCategory[i]);
    }

    for ( i = 0; i < 10; i++)	//写入查看商品次数
    {
        for ( j = 0; j < 10; j++)
        {
            fprintf(fp, "%d ",customer.seeCommodity[i][j]);
        }
    }
    
    for (i = 0; i < 10; i++)	//写入购买商品次数
    {
        for (j = 0; j < 10; j++)
        {
            fprintf(fp, "%d ", customer.buyCommodity[i][j]);
        }
    }
}

void Interaction(Commodity com[10][10],Customer&customer)   //人机交互界面
{   int n;
    system("cls");
    Recommend(com,customer);	//推荐商品

    printf("\n\n\t\t\t\t\t       请您选择要进行的操作:\n\n");
    printf("\t\t\t\t\t\t    1.购买商品\n");
    printf("\t\t\t\t\t\t    2.查看商品\n");
    printf("\t\t\t\t\t\t    3.退出\n");
    scanf("%d",&n);

    switch (n)
    {
    case 1:
        Buy(com,customer);		//购买
        Interaction(com,customer);		//递归
        break;
    case 2:
        See(com,customer);	//购买
        Interaction(com,customer);	//递归
        break;

    case 3:
        exit(0);	//退出
        break; 
    
    default:
        Interaction(com,customer);	//递归
        break;
    }
}