目录
前言:
源代码:
product.h
product.c
fileio.h
fileio.c
main.c
json_export.h
json_export.c
tasks.json
idex.html
script.js
相关步骤:
第一步:
第二步:
第三步:
第四步:
第五步:
第六步:
运行结果:
前言:
当前这篇博客是预告,基于上篇博客超市管理系统基础上来写的网页版,今天只是展示:
(C语言)超市管理系统 (正式版)(指针)(数据结构)(清屏操作)(文件读写)-CSDN博客
看之前建议先看测试版博客:
(C语言)超市管理系统(测试版)(指针)(数据结构)(二进制文件读写)-CSDN博客
如果大家对前端(html,js,json)有兴趣,后续可以教大家一些,我也只是略懂一二
共13个文件(加上二进制文件);
源代码:
product.h
#pragma once // 防止头文件重复定义
#define NAME_LEN 50 // 商品名称最大容量
// 单个商品结构体
typedef struct {
int id; // 商品编号
char name[NAME_LEN]; // 商品名字
float price; // 商品单价
int stock; // 商品库存
} Product;
// 商品列表表结构体
typedef struct {
Product* Data; // 指向单个商品数组的指针
int count; // 当前商品数量
} ProductList;
// 函数原型
void Init_products(ProductList* list); // 初始化商品列表结构体
void add_product(ProductList* list, Product* product); // 添加单个商品
void display_products(ProductList* list); // 显示所有商品
void mod_product(ProductList* list); // 修改单个商品
void del_product(ProductList* list); // 删除单个商品
void que_product(ProductList* list); // 查询单个商品
product.c
#include "product.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 初始化商品列表结构体
void Init_products(ProductList* list) {
list->Data = NULL; // 指针置空,防止野指针
list->count = 0; // 商品数量归0
}
// 添加单个商品
void add_product(ProductList* list, Product* product) {
// 1. 扩展空间
Product* listnew_Data = realloc(list->Data, (list->count + 1) * sizeof(Product));
if (listnew_Data == NULL) {
printf("内存分配失败!\n");
exit(EXIT_FAILURE);
}
list->count++; // 商品数量加一
list->Data = listnew_Data; // 依然用老数组表示描述
// 2. ID自动生成
list->Data[list->count - 1].id = list->count; // 利用商品当前数量赋值ID
printf("商品ID:%d\n", list->count);
// 3. 商品信息录入
printf("请输入商品名称:");
scanf("%49s", list->Data[list->count - 1].name);
printf("请输入单价:");
scanf("%f", &list->Data[list->count - 1].price);
printf("请输入库存:");
scanf("%d", &list->Data[list->count - 1].stock);
printf("添加成功!\n");
}
// 显示所有商品
void display_products(ProductList* list) {
// 1. 判断列表是否为空
if (list->count == 0) {
printf("库存为空\n");
return;
}
// 2. 打印表头
printf("\n%5s %-20s %10s %6s\n", "ID", "名称", "单价", "库存");
printf("--------------------------------------------\n");
// 3. 打印商品信息
for (int i = 0; i < list->count; i++) { // 遍历商品列表
printf("%5d %-20s %10.2f %5d\n",
list->Data[i].id,
list->Data[i].name,
list->Data[i].price,
list->Data[i].stock);
}
}
// 修改单个商品
void mod_product(ProductList* list) {
// 1. 判断列表是否为空
if (list->count == 0) {
printf("库存为空\n");
return;
}
// 2. 输入要修改的ID
int id_0;
printf("请输入要修改的ID:");
scanf("%d", &id_0);
// 3. 判断ID是否存在
if (id_0 > list->count) {
printf("ID不存在!\n");
return;
}
// 4. 找要修改商品的ID
int i = 0;
for (i; i < list->count; i++) {
if (id_0 == list->Data[i].id) { // 此时的i+1就是当前商品ID
break;
}
}
// 5. 修改商品
printf("\n%5s %-20s %10s %6s\n", "ID", "名称", "单价", "库存");
printf("--------------------------------------------\n");
printf("%5d %-20s %10.2f %5d\n",
list->Data[i].id,
list->Data[i].name,
list->Data[i].price,
list->Data[i].stock);
printf("--------------------------------------------\n");
printf("修改商品名称:");
scanf("%49s", list->Data[i].name);
printf("修改单价:");
scanf("%f", &list->Data[i].price);
printf("修改库存:");
scanf("%d", &list->Data[i].stock);
printf("修改成功!\n");
}
// 删除单个商品
void del_product(ProductList* list) {
// 1. 显示所有商品
display_products(list);
printf("--------------------------------------------\n");
// 2. 输入要删除的ID
int id_0;
printf("请输入要删除的ID:");
scanf("%d", &id_0);
// 3. 判断ID是否存在
if (id_0 > list->count) {
printf("ID不存在!\n");
return;
}
// 4. 找要删除商品的ID
int i = 0;
for (i; i < list->count; i++) { // 此时的i+1就是当前商品ID
if (id_0 == list->Data[i].id) {
break;
}
}
// 5. 删除商品
for (int j = i; j < list->count - 1; j++) {
list->Data[j] = list->Data[j + 1];
}
printf("删除成功!\n");
list->count--; // 商品数量减一
// 6. 重新生成商品ID
if (list->count == 1) {
list->Data[0].id = 1;
}
else {
list->Data[list->count - 1].id = list->Data[list->count - 2].id + 1;
}
}
// 查询单个商品
void que_product(ProductList* list) {
// 1. 判断列表是否为空
if (list->count == 0) {
printf("库存为空\n");
return;
}
// 2. 输入要搜索的ID
int id_0;
printf("请输入要搜索的ID:");
scanf("%d", &id_0);
// 3. 判断ID是否存在
if (id_0 > list->count) {
printf("ID不存在!\n");
return;
}
// 4. 找要搜索商品的ID
int i = 0;
for (i; i < list->count; i++) {
if (id_0 == list->Data[i].id) { // 此时的i+1就是当前商品ID
break;
}
}
// 5. 显示商品
printf("搜索成功!\n");
printf("\n%5s %-20s %10s %6s\n", "ID", "名称", "单价", "库存");
printf("--------------------------------------------\n");
printf("%5d %-20s %10.2f %5d\n",
list->Data[i].id,
list->Data[i].name,
list->Data[i].price,
list->Data[i].stock);
}
fileio.h
#pragma once
#include "product.h"
// 文件操作函数原型
void save_to_file(const char* filename, const ProductList* list);
void load_from_file(const char* filename, ProductList* list);
fileio.c
#include <stdio.h>
#include <stdlib.h>
#include "product.h"
// 保存数据到文件(二进制写入)
void save_to_file(const char* filename, const ProductList* list) {
// 1. 打开文件(二进制写入模式)
FILE* fp = fopen(filename, "wb");
if (!fp) { // fp == NULL 表示打开失败
perror("保存失败"); // 输出错误信息(包含具体原因,如权限不足)
exit(EXIT_FAILURE); // 终止程序,EXIT_FAILURE 表示异常退出
}
// 2. 先写入商品数量(int 类型)
fwrite(&list->count, sizeof(int), 1, fp);
// 3. 再写入所有商品数据(Product 结构体数组)
fwrite(list->Data, sizeof(Product), list->count, fp);
// 4. 关闭文件
fclose(fp);
}
// 从文件加载数据(二进制读取)
void load_from_file(const char* filename, ProductList* list) {
// 1. 初始化结构体(防御性编程)
Init_products(list); // 初始化商品列表结构体
// 2. 尝试打开文件(二进制读取模式)
FILE* fp = fopen(filename, "rb"); // "rb":二进制读取模式,文件不存在时返回 NULL
if (!fp) { // 文件打开失败处理
return; // 保持 list 的初始状态(count=0, Data=NULL)
}
// 3. 读取商品数量(int 类型)
fread(&list->count, sizeof(int), 1, fp);
// 4. 根据数量分配内存
list->Data = (Product*)malloc(list->count * sizeof(Product));
if (list->Data == NULL) { // list->Data == NULL 表示失败
printf("内存分配失败\n");
exit(EXIT_FAILURE); // 终止程序
}
// 5. 读取所有商品数据
fread(list->Data, sizeof(Product), list->count, fp);
// 6. 关闭文件
fclose(fp);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "product.h"
#include "fileio.h"
#include "json_export.h"
#define FILENAME "products.dat" // 宏定义文件名
// 清屏操作
void clear_screen() {
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
}
// 显示主菜单(用户界面)
void display_menu() {
printf("\n超市管理系统\n");
printf("1. 添加商品\n");
printf("2. 显示所有商品\n");
printf("3. 修改商品信息\n");
printf("4. 删除商品\n");
printf("5. 搜索商品\n");
printf("6. 保存并退出\n");
printf("7. 导出为 JSON\n"); // 新增 JSON 导出选项
printf("请选择操作:");
}
int main() {
// 1. 创建结构体并初始化
Product product; // 创建单个商品结构体
ProductList list; // 创建商品列表结构体
Init_products(&list); // 初始化
// 2. 读文件
load_from_file(FILENAME, &list); // 读文件
// 3. 选择模块
int choice; // 选择选项
while (1) {
display_menu(); // 显示菜单
scanf("%d", &choice); // 输入选项
switch (choice) {
case 1:
clear_screen();
add_product(&list, &product);
printf("--------------------------------------------\n");
break;
case 2:
clear_screen();
display_products(&list);
printf("--------------------------------------------\n");
break;
case 3:
clear_screen();
mod_product(&list);
printf("--------------------------------------------\n");
break;
case 4:
clear_screen();
del_product(&list);
printf("--------------------------------------------\n");
break;
case 5:
clear_screen();
que_product(&list);
printf("--------------------------------------------\n");
break;
case 6:
save_to_file(FILENAME, &list); // 保存数据
free(list.Data); // 释放动态内存
printf("系统已退出\n");
return 0; // 正确退出
case 7: {
clear_screen();
export_products_to_json(&list); // 正确调用导出函数
printf("--------------------------------------------\n");
break;
}
default:
printf("无效输入\n");
}
}
}
json_export.h
#pragma once
#include "product.h"
// 导出商品列表为 JSON 文件
void export_products_to_json(const ProductList* list);
json_export.c
#include "json_export.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 导出商品列表为 JSON 文件
void export_products_to_json(const ProductList* list) {
if (list->count == 0) {
printf("当前没有商品数据可导出!\n");
return;
}
// 打开 JSON 文件(覆盖模式)
FILE* json_file = fopen("products.json", "w");
if (!json_file) {
perror("无法创建 JSON 文件");
exit(EXIT_FAILURE);
}
// 写入 JSON 数组开头
fprintf(json_file, "[\n");
// 遍历所有商品
for (int i = 0; i < list->count; i++) {
const Product* p = &list->Data[i];
// 写入商品对象
fprintf(json_file, " {\n");
fprintf(json_file, " \"id\": %d,\n", p->id);
fprintf(json_file, " \"name\": \"%s\",\n", p->name);
fprintf(json_file, " \"price\": %.2f,\n", p->price);
fprintf(json_file, " \"stock\": %d\n", p->stock);
// 非最后一个商品添加逗号
if (i < list->count - 1) {
fprintf(json_file, " },\n");
} else {
fprintf(json_file, " }\n");
}
}
// 写入 JSON 数组结尾
fprintf(json_file, "]");
fclose(json_file);
printf("JSON 文件已生成:products.json\n");
}
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "编译 C 程序", // 关键:任务名
"type": "shell",
"command": "gcc",
"args": [
"-o",
"supermarket",
"main.c",
"product.c",
"fileio.c",
"json_export.c"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"]
}
]
}
idex.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>超市商品展示</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 20px auto;
padding: 20px;
}
table {
width: 100%;
border-collapse: collapse;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
}
th {
background-color: #f5f5f5;
font-weight: 600;
}
tr:hover {
background-color: #f9f9f9;
}
.no-data {
text-align: center;
padding: 20px;
}
</style>
</head>
<body>
<h1>双叶超市商品列表</h1>
<table id="productTable">
<thead>
<tr>
<th>商品 ID</th>
<th>商品名称</th>
<th>单价(元)</th>
<th>库存</th>
</tr>
</thead>
<tbody>
<!-- 商品数据将在此动态填充 -->
</tbody>
</table>
<script src="script.js"></script>
</body>
</html>
script.js
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', async () => {
try {
// 读取本地 JSON 文件(需通过 Live Server 启动才能正常读取)
const response = await fetch('products.json');
if (!response.ok) throw new Error('文件读取失败');
const products = await response.json();
renderProducts(products); // 渲染商品表格
} catch (error) {
const tbody = document.querySelector('#productTable tbody');
tbody.innerHTML = `<tr class="no-data"><td colspan="4">${error.message}</td></tr>`;
}
});
// 渲染商品列表到表格
function renderProducts(products) {
const tbody = document.querySelector('#productTable tbody');
tbody.innerHTML = ''; // 清空原有内容
if (products.length === 0) {
tbody.innerHTML = '<tr class="no-data"><td colspan="4">当前没有商品数据</td></tr>';
return;
}
products.forEach(product => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${product.id}</td>
<td>${product.name}</td>
<td>¥${product.price.toFixed(2)}</td>
<td>${product.stock}</td>
`;
tbody.appendChild(row);
});
}
相关步骤:
第一步:
下载VS code:Visual Studio Code - Code Editing. Redefined
第二步:
下载安装后,下载插件(一共九个):
第三步:
建立一个文件夹(主文件夹名字自己起):
第四步:
按照第三步复制代码到文件里,注意文件层次:
supermarket - project/
├──.vscode/
│ └── tasks.json
├── output/
├── fileio.c
├── fileio.h
├── index.html
├── json_export.c
├── json_export.h
├── main.c
├── product.c
├── product.h
├── products.dat(提前自己建立)
├── products.json(自动生成)
├── script.js
└── supermarket.exe(自动生成)
第五步:
1.打开 VS Code 的设置。你可以通过点击菜单栏中的 文件
-> 首选项
-> 设置
来打开设置页面。
在设置页面的搜索框中输入 C_Cpp.default.compilerPath
。
在搜索结果中,找到 C/C++: Default Compiler Path
这个设置项,并确保它的值是你的 GCC 编译器的路径。
点击 “在 settings.json 中编辑”,此时会打开 settings.json
文件。
在 settings.json
文件中添加以下内容(假设 GCC 路径为 C:\mingw64\bin\gcc.exe
,若实际路径不同需调整):
"C_Cpp.default.compilerPath": "C:\\mingw64\\bin\\gcc.exe"
保存 settings.json
文件。按 Ctrl+Shift+P
,输入 Reload Window
(重新加载窗口)。
2.编译超市管理系统,生成takes.json文件:
此时有这些文件就可(当然你粘贴完也不是不行):
按 Ctrl+Shift+P
,输入 Tasks: Open Task File
,选择 tasks.json
(若无则创建粘贴)
3.运行超市管理系统,生成exe文件和products.json
按 Ctrl+Shift+B
,选择 “编译 C 程序”,生成exe文件,在终端输入 supermarket
(或 supermarket.exe
,取决于系统)运行程序(如果不行,直接在文件管理器打开也行),添加些商品,然后选择7,生成json文件
第六步:
复制粘贴html和js文件,在 VS Code 中打开 index.html
,右键点击页面空白处,选择 “Open with Live Server”。浏览器会自动打开 http://localhost:5500
,显示商品列表。
运行结果:
注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!