超市智能商品推荐系统设计

根据客户以往商品选购情况(用户登录后检索以往的商品选购和商品查询情况), 并能根据用户的兴趣爱好自动地推荐给每个用户可能感兴趣的商品,实现具有一种类似采购助手的功能来帮助用户选购商品。提供不少于10个种类,100种商品,并以文件形式存储。
设计用户及商品的信息数据结构,实现如下功能
(1)以文件形式存储用户信息,并以文件形式存储用户的商品选购和查询情况;
(2)设计商品兴趣度简单的数学模型(要求参数有权重【购买 * 2 查询 *1】、或者提供数据模型);
(3)应用排序算法实现商品的排名推荐(及格);
(4)实现商品分类推荐(良好);
(5)实现多用户不同商品兴趣度个性化推荐(优秀)。
要求:
(1)理解及熟练运用内部排序算法;
(2)理解运用数据的分类组织和存储;
(3)理解运用相关查询技术;
(4)界面友好、系统运行应该快速、稳定、高效和可靠。

Commodity.txt:

XpV awT pNk K2S ljs oMP nf6 FaN Hj3 bix
QqB cn1 84r 6zk 0ai QAk iNp hzN IW0 twj
oVM Zr1 Ikl 9PX DiB pYq tah i24 kHQ SqL
XEn Kbf X5Y KsL ZDF S3z TVg QDA 9XP fYt
XpV awT pNk K2S ljs oMP nf6 FaN Hj3 bix
QqB cn1 84r 6zk 0ai QAk iNp hzN IW0 twj
oVM Zr1 Ikl 9PX DiB pYq tah i24 kHQ SqL
XEn Kbf X5Y KsL ZDF S3z TVg QDA 9XP fYt
XpV awT pNk K2S ljs oMP nf6 FaN Hj3 bix
QqB cn1 84r 6zk 0ai QAk iNp hzN IW0 twj

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#include<string.h>

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

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;
    //初始化商品结构体数组
    for ( i = 0; i < 10; i++)   
    {
        for ( j = 0; j < 10; j++)
        {  
            com[i][j].Category = i;
            com[i][j].id  = j;
            strcpy(com[i][j].name,"no");
        }
    }

    //初始化客户结构体变量
    strcpy(customer.id,"no");
    strcpy(customer.password,"no");
    for ( i = 0; i < 10; i++)
    {
        for ( j = 0; j < 10; j++)
        {
            customer.seeCommodity[i][j] = 0;
            customer.buyCommodity[i][j] = 0;
            customer.interCommodity[i][j] = 0.0;
        }
       customer.seeCategory[i] = 0;
       customer.buyCategory[i] = 0;
       customer.interCategory[i] = 0.0;
    }

    //读取商品信息文件
    i = 0;
    fp = fopen("Commodity.txt", "r+");
    while (fscanf(fp, "%s %s %s %s %s %s %s %s %s %s\n",com[i][0].name,com[i][1].name,com[i][2].name,
    com[i][3].name,com[i][4].name,com[i][5].name,
    com[i][6].name,com[i][7].name,com[i][8].name,com[i][9].name) != EOF)//读到文件尾停止
	{
		++i;
	}
}  

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)//如果用户文件存在,即用户非首次登陆
    {
        fscanf(fp,"%s %s ",customer.id,customer.password);	//读取密码到用户结构体变量

        if (strcmp(password,customer.password) == 0)    //如果密码正确
        {
			for (i = 0; i < 10; i++)	//写入查看种类次数
			{
				fscanf(fp, "%d ", &customer.seeCategory[i]);
			}

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

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

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

            fclose(fp);
        }
        else    //如果密码错误
        {
            
            printf("您输入的账号或密码不正确,请重新输入!\n");
            fclose(fp);
            system("pause");
            LogIn(customer);    //未登录成功,递归执行登录操作,直到登录成功为止
            return;
        }
    }
    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("您要购买的商品名称是:%s ,谢谢您的选购!\n",com[category][id].name);

    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");
    for ( i = 0; i < 10; i++)
    {
        printf("类别:%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");
	for (i = 0; i < 3; i++)
	{
		printf("类别:%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请您选择要进行的操作:\n");
    printf("1.购买商品\n");
    printf("2.查看商品\n");
    printf("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;
    }
}