17.2 修改购物车商品

17.2 修改购物车商品

问题分析

  1. 同样要分为登录和未登录两种状态分别处理。
  2. 要处理商品数据的变化及勾选状态的变化,还有商品总金额的变化 (在前端实现)。
  3. 若已登录,则需要覆盖redis中的数据。若未登录,则需要覆盖COOKIE中的数据。

设计

因只是对购物车中的商品数据进行修改,所以请求方式为put。

需要更新的数据为sku_id,count , selected几个参数。

实现

在carts应用下定义constants.py,存放常量

CARTS_COOKIE_EXPIRES = 3600 * 24 * 14  # 两周

carts应用下views.py中增加put方法,修改后的全部代码如下

import base64
import json
import pickle

from django.conf import settings
from django.http import HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from carts import constants
from goods.models import SKU
from xiaoyu_mall_new.utils.response_code import RETCODE


class CartsView(View):

    def put(self, request):
        # 接收参数
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected')

        # 校验参数
        if not all([sku_id, count]):
            return HttpResponseForbidden('缺少必须的参数')

        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return HttpResponseForbidden('商品sku_id不存在')

        try:
            count = int(count)
        except Exception:
            return HttpResponseForbidden('参数count有误')

        if selected:
            if not isinstance(selected, bool):
                return HttpResponseForbidden('参数selected 有误')

        user = request.user
        if user.is_authenticated:
            # 登录状态
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            pl.hset('carts_%s' % user.id, sku_id)
            if selected:
                pl.sadd('selected_%s' % user.id, sku_id)
            else:
                pl.srem('selected_%s' % user.id, sku_id)

            pl.execute()

            # 创建响应
            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'price': sku.price,
                'amount': sku.price * count,
                'stock': sku.stock,
                'default_image_url': settings.STATIC_URL + 'images/goods/' + sku.default_image.url + '.jpg',
            }
            return JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车成功', 'cart_sku': cart_sku})
        else:
            # 未登录 状态
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart_dict = {}

            cart_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            cookie_cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'price': sku.price,
                'amount': sku.price * count,
                'stock': sku.stock,
                'default_image_url': settings.STATIC_URL + 'images/goods/' + sku.default_image.url + '.jpg',
            }

            response = JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车成功', 'cart_sku': cart_sku})
            response.set_cookie('carts', cookie_cart_str, max_age=constants.CARTS_COOKIE_EXPIRES)
            return response

    def get(self, request):
        # 判断用户是否登录
        user = request.user
        if user.is_authenticated:
            # 创建连接到redis的对象
            redis_conn = get_redis_connection('carts')
            # 查询user_id、count与sku_id构成的购物车记录
            redis_cart = redis_conn.hgetall('carts_%s' % user.id)
            # 查询勾选的商品smembers 命令返回集合中的所有的成员
            redis_selected = redis_conn.smembers('selected_%s' % user.id)
            cart_dict = {}
            for sku_id, count in redis_cart.items():
                cart_dict[int(sku_id)] = {
                    "count": int(count),
                    "selected": sku_id in redis_selected
                }
        else:
            # 用户未登录,查询cookies购物车
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                # 对 cart_str进行编码,获取字节类型的数据
                cart_str_bytes = cart_str.encode()
                # 对cart_str_bytes进行解码,获取明文数据
                cart_dict_bytes = base64.b64decode(cart_str_bytes)
                # 对cart_dict_bytes反序列化,转换成Python能识别的字典类型的数据
                cart_dict = pickle.loads(cart_dict_bytes)
            else:
                cart_dict = {}
        # 构造响应数据
        sku_ids = cart_dict.keys()
        # 一次性查询出所有的skus
        skus = SKU.objects.filter(id__in=sku_ids)
        cart_skus = []
        for sku in skus:
            cart_skus.append({
                'id': sku.id,
                'count': cart_dict.get(sku.id).get('count'),
                # 将True,转'True',方便json解析
                'selected': str(cart_dict.get(sku.id).get('selected')),
                'name': sku.name,
                'default_image_url': settings.STATIC_URL +
                                     'images/goods/' + sku.default_image.url + '.jpg',
                'price': str(sku.price),
                'amount': str(sku.price * cart_dict.get(sku.id).get('count')),
                'stock': sku.stock
            })
        context = {
            'cart_skus': cart_skus
        }
        # 渲染购物车页面
        return render(request, 'cart.html', context)

    def post(self, request):
        # 将JSON格式的字符串反序列化为Python对象
        json_dict = json.loads(request.body.decode())
        # 接收参数
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected', True)

        # 校验参数
        if not all([sku_id, count]):
            return HttpResponseForbidden('缺少必要参数')

        # 校验sku_id参数
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return HttpResponseForbidden('参数sku_id错误')
        # 校验count参数
        try:
            count = int(count)
        except Exception:
            return HttpResponseForbidden('参数count错误')

        # 校验selected参数
        if selected:
            if not isinstance(selected, bool):
                return HttpResponseForbidden('参数selected错误')

        # 判断用户是否登录
        user = request.user
        # 已登录,数据格式为:
        # carts_user_id:{sku_id1:count1,sku_id2:count2,...}
        # selected_user_id:{sku_id1,sku_id2,...}
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            # 创建管道,用于执行多个命令
            pl = redis_conn.pipeline()
            # 以增量形式保存商品数据
            # - 'carts_%s' % user.id :生成以用户ID为后缀的购物车键名(如 carts_123 )
            # - sku_id :商品SKU的唯一标识,作为哈希表的字段名
            # - count :要增加的数量(可为正数或负数)
            pl.hincrby('carts_%s' % user.id, sku_id, count)
            # 保存商品的勾选状态
            if selected:
                # 若selected为True,将sku_id添加到selected集合中
                pl.sadd('selected_%s' % user.id, sku_id)

            # 执行管道命令
            pl.execute()
            return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
        else:  # 未登录,购物车数据存储在cookie中,数据结构如下
            # cart_dict = {
            #     'sku_id1': {'count': 5, 'selected': 'True'},
            #     'sku_id2': {'count': 3, 'selected': 'False'}
            # ...
            # }
            cart_str = request.COOKIES.get('carts')
            # 若购物车数据存在,将其反序列化为字典
            if cart_str:
                # 对cart_str进行编码,获取字节类型数据
                cart_str_bytes = cart_str.encode()
                # 对密文类型数据cart_str_bytes进行base64解码,获取明文数据
                cart_dict_bytes = base64.b64decode(cart_str_bytes)
                # 对明文类型数据cart_dict_bytes进行反序列化,获取字典类型数据
                cart_dict = pickle.loads(cart_dict_bytes)
            # 若没有数据,创建空字典
            else:
                cart_dict = {}
            # 若购物车数据中已存在该商品,累加数量
            if sku_id in cart_dict:
                origin_count = cart_dict[sku_id]['count']
                count += origin_count
            cart_dict[sku_id] = {'count': count, 'selected': selected}
            # 对字典类型数据cart_dict进行序列化,获取字节类型数据
            cart_dict_bytes = pickle.dumps(cart_dict)
            # 对字节类型数据cart_dict_bytes进行base64编码,获取密文类型数据
            cart_str_bytes = base64.b64encode(cart_dict_bytes)
            # 对密文类型数据cart_str_bytes进行解码,获取明文类型数据
            cookie_cart_str = cart_str_bytes.decode()

            response = JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
            response.set_cookie('carts', cookie_cart_str)
            # 响应结果
            return response

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define NUM 10 typedef struct item { char brand[20];//商品名字 char id[10];//商品编号 float in_price;//进价 float out_price;//售价 int storage;//商品数量 }item; item goods[NUM]; //购物车类型 typedef struct item_node { item wanted;//商品 int amount;//购物数量 struct item_node* next; } item_node; item_node* cart; void clear_input_buffer() { int c; while ((c = getchar()) != '\n' && c != EOF); } //主菜单 int menu() { int select; printf("请选择数字进行操作:\n"); printf("1.建立库存信息\n"); printf("2.显示库存信息\n"); printf("3.购物车\n"); printf("4.结算\n"); printf("5.进货管理\n"); printf("6.营收统计\n"); printf("7.货物清理\n"); printf("8.退出\n"); printf("请选择对应数字(1-8):\n"); while (1) { scanf("%d", &select); if (select < 1 || select>8) { printf("输入错误,请重新输入\n"); } else { break; } } return select; } //建立库存信息 void establish() { FILE* fp;//创建指向文件的指针 printf("请依次输入货物信息(库存货物种类为10):\n"); printf("------------------------\n"); //初始化商品信息 for (int i = 0; i < NUM; i++) { printf("商品名称:"); fflush(stdin); scanf("%s", goods[i].brand); printf("商品编号:"); fflush(stdin); scanf("%s", goods[i].id); printf("商品进价:"); fflush(stdin); scanf("%f", &goods[i].in_price); printf("商品售价:"); fflush(stdin); scanf("%f", &goods[i].out_price); printf("商品数量:"); fflush(stdin); scanf("%d", &goods[i].storage); printf("\n"); printf("是否还要添加货物种类:(Y/N)"); clear_input_buffer(); char g = getchar(); if (g == 'n' || g == 'N') { break; } else { continue; } } if ((fp = fopen("goods", "w")) == NULL) { printf("创建文件失败\n"); } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } //显示库存信息 void dis_all() { //清空前面显示的内容 system("cls"); FILE* fp; fp = fopen("goods", "r"); for (int i = 0; (fread(goods + i, sizeof(item), 1, fp) != 0); i++) { printf("----------------------------------------------------------\n"); printf("商品编号\t商品名称\t商品单价\t库存数量\n"); printf("----------------------------------------------------------\n"); printf("%s%18s%17.2f%17d\n", goods[i].id, goods[i].brand, goods[i].out_price, goods[i].storage); } } //购物车菜单 int cart_menu() { int select; printf("------------------\n"); printf("1.显示当前购物列表\n"); printf("2.添加商品\n"); printf("3.退出\n"); printf("------------------\n"); printf("请选择操作:\n"); while (1) { scanf("%d", &select); if (select < 1 || select>3) { printf("输入错误,请重新输入\n"); } else { break; } } return select; } //购物车添加商品 void add() { FILE* fp; char str[20];//获取物品名字/编号的字符串 int n; int i; char choice, choice2; item_node* p1, * p; do { printf("输入所需物品的名称或编号:\n"); fflush(stdin); scanf("%s", str); if ((fp = fopen("goods", "r")) == NULL) { printf("打开文件失败!\n"); continue; } for (i = 0; fread(goods + i, sizeof(item), 1, fp) != 0; i++) { if ((strcmp(goods[i].brand, str) == 0 || strcmp(goods[i].id, str) == 0) && goods[i].storage != 0) { printf("已经找到所需物品:\n"); printf("----------------------------------------------------------\n"); printf("商品编号\t商品名称\t商品单价\t库存数量\n"); printf("----------------------------------------------------------\n"); printf("%s%18s%17.2f%17d\n", goods[i].id, goods[i].brand, goods[i].out_price, goods[i].storage); printf("请输入所需要数量:\n"); clear_input_buffer();// 清除缓冲区 if (scanf("%d", &n) != 1) { printf("输入错误,请输入数字!\n"); n = 0; // 防止未初始化值 clear_input_buffer(); break; } if (n > goods[i].storage) { printf("库存不足\n"); break; } printf("是否购买?(Y/N)\n"); clear_input_buffer(); choice = getchar(); if (choice == 'Y' || choice == 'y') { p1 = (item_node*)malloc(sizeof(item_node)); if (p1 == NULL) { printf("内存申请失败!\n"); exit(1); } p1->amount = n;//存入需要购物商品数量 p1->wanted = goods[i]; p1->next = NULL; p = cart; if (cart == NULL) cart = p1; else { while (p->next != NULL) p = p->next; p1->next = p->next; p->next = p1; } } break; } } if (i == NUM) { printf("未找到所需物品\n"); } fclose(fp); printf("是否继续购物?(Y/N)"); clear_input_buffer(); choice2 = getchar(); } while (choice2 == 'Y' || choice2 == 'y'); } //显示购物列表 void display() { system("cls"); item_node* p = cart; if (p == NULL) { printf("购物车为空!\n"); return; } while (p != NULL) { printf("----------------------------------------------------------\n"); printf("商品编号\t商品名称\t商品单价\t购买数量\n"); printf("----------------------------------------------------------\n"); printf("%s%18s%17.2f%17d\n\n", p->wanted.id, p->wanted.brand, p->wanted.out_price, p->amount); p = p->next; } } //购物车 void shop_car() { system("cls"); while (1) { switch (cart_menu()) { //显示当前购物列表 case 1: display(); break; //添加商品 case 2: add(); break; //退出购物车 case 3: return; break; } } } //结算功能实现 void calculate() { system("cls"); float total = 0, pay; item_node* p; FILE* fp; printf("以下是购物清单:\n"); display();//显示购物车的内容 if ((fp = fopen("goods", "r")) == NULL) { printf("文件打开失败!\n"); return; } for (int i = 0; (fread(goods + i, sizeof(item), 1, fp)) != 0; i++); fclose(fp); p = cart; while (p != NULL) { total += p->wanted.out_price * p->amount; for (int i = 0; strcmp(goods[i].id, p->wanted.id) != 0; i++) goods[i].storage -= p->amount; p = p->next; } printf("总计:%7.2f", total); printf("\n输入支付金额:"); scanf("%f", &pay); printf("\n实际支付:%7.2f\t\t找零:%7.2f\n", pay, pay - total); if ((fp = fopen("goods", "w")) == NULL) { printf("文件读取打开失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); FILE* log_fp = fopen("sales_log.txt", "a"); // 以追加方式打开日志文件 if (log_fp == NULL) { printf("无法打开日志文件。\n"); } else { time_t t = time(NULL); struct tm* tm_info = localtime(&t); char buffer[80]; strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", tm_info); fprintf(log_fp, "=== 结算时间:%s ===\n", buffer); p = cart; while (p != NULL) { fprintf(log_fp, "商品名称:%s\t售价:%.2f\t进价:%.2f\t数量:%d\n", p->wanted.brand, p->wanted.out_price, p->wanted.in_price, p->amount); p = p->next; } fprintf(log_fp, "总计:%.2f 元\n", total); fprintf(log_fp, "===============================\n"); fclose(log_fp); } } // 进货管理 - 支持添加新商品 void stock_in() { FILE* fp; char str[20]; // 获取物品名字/编号的字符串 int n; // 进货或新增数量 int i; char choice; printf("请输入要进货的商品名称或编号:\n"); clear_input_buffer(); scanf("%s", str); if ((fp = fopen("goods", "r")) == NULL) { printf("打开文件失败!\n"); return; } // 读取所有商品信息到 goods 数组中 for (i = 0; fread(goods + i, sizeof(item), 1, fp) != 0; i++); fclose(fp); // 查找匹配的商品 for (i = 0; i < NUM; i++) { if (strcmp(goods[i].brand, str) == 0 || strcmp(goods[i].id, str) == 0) { // 找到已有商品 printf("找到商品:%s %s\n", goods[i].id, goods[i].brand); printf("当前库存数量:%d\n", goods[i].storage); printf("请输入进货数量:\n"); clear_input_buffer(); if (scanf("%d", &n) != 1 || n <= 0) { printf("输入错误,请输入正整数!\n"); clear_input_buffer(); return; } printf("确认进货 %d 个 %s?(Y/N)\n", n, goods[i].brand); clear_input_buffer(); choice = getchar(); if (choice == 'Y' || choice == 'y') { goods[i].storage += n; // 增加库存数量 printf("进货成功!新的库存数量:%d\n", goods[i].storage); // 将更新后的商品信息写入文件 if ((fp = fopen("goods", "w")) == NULL) { printf("文件写入失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } else { printf("取消进货。\n"); } return; } } // 没有找到该商品,提示是否作为新商品添加 printf("未找到该商品,是否添加为新商品?(Y/N)\n"); clear_input_buffer(); choice = getchar(); if (choice == 'Y' || choice == 'y') { // 寻找空位插入新商品 for (i = 0; i < NUM; i++) { if (goods[i].storage == 0 && strlen(goods[i].brand) == 0) break; } if (i >= NUM) { printf("库存已满,无法添加新商品。\n"); return; } item new_item; printf("请输入新商品的信息:\n"); printf("商品名称: "); scanf("%s", new_item.brand); printf("商品编号: "); scanf("%s", new_item.id); printf("商品进价: "); scanf("%f", &new_item.in_price); printf("商品售价: "); scanf("%f", &new_item.out_price); printf("进货数量: "); if (scanf("%d", &n) != 1 || n <= 0) { printf("输入错误,请输入正整数!\n"); return; } new_item.storage = n; goods[i] = new_item; // 写回文件 if ((fp = fopen("goods", "w")) == NULL) { printf("文件写入失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); printf("新商品已添加成功!\n"); } else { printf("操作已取消。\n"); } } // 营收统计 (从销售日志中提取数据) void revenue() { system("cls"); FILE* fp = fopen("sales_log.txt", "r"); if (!fp) { printf("没有找到销售日志文件。\n"); return; } char line[256]; float total_sales = 0.0f, total_cost = 0.0f; // 用于存储当前交易的时间 char current_time[80] = ""; while (fgets(line, sizeof(line), fp)) { // 如果匹配到时间行 if (strncmp(line, "===", 3) == 0 && strstr(line, "结算时间:")) { sscanf(line, "=== 结算时间:%79[^ ] ===", current_time); // 提取时间 } // 如果匹配到商品行 else if (strstr(line, "商品名称:")) { char name[50]; float out_price, in_price; int amount; sscanf(line, "商品名称:%[^ ] 售价:%f 进价:%f 数量:%d", name, &out_price, &in_price, &amount); float sales = out_price * amount; float cost = in_price * amount; total_sales += sales; total_cost += cost; // 显示每条记录及其时间 printf("时间:%s\n", current_time); printf("商品名称:%s\t售价:%.2f\t进价:%.2f\t数量:%d\n", name, out_price, in_price, amount); printf("销售收入:%.2f 元\t商品利润:%.2f 元\n\n", sales, sales - cost); } } fclose(fp); printf("=== 销售营收报告(来自日志) ===\n"); printf("总销售额:%.2f 元\n", total_sales); printf("总成本:%.2f 元\n", total_cost); printf("总利润:%.2f 元\n", total_sales - total_cost); } // 删除商品函数(紧凑库存) void delete_item() { FILE* fp; char str[20]; // 存储用户输入的名称或编号 int i, j; printf("请输入要删除的商品名称或编号:\n"); clear_input_buffer(); scanf("%s", str); // 打开文件读取库存数据 if ((fp = fopen("goods", "r")) == NULL) { printf("打开文件失败!\n"); return; } // 从文件中读取所有商品信息到 goods 数组 for (i = 0; fread(goods + i, sizeof(item), 1, fp) != 0; i++); fclose(fp); // 遍历数组查找匹配的商品 for (i = 0; i < NUM; i++) { if (strcmp(goods[i].brand, str) == 0 || strcmp(goods[i].id, str) == 0) { printf("找到商品:%s %s\n", goods[i].id, goods[i].brand); printf("确认删除?(Y/N)\n"); clear_input_buffer(); char choice = getchar(); if (choice == 'Y' || choice == 'y') { // 将后面的商品前移一位 for (j = i; j < NUM - 1; j++) { goods[j] = goods[j + 1]; } // 最后一个位置清空 memset(&goods[NUM - 1], 0, sizeof(item)); printf("商品已成功删除,库存已紧凑。\n"); // 将更新后的库存写回文件 if ((fp = fopen("goods", "w")) == NULL) { printf("文件写入失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } else { printf("取消删除。\n"); } return; } } // 没有找到匹配的商品 printf("未找到该商品。\n"); } int main() { int select; printf("**********************\n"); printf("*欢迎使用超市管理系统*\n"); printf("**********************\n"); while (1) { switch (menu()) { //建立库存信息 case 1: establish(); break; //显示库存信息 case 2: dis_all(); break; //购物车 case 3: shop_car(); break; //结算 case 4: calculate(); break; //进货管理 case 5: stock_in(); break; //营收统计 case 6: revenue(); break; //退出 case 7: delete_item(); break; case 8: printf("感谢您的使用,再见!"); exit(0); break; } } return 0; }帮我处理一下购物车购买完物品然后结算后没有更新库存信息的问题
07-04
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define NUM 10 typedef struct item { char brand[20];//商品名字 char id[10];//商品编号 float in_price;//进价 float out_price;//售价 int storage;//商品数量 }item; item goods[NUM]; //购物车类型 typedef struct item_node { item wanted;//商品 int amount;//购物数量 struct item_node* next; } item_node; item_node* cart; void clear_input_buffer() { int c; while ((c = getchar()) != ‘\n’ && c != EOF); } int menu() { int select; printf(“请选择数字进行操作:\n”); printf(“1.建立库存信息\n”); printf(“2.显示库存信息\n”); printf(“3.购物车\n”); printf(“4.结算\n”); printf(“5.进货管理\n”); printf(“6.营收统计\n”); printf(“7.退出\n”); printf(“请选择对应数字(1-7):\n”); while (1) { scanf(“%d”, &select); if (select < 1 || select>7) { printf(“输入错误,请重新输入\n”); } else { break; } } return select; } //建立库存信息 void establish() { FILE* fp;//创建指向文件的指针 printf(“请依次输入货物信息(库存货物种类为10):\n”); printf(“------------------------\n”); //初始化商品信息 for (int i = 0; i < NUM; i++) { printf(“商品名称:”); fflush(stdin); scanf(“%s”, goods[i].brand); printf("商品编号:"); fflush(stdin); scanf("%s", goods[i].id); printf("商品进价:"); fflush(stdin); scanf("%f", &goods[i].in_price); printf("商品售价:"); fflush(stdin); scanf("%f", &goods[i].out_price); printf("商品数量:"); fflush(stdin); scanf("%d", &goods[i].storage); printf("\n"); printf("是否还要添加货物种类:(Y/N)"); clear_input_buffer(); char g = getchar(); if (g == 'n' || g == 'N') { break; } else { continue; } } if ((fp = fopen("goods", "w")) == NULL) { printf("创建文件失败\n"); } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } //显示库存信息 void dis_all() { //清空前面显示的内容 system(“cls”); FILE* fp; fp = fopen(“goods”, “r”); for (int i = 0; (fread(goods + i, sizeof(item), 1, fp) != 0); i++) { printf(“----------------------------------------------------------\n”); printf(“商品编号\t商品名称\t商品单价\t库存数量\n”); printf(“----------------------------------------------------------\n”); printf(“%s%18s%17.2f%17d\n”, goods[i].id, goods[i].brand, goods[i].out_price, goods[i].storage); } } //购物车菜单 int cart_menu() { int select; printf(“------------------\n”); printf(“1.显示当前购物列表\n”); printf(“2.添加商品\n”); printf(“3.退出\n”); printf(“------------------\n”); printf(“请选择操作:\n”); while (1) { scanf(“%d”, &select); if (select < 1 || select>3) { printf(“输入错误,请重新输入\n”); } else { break; } } return select; } //添加商品 void add() { FILE* fp; char str[20];//获取物品名字/编号的字符串 int n; int i; char choice,choice2; item_node* p1,p; do { printf(“输入所需物品的名称或编号:\n”); fflush(stdin); scanf(“%s”, str); if ((fp = fopen(“goods”, “r”)) == NULL) { printf(“打开文件失败!\n”); continue; } for (i = 0; fread(goods + i, sizeof(item), 1, fp) != 0; i++) { if ((strcmp(goods[i].brand, str) == 0 || strcmp(goods[i].id, str) == 0) && goods[i].storage != 0) { printf(“已经找到所需物品:\n”); printf(“----------------------------------------------------------\n”); printf(“商品编号\t商品名称\t商品单价\t库存数量\n”); printf(“----------------------------------------------------------\n”); printf(“%s%18s%17.2f%17d\n”, goods[i].id, goods[i].brand, goods[i].out_price, goods[i].storage); printf(“请输入所需要数量:\n”); clear_input_buffer();// 清除缓冲区 if (scanf(“%d”, &n) != 1) { printf(“输入错误,请输入数字!\n”); n = 0; // 防止未初始化值 clear_input_buffer(); break; } if (n > goods[i].storage) { printf(“库存不足\n”); break; } printf(“是否购买?(Y/N)\n”); clear_input_buffer(); choice = getchar(); if (choice == ‘Y’ || choice == ‘y’) { p1 = (item_node)malloc(sizeof(item_node)); if (p1 == NULL) { printf(“内存申请失败!\n”); exit(1); } p1->amount = n;//存入需要购物商品数量 p1->wanted = goods[i]; p1->next = NULL; p = cart; if (cart == NULL) cart = p1; else { while (p->next != NULL) p = p->next; p1->next = p->next; p->next = p1; } } break; } } if (i == NUM) { printf(“未找到所需物品\n”); } fclose(fp); printf("是否继续购物?(Y/N)"); clear_input_buffer(); choice2 = getchar(); } while (choice2 == 'Y' || choice2 == 'y'); } //显示购物列表 void display() { system(“cls”); item_node* p = cart; if (p == NULL) { printf(“购物车为空!\n”); return; } while (p != NULL) { printf(“----------------------------------------------------------\n”); printf(“商品编号\t商品名称\t商品单价\t购买数量\n”); printf(“----------------------------------------------------------\n”); printf(“%s%18s%17.2f%17d\n\n”,p->wanted .id,p->wanted .brand,p->wanted .out_price ,p->amount ); p = p->next; } } //购物车 void shop_car() { system(“cls”); while (1) { switch (cart_menu()) { //显示当前购物列表 case 1: display(); break; //添加商品 case 2: add(); break; //退出购物车 case 3: return; break; } } } //结算功能实现 void calculate() { system(“cls”); float total = 0, pay; item_node* p; FILE* fp; printf(“以下是购物清单:\n”); display();//显示购物车的内容 if ((fp = fopen(“goods”, “r”)) == NULL) { printf(“文件打开失败!\n”); return; } for (int i = 0; (fread(goods + i, sizeof(item), 1, fp)) != 0; i++); fclose(fp); p = cart; while (p != NULL) { total += p->wanted.out_price * p->amount; for (int i = 0; strcmp(goods[i].id, p->wanted.id) != 0; i++) goods[i].storage -= p->amount; p = p->next; } printf(“总计:%7.2f”,total); printf(“\n输入支付金额:”); scanf(“%f”, &pay); printf(“\n实际支付:%7.2f\t\t找零:%7.2f\n”, pay, pay - total); if ((fp = fopen(“goods”, “w”)) == NULL) { printf(“文件读取打开失败!\n”); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); FILE* log_fp = fopen(“sales_log.txt”, “a”); // 以追加方式打开日志文件 if (log_fp == NULL) { printf(“无法打开日志文件。\n”); } else { time_t t = time(NULL); struct tm* tm_info = localtime(&t); char buffer[80]; strftime(buffer, 80, “%Y-%m-%d %H:%M:%S”, tm_info); fprintf(log_fp, "=== 结算时间:%s ===\n", buffer); p = cart; while (p != NULL) { fprintf(log_fp, "商品名称:%s\t售价:%.2f\t进价:%.2f\t数量:%d\n", p->wanted.brand, p->wanted.out_price, p->wanted.in_price, p->amount); p = p->next; } fprintf(log_fp, "总计:%.2f 元\n", total); fprintf(log_fp, "===============================\n"); fclose(log_fp); } } // 进货管理 - 支持添加新商品 void stock_in() { FILE* fp; char str[20]; // 获取物品名字/编号的字符串 int n; // 进货或新增数量 int i; char choice; printf("请输入要进货的商品名称或编号:\n"); clear_input_buffer(); scanf("%s", str); if ((fp = fopen("goods", "r")) == NULL) { printf("打开文件失败!\n"); return; } // 读取所有商品信息到 goods 数组中 for (i = 0; fread(goods + i, sizeof(item), 1, fp) != 0; i++); fclose(fp); // 查找匹配的商品 for (i = 0; i < NUM; i++) { if (strcmp(goods[i].brand, str) == 0 || strcmp(goods[i].id, str) == 0) { // 找到已有商品 printf("找到商品:%s %s\n", goods[i].id, goods[i].brand); printf("当前库存数量:%d\n", goods[i].storage); printf("请输入进货数量:\n"); clear_input_buffer(); if (scanf("%d", &n) != 1 || n <= 0) { printf("输入错误,请输入正整数!\n"); clear_input_buffer(); return; } printf("确认进货 %d 个 %s?(Y/N)\n", n, goods[i].brand); clear_input_buffer(); choice = getchar(); if (choice == 'Y' || choice == 'y') { goods[i].storage += n; // 增加库存数量 printf("进货成功!新的库存数量:%d\n", goods[i].storage); // 将更新后的商品信息写入文件 if ((fp = fopen("goods", "w")) == NULL) { printf("文件写入失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } else { printf("取消进货。\n"); } return; } } // 没有找到该商品,提示是否作为新商品添加 printf("未找到该商品,是否添加为新商品?(Y/N)\n"); clear_input_buffer(); choice = getchar(); if (choice == 'Y' || choice == 'y') { // 寻找空位插入新商品 for (i = 0; i < NUM; i++) { if (goods[i].storage == 0 && strlen(goods[i].brand) == 0) break; } if (i >= NUM) { printf("库存已满,无法添加新商品。\n"); return; } item new_item; printf("请输入新商品的信息:\n"); printf("商品名称: "); scanf("%s", new_item.brand); printf("商品编号: "); scanf("%s", new_item.id); printf("商品进价: "); scanf("%f", &new_item.in_price); printf("商品售价: "); scanf("%f", &new_item.out_price); printf("进货数量: "); if (scanf("%d", &n) != 1 || n <= 0) { printf("输入错误,请输入正整数!\n"); return; } new_item.storage = n; goods[i] = new_item; // 写回文件 if ((fp = fopen("goods", "w")) == NULL) { printf("文件写入失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); printf("新商品已添加成功!\n"); } else { printf("操作已取消。\n"); } } // 营收统计 (从销售日志中提取数据) void revenue() { FILE* fp = fopen(“sales_log.txt”, “r”); if (!fp) { printf(“没有找到销售日志文件。\n”); return; } char line[256]; float total_sales = 0.0f, total_cost = 0.0f; // 用于存储当前交易的时间 char current_time[80] = ""; while (fgets(line, sizeof(line), fp)) { // 如果匹配到时间行 if (strncmp(line, "===", 3) == 0 && strstr(line, "结算时间:")) { sscanf(line, "=== 结算时间:%79[^ ] ===", current_time); // 提取时间 } // 如果匹配到商品行 else if (strstr(line, "商品名称:")) { char name[50]; float out_price, in_price; int amount; sscanf(line, "商品名称:%[^ ] 售价:%f 进价:%f 数量:%d", name, &out_price, &in_price, &amount); float sales = out_price * amount; float cost = in_price * amount; total_sales += sales; total_cost += cost; // 显示每条记录及其时间 printf("时间:%s\n", current_time); printf("商品名称:%s\t售价:%.2f\t进价:%.2f\t数量:%d\n", name, out_price, in_price, amount); printf("销售收入:%.2f 元\t商品利润:%.2f 元\n\n", sales, sales - cost); } } fclose(fp); printf("=== 销售营收报告(来自日志) ===\n"); printf("总销售额:%.2f 元\n", total_sales); printf("总成本:%.2f 元\n", total_cost); printf("总利润:%.2f 元\n", total_sales - total_cost); } int main() { int select; printf(“\n"); printf(“欢迎使用超市管理系统\n”); printf("\n”); while(1) { switch (menu()) { //建立库存信息 case 1: establish(); break; //显示库存信息 case 2: dis_all(); break; //购物车 case 3: shop_car(); break; //结算 case 4: calculate(); break; //进货管理 case 5: stock_in(); break; //营收统计 case 6: revenue(); break; //退出 case 7: printf("感谢您的使用,再见!"); exit(0); break; } } return 0; }帮我补充一个货物删除函数
07-04
#include<stdio.h> #include<stdlib.h> #include<string.h> #define NUM 10 typedef struct item { char brand[20];//商品名字 char id[10];//商品编号 float in_price;//进价 float out_price;//售价 int storage;//商品数量 }item; item goods[NUM]; //购物车类型 typedef struct item_node { item wanted;//商品 int amount;//购物数量 struct item_node* next; } item_node; item_node* cart; void clear_input_buffer() { int c; while ((c = getchar()) != '\n' && c != EOF); } int menu() { int select; printf("请选择数字进行操作:\n"); printf("1.建立库存信息\n"); printf("2.显示库存信息\n"); printf("3.购物车\n"); printf("4.结算\n"); printf("5.进货管理\n"); printf("6.退出\n"); printf("请选择对应数字(1-5):\n"); while (1) { scanf("%d", &select); if (select < 1 || select>5) { printf("输入错误,请重新输入\n"); } else { break; } } return select; } //建立库存信息 void establish() { FILE* fp;//创建指向文件的指针 printf("请依次输入货物信息(库存货物种类为10):\n"); printf("------------------------\n"); //初始化商品信息 for (int i = 0; i < NUM; i++) { printf("商品名称:"); fflush(stdin); scanf("%s", goods[i].brand); printf("商品编号:"); fflush(stdin); scanf("%s", goods[i].id); printf("商品进价:"); fflush(stdin); scanf("%f", &goods[i].in_price); printf("商品售价:"); fflush(stdin); scanf("%f", &goods[i].out_price); printf("商品数量:"); fflush(stdin); scanf("%d", &goods[i].storage); printf("\n"); printf("是否还要添加货物种类:(Y/N)"); clear_input_buffer(); char g = getchar(); if (g == 'n' || g == 'N') { break; } else { continue; } } if ((fp = fopen("goods", "w")) == NULL) { printf("创建文件失败\n"); } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } //显示库存信息 void dis_all() { //清空前面显示的内容 system("cls"); FILE* fp; fp = fopen("goods", "r"); for (int i = 0; (fread(goods + i, sizeof(item), 1, fp) != 0); i++) { printf("----------------------------------------------------------\n"); printf("商品编号\t商品名称\t商品单价\t库存数量\n"); printf("----------------------------------------------------------\n"); printf("%s%18s%17.2f%17d\n", goods[i].id, goods[i].brand, goods[i].out_price, goods[i].storage); } } //购物车菜单 int cart_menu() { int select; printf("------------------\n"); printf("1.显示当前购物列表\n"); printf("2.添加商品\n"); printf("3.退出\n"); printf("------------------\n"); printf("请选择操作:\n"); while (1) { scanf("%d", &select); if (select < 1 || select>3) { printf("输入错误,请重新输入\n"); } else { break; } } return select; } //添加商品 void add() { FILE* fp; char str[20];//获取物品名字/编号的字符串 int n; int i; char choice,choice2; item_node* p1,*p; do { printf("输入所需物品的名称或编号:\n"); fflush(stdin); scanf("%s", str); if ((fp = fopen("goods", "r")) == NULL) { printf("打开文件失败!\n"); continue; } for (i = 0; fread(goods + i, sizeof(item), 1, fp) != 0; i++) { if ((strcmp(goods[i].brand, str) == 0 || strcmp(goods[i].id, str) == 0) && goods[i].storage != 0) { printf("已经找到所需物品:\n"); printf("----------------------------------------------------------\n"); printf("商品编号\t商品名称\t商品单价\t库存数量\n"); printf("----------------------------------------------------------\n"); printf("%s%18s%17.2f%17d\n", goods[i].id, goods[i].brand, goods[i].out_price, goods[i].storage); printf("请输入所需要数量:\n"); clear_input_buffer();// 清除缓冲区 if (scanf("%d", &n) != 1) { printf("输入错误,请输入数字!\n"); n = 0; // 防止未初始化值 clear_input_buffer(); break; } if (n > goods[i].storage) { printf("库存不足\n"); break; } printf("是否购买?(Y/N)\n"); clear_input_buffer(); choice = getchar(); if (choice == 'Y' || choice == 'y') { p1 = (item_node*)malloc(sizeof(item_node)); if (p1 == NULL) { printf("内存申请失败!\n"); exit(1); } p1->amount = n;//存入需要购物商品数量 p1->wanted = goods[i]; p1->next = NULL; p = cart; if (cart == NULL) cart = p1; else { while (p->next != NULL) p = p->next; p1->next = p->next; p->next = p1; } } break; } } if (i == NUM) { printf("未找到所需物品\n"); } fclose(fp); printf("是否继续购物?(Y/N)"); clear_input_buffer(); choice2 = getchar(); } while (choice2 == 'Y' || choice2 == 'y'); } //显示购物列表 void display() { system("cls"); item_node* p = cart; if (p == NULL) { printf("购物车为空!\n"); return; } while (p != NULL) { printf("----------------------------------------------------------\n"); printf("商品编号\t商品名称\t商品单价\t购买数量\n"); printf("----------------------------------------------------------\n"); printf("%s%18s%17.2f%17d\n\n",p->wanted .id,p->wanted .brand,p->wanted .out_price ,p->amount ); p = p->next; } } //购物车 void shop_car() { system("cls"); while (1) { switch (cart_menu()) { //显示当前购物列表 case 1: display(); break; //添加商品 case 2: add(); break; //退出购物车 case 3: return; break; } } } //结算功能实现 void calculate() { system("cls"); float total = 0, pay; item_node* p; FILE* fp; printf("以下是购物清单:\n"); display();//显示购物车的内容 if ((fp = fopen("goods", "r")) == NULL) { printf("文件打开失败!\n"); return; } for (int i = 0; (fread(goods + i, sizeof(item), 1, fp)) != 0; i++); fclose(fp); p = cart; while (p != NULL) { total += p->wanted.out_price * p->amount; for (int i = 0; strcmp(goods[i].id, p->wanted.id) != 0; i++) goods[i].storage -= p->amount; p = p->next; } printf("总计:%7.2f",total); printf("\n输入支付金额:"); scanf("%f", &pay); printf("\n实际支付:%7.2f\t\t找零:%7.2f\n", pay, pay - total); if ((fp = fopen("goods", "w")) == NULL) { printf("文件读取打开失败!\n"); return; } fwrite(goods, sizeof(item), NUM, fp); fclose(fp); } //进货管理 void stock_in() { } int main() { int select; printf("**********************\n"); printf("*欢迎使用超市管理系统*\n"); printf("**********************\n"); while(1) { switch (menu()) { //建立库存信息 case 1: establish(); break; //显示库存信息 case 2: dis_all(); break; //购物车 case 3: shop_car(); break; //结算 case 4: calculate(); break; //进货管理 case 5: stock_in(); break; //退出 case 6: printf("感谢您的使用,再见!"); exit(0); break; } } return 0; }帮我完成进货管理函数
07-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值