一.题目:

二.参考代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MaxSize 100 //购物车最多存储数量
static int PNum; //商品购买数量
static int PIS; //是否选择该商品
static int i; //循环索引i
//定义购物车商品结构体
typedef struct
{
//1.编号
int BH;
//2.品牌(如"Bvlgari")
char PP[50];
//3.型号(如"BHX0023")
char XH[50];
//4.产品名称(如"Women Bag")
char PName[100];
//5.产品价格
double PPri;
//6.库存量
int PKCNum;
//7.促销(例如"300-40"就是满300减40的优惠)
char CX[50];
} PType;
//定义用来存储购物车里的商品的顺序表
typedef struct
{
//1.用静态数组存放商品,最大容量为MaxSize
PType p[MaxSize];
//2.顺序表当前长度
int length;
}SeqList;
//预定义的产品数据
PType predefinedProducts[] = {
//编号,品牌,型号,产品名称,产品价格,库存量,促销方案
{1, "Bvlgari", "BHX0023", "Women Bag", 112, 100, "0"},
{2, "Chanel", "CHX0023", "Perfume", 42, 100, "0"},
{3, "Armani", "AX0023", "Men Watch", 242, 100, "0"},
{4, "Dior", "DX0023", "Women Watch", 172, 100, "0"},
{5, "OPPO", "OPPOR30", "OPPOR", 144, 100, "300-40"}
};
//初始化购物车顺序表
void InitSeqList(SeqList &L) /*形参为购物车*/
{
/* 不需要对静态数组p做NULL赋值,因为它是固定大小的数组
(L.p=NULL是错误的,因为p是静态数组,不是指针)*/
//1.购物车一开始为空(这一步可以不写)
for(int i=0; i<MaxSize; i++){
L.p[i].BH = 0;
L.p[i].PP[0] = '\0';
L.p[i].XH[0] = '\0';
L.p[i].PName[0] = '\0';
L.p[i].PPri = 0.0;
L.p[i].PKCNum = 0;
L.p[i].CX[0] = '\0';
}
//2.购物车的长度初始化为0(表示空购物车)
L.length = 0;
}
// 添加商品到购物车的函数
/*第一个形参为购物车,第二个形参为商品编号*/
bool InsertSeqList(SeqList &L,int addBH)
{
//1.检查购物车是否已满
if(L.length >= MaxSize)
{
//2.已满
printf("购物车已满,添加失败。 \n");
return false;
}
else
{
//3.未满
printf("购物车有剩余容量,添加成功。 \n");
L.p[L.length]=predefinedProducts[addBH-1];
L.length++;
/*对应编号的商品库存量减1*/
predefinedProducts[addBH-1].PKCNum--;
return true;
}
}
// 解析促销信息,返回满减金额
/*促销的思路就是总金额达到对应商品的满减门槛时,就可以打折*/
int parsePromotion(const char* cx,double totalPri)
{
//1.如果促销信息为"0",则不进行任何处理
if (strcmp(cx, "0") == 0)
{
//意味着没有折扣金额
return 0;
}
//2.此时促销信息不为0,解析"XX-XX"格式的促销信息
int threshold, discount; //threshold记录满减门槛,discount记录减免金额
if (sscanf(cx, "%d-%d", &threshold, &discount) == 2)
{
/*通过sscanf函数把促销信息cx的满减门槛和减免金额依次赋值给threshold、discount,
比如cx为300-40,那么threshold为300,discount为40,现在存了两个数据threshold、discount,sscanf为2*/
//3.如果总金额达到满减门槛threshold,则返回减免金额discount
if (totalPri >= threshold)
{
return discount;
}
}
//4.此时意味着没有达到满减门槛threshold,那么减免金额为0
return 0;
}
//计算最终支付总金额的函数
void finalPri(SeqList L)
{
//1.定义变量记录商品价格总和
double totalPri=0;
//2.求出未处理促销前的总价格
for(i=0;i<L.length;i++) totalPri=totalPri+L.p[i].PPri;
printf("未使用促销下总价格为%.2f元 \n",totalPri);
//3.定义变量
/*定义变量记录总共折扣金额*/
double totalDiscount = 0;
/*定义变量记录子促销信息即每一个商品的促销信息*/
char tempInfo[100];
/*定义变量记录总促销信息即所有商品的促销信息*/
char promotionInfo[100] = "";
/*定义变量记录已使用折扣的商品*/
char appliedProducts[100] = "";
//4.检查购物车中每个商品的促销信息
for (i = 0;i<L.length;i++)
{
//4.1.判断当前商品是否有促销,strcmp不为0意味着有促销
if (strcmp(L.p[i].CX,"0") != 0)
{
//4.2.检查当前商品是否已经应用过折扣
/*strstr函数用于搜索子字符串,此时用来搜索L.p[i].PName是否存在于appliedProducts里,不存在返回NULL*/
if (strstr(appliedProducts,L.p[i].PName) == NULL)
{
//4.3.此时意味着还没有使用过折扣,调用parsePromotion函数得出减免金额
double discount = parsePromotion(L.p[i].CX, totalPri);
if (discount > 0)
{
//4.4.此时意味着可以享受折扣,累加所有满足条件的折扣
totalDiscount += discount;
//4.5.把当前商品的促销信息整理完整
sprintf(tempInfo, "%s (Spend %d, Save %.2f)", //tempInfo存储促销信息
L.p[i].PName,
//第一个%s记录L.p[i].PName即当前可促销商品的名称
atoi(strtok(L.p[i].CX, "-")),
/*先利用strtok函数把促销方案CX切割,
比如促销方案300-40(字符串),这里只调用了一次strtok,且用-切割,
所以只切割出300,再调用atoi函数把字符串300转为整数,
最后把300存入第二个%d*/
discount
//第三个%.2f记录减免金额discount(discount是浮点型,要用%f)
);
//4.6.将当前促销信息追加到总促销信息字符串
strcat(promotionInfo, tempInfo);
//4.7.核心:记录已经打过折的商品,将商品名称添加到已应用折扣的列表
strcat(appliedProducts, L.p[i].PName);
strcat(appliedProducts, "|"); // 使用|作为分隔符
}
}
}
}
//5.打印最终支付价格
/*如果有促销,打印促销信息和最终金额*/
if (totalDiscount > 0)
{
printf("总促销信息为%s。\n", promotionInfo);
printf("可享受总共折扣%.2f元,最终需支付%.2f元。\n", totalDiscount,totalPri - totalDiscount);
}
else
/*此时没有促销*/
{
printf("没有可享受的促销,最终需支付%.2f元。\n",totalPri);
}
}
// 打印购物车内容
void printShoppingCart(SeqList L)
{
//1.判断购物车是否为空
if(L.length==0)
{
printf("购物车为空。\n");
return;
}
//2.此时购物车不为空,开始打印购物车信息
printf("当前购物车信息如下: \n");
for(i=0;i<L.length;i++)
{
printf("编号:%d,品牌:%s,型号:%s,产品名称:%s,产品价格:%.2f,库存量:%d \n",
L.p[i].BH , L.p[i].PP , L.p[i].XH , L.p[i].PName , L.p[i].PPri , predefinedProducts[L.p[i].BH - 1].PKCNum); //注:库存量在全局变量predefinedProducts里
}
//3.调用finalPri函数得出最终支付价格
finalPri(L);
}
//查找指定型号的商品
bool GetXH()
{
//1.定义变量记录商品型号
char name[50];
//2.开始查找
printf("请输入要查找的商品型号:");
scanf("%s",&name);
for(i=0;i<5;i++)
{
if( strcmp(predefinedProducts[i].XH,name)==0 )
{
//意味着查找成功
printf("查找成功 \n");
return true;
}
}
//3.此时查找失败
printf("查找失败 \n");
return false;
}
//删除购物车商品
bool SeqListDelete(SeqList &L)
{
//1.定义变量记录删除哪个商品
int num;
printf("请输入删除第几个商品:");
scanf("%d",&num);
//2.判断是否越界
if(num<1||num>L.length) return false;
//3.此时没有越界
for(i=num;i<L.length;i++)
{
L.p[num-1]=L.p[num];
num++;
}
//4.长度减1
L.length--;
//5.返回
return true;
}
// 计算最符合300-40的商品
void findPri_300_40(SeqList L)
{
if (L.length==0)
{
//1.此时购物车为空,从商品中找到符合总价值为300的最小值
printf("此时购物车为空,'满300减40'活动最优商品组合推荐:");
/*1.1.定义变量记录与目标300最近的差距,初始化为无穷大,因为要找差距更小的*/
int closestDiff=0X7fffffff;
/*1.2.定义变量记录最符合的商品的索引*/
int bestProductIndex = -1;
/*1.3.从已有商品中找最接近300的*/
for (i=0;i<5;i++)
{
//定义变量记录当前商品与300的差距的绝对值
int diff = abs(predefinedProducts[i].PPri-300);
//把当前差距diff与上一次差距closestDiff
if (diff < closestDiff)
{
//此时代表当前离300更近,更新最近差距closestDiff,并记录当前商品索引
closestDiff = diff;
bestProductIndex = i;
}
}
if (bestProductIndex != -1)
{
/*此时代表找到了最接近300的商品*/
printf("此时最接近300元的商品名称为%s,价格为%.2f元,与300元的差距为%.2f元。 \n",
predefinedProducts[bestProductIndex].PName,
predefinedProducts[bestProductIndex].PPri,
closestDiff);
}
else
{
printf("未找到最接近300元的商品.\n");
}
}
else
{
//2.此时购物车有商品,基于当前物品找到最优的商品
printf("此时购物车不为空,寻找适合参加‘满300减40’促销活动的最佳商品 \n");
/*2.1.定义变量记录当前购物车总金额并计算*/
double currentTotal;
for (i=0;i<L.length;i++)
{
currentTotal += L.p[i].PPri;
}
printf("当前购物车商品总额为%.2f元 \n", currentTotal);
/*2.2.如果当前购物车总金额超过300,不需要添加商品*/
if (currentTotal >= 300)
{
printf("当前金额已满足满300减40,无需再凑单啦。\n");
}
/*2.3.当前购物车总金额未超过300,需寻找使总金额最接近300的商品*/
//定义变量记录距离300元还差多少
int targetDiff = 300 - currentTotal;
//定义变量记录距离300最近的差值
int closestDiff = targetDiff;
//定义变量记录距离300最近的商品的索引
int bestProductIndex = -1;
//开始查找符合要求的商品
for (i=0;i<5;i++)
{
// 检查当前处理的商品是否已在购物车中
int alreadyInCart = 0;
for (int j = 0; j < L.length; j++)
{
if (predefinedProducts[i].BH == L.p[j].BH)
{
//此时发现购物车存在当前处理的商品,当前处理的商品停止操作,开始处理下一个商品
alreadyInCart = 1;
break;
}
}
if (!alreadyInCart)
{
//此时意味着当前处理的商品购物车中没有
//定义变量记录当前购物车总金额加上当前处理商品的价格
int newTotal = currentTotal + predefinedProducts[i].PPri;
//定义变量记录与300的差
int diff = abs(newTotal - 300);
if (diff < closestDiff)
{
//此时代表有更接近的差值,更新差值并记录当前处理的商品的索引
closestDiff = diff;
bestProductIndex = i;
}
}
}
if (bestProductIndex != -1)
{
//此时代表找到了更接近300的商品
printf("找到了‘满300减40’促销活动的最佳商品: \n");
printf("该商品的名称为: %s \n", predefinedProducts[bestProductIndex].PName);
printf("该商品的价格为: %.2f元 \n", predefinedProducts[bestProductIndex].PPri);
printf("此时需支付总金额为: %.2f元 \n", currentTotal + predefinedProducts[bestProductIndex].PPri);
printf("距离300差: %d元 \n", closestDiff);
}
else
{
printf("未找到‘满300减40’促销活动的最佳商品。 \n");
}
}
}
int main()
{
//1.定义购物车并初始化
SeqList L;
InitSeqList(L);
//2.购物界面
printf("=================================欢迎来到您的购物车================================= \n");
//3.显示现有商品
printf("可选择的商品如下:\n");
printf("编号,品牌,型号,产品名称,产品价格,库存量,促销方案 \n");
for (int i = 0; i < 5; i++)
{
printf("%d,%s,%s,%s,%.2f,%d,%s \n",
predefinedProducts[i].BH, //编号
predefinedProducts[i].PP, //品牌
predefinedProducts[i].XH, //型号
predefinedProducts[i].PName, //名称
predefinedProducts[i].PPri, //价格
predefinedProducts[i].PKCNum, //库存量
predefinedProducts[i].CX //促销方案
);
}
printf("=================================================================================== \n");
printf("现在有如下选择: \n");
printf("1.生成订单及订单明细表 2.添加购物车商品 \n");
printf("3.删除购物车商品 4.找到价格最接近300-40的商品 \n");
printf("5.查找指定型号的商品 6.退出购物车 \n");
while(true)
{
//开始选择
printf("请输入上述操作的编号:");
int choice;
scanf("%d",&choice);
switch(choice)
{
case 1:
{
printShoppingCart(L);
printf("=================================================================================== \n");
break;
}
case 2:
{
printf("请输入要添加的商品数量:");
scanf("%d",&PNum);
for(int i=0;i<PNum;i++)
{
printf("请输入要添加的商品的编号:");
int addBH; //商品编号
scanf("%d",&addBH);
//判断是否选择该商品
printf("是否选择该商品(1.是;2.不是):");
scanf("%d",&PIS);
if(PIS==2) continue;
else InsertSeqList(L,addBH);
}
printf("=================================================================================== \n");
break;
}
case 3:
{
SeqListDelete(L);
printf("=================================================================================== \n");
break;
}
break;
case 4:
{
findPri_300_40(L);
printf("=================================================================================== \n");
break;
}
case 5:
{
GetXH();
printf("=================================================================================== \n");
break;
}
case 6: exit(0);
}
}
return 0;
}