category


@implementation NSObject (MyCategory)  
- description { return "hello"; }     // 覆盖已有的方法不需要指明返回值和参数  
- (double) f:(int)v  { return v * 0.5; } // 定义新方法需要指明返回值和参数  
@end


                
电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格和销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌和年份的电动汽车和插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售和安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商和车型组合,包括纯电动汽车和插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准和速度、价格、产地、自主水平、排放、安全等级、销售和保修。 时间跨度:模型跨度多年(包括传统和即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含不同的、特定于供应商的值(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km和额定值。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <ctype.h> // 用户结构体 typedef struct { int id; char username[50]; char password[50]; int role; // 0-普通用户 1-管理员 char register_date[20]; } User; // 分类结构体 typedef struct { int id; char name[50]; int article_count; } Category; // 文章结构体 typedef struct { int id; char title[100]; char content[1024]; int author_id; int category_id; char publish_date[20]; int view_count; } Article; // 浏览记录结构体 typedef struct { int user_id; int article_id; char view_time[20]; } ViewRecord; // 文件路径常量 #define USER_FILE "users.dat" #define CATEGORY_FILE "categories.dat" #define ARTICLE_FILE "articles.dat" #define VIEW_FILE "views.dat" // 函数声明 int generate_user_id(); int generate_article_id(); int generate_category_id(); void get_current_time(char *time_str); void list_categories(); void update_category_count(int category_id, int increment); Article find_article_by_id(int article_id); const char *get_category_name(int category_id); void update_article_view_count(int article_id); void record_view_history(int user_id, int article_id); void browse_articles(User *user); void manage_articles(User *user); void manage_categories(User *user); void generate_statistics(); int check_permission(User *user, int required_role); void user_register(); User *user_login(); void publish_article(User *author); void view_article(User *user, int article_id); void delete_article(User *user); void add_category(); void delete_category(); void modify_category(); // 主函数 int main() { User *current_user = NULL; int choice; while (1) { printf("\n===== 文章管理系统 =====\n"); if (current_user) { printf("当前用户: %s (%s)\n", current_user->username, current_user->role ? "管理员" : "普通用户"); } printf("1. 注册\n2. 登录\n3. 发布文章\n4. 浏览文章\n"); printf("5. 文章管理\n6. 分类管理\n7. 数据统计\n8. 退出\n"); printf("选择操作: "); scanf("%d", &choice); switch (choice) { case 1: user_register(); break; case 2: current_user = user_login(); break; case 3: if (current_user) publish_article(current_user); else printf("请先登录!\n"); break; case 4: browse_articles(current_user); break; case 5: manage_articles(current_user); break; case 6: manage_categories(current_user); break; case 7: generate_statistics(); break; case 8: if (current_user) free(current_user); printf("系统已退出\n"); return 0; default: printf("无效选择!\n"); } } } // 生成用户ID int generate_user_id() { FILE *fp = fopen(USER_FILE, "rb"); if (!fp) return 1; // 文件不存在,从1开始 User user; int max_id = 0; while (fread(&user, sizeof(User), 1, fp)) { if (user.id > max_id) max_id = user.id; } fclose(fp); return max_id + 1; } // 生成文章ID int generate_article_id() { FILE *fp = fopen(ARTICLE_FILE, "rb"); if (!fp) return 1; // 文件不存在,从1开始 Article article; int max_id = 0; while (fread(&article, sizeof(Article), 1, fp)) { if (article.id > max_id) max_id = article.id; } fclose(fp); return max_id + 1; } // 生成分类ID int generate_category_id() { FILE *fp = fopen(CATEGORY_FILE, "rb"); if (!fp) return 1; // 文件不存在,从1开始 Category category; int max_id = 0; while (fread(&category, sizeof(Category), 1, fp)) { if (category.id > max_id) max_id = category.id; } fclose(fp); return max_id + 1; } // 获取当前时间字符串 void get_current_time(char *time_str) { time_t now = time(NULL); struct tm *t = localtime(&now); strftime(time_str, 20, "%Y-%m-%d %H:%M:%S", t); } // 列出所有分类 void list_categories() { FILE *fp = fopen(CATEGORY_FILE, "rb"); if (!fp) { printf("暂无分类\n"); return; } printf("\n===== 文章分类 =====\n"); Category category; while (fread(&category, sizeof(Category), 1, fp)) { printf("ID: %d | 名称: %s | 文章数: %d\n", category.id, category.name, category.article_count); } fclose(fp); } // 更新分类文章计数 void update_category_count(int category_id, int increment) { // 临时文件用于更新 FILE *fp = fopen(CATEGORY_FILE, "rb"); FILE *tmp = fopen("temp.dat", "wb"); if (!fp || !tmp) return; Category category; while (fread(&category, sizeof(Category), 1, fp)) { if (category.id == category_id) { category.article_count += increment; } fwrite(&category, sizeof(Category), 1, tmp); } fclose(fp); fclose(tmp); // 替换原文件 remove(CATEGORY_FILE); rename("temp.dat", CATEGORY_FILE); } // 通过ID查找文章 Article find_article_by_id(int article_id) { FILE *fp = fopen(ARTICLE_FILE, "rb"); Article article = {.id = -1}; // 默认返回无效文章 if (fp) { while (fread(&article, sizeof(Article), 1, fp)) { if (article.id == article_id) { break; } } fclose(fp); } return article; } // 获取分类名称 const char *get_category_name(int category_id) { static char name[50] = "未知分类"; FILE *fp = fopen(CATEGORY_FILE, "rb"); if (fp) { Category category; while (fread(&category, sizeof(Category), 1, fp)) { if (category.id == category_id) { strcpy(name, category.name); break; } } fclose(fp); } return name; } // 更新文章浏览计数 void update_article_view_count(int article_id) { // 临时文件用于更新 FILE *fp = fopen(ARTICLE_FILE, "rb"); FILE *tmp = fopen("temp.dat", "wb"); if (!fp || !tmp) return; Article article; while (fread(&article, sizeof(Article), 1, fp)) { if (article.id == article_id) { article.view_count++; } fwrite(&article, sizeof(Article), 1, tmp); } fclose(fp); fclose(tmp); // 替换原文件 remove(ARTICLE_FILE); rename("temp.dat", ARTICLE_FILE); } // 记录浏览历史 void record_view_history(int user_id, int article_id) { ViewRecord record; record.user_id = user_id; record.article_id = article_id; get_current_time(record.view_time); FILE *fp = fopen(VIEW_FILE, "ab"); if (fp) { fwrite(&record, sizeof(ViewRecord), 1, fp); fclose(fp); } } // 浏览文章 void browse_articles(User *user) { FILE *fp = fopen(ARTICLE_FILE, "rb"); if (!fp) { printf("暂无文章\n"); return; } printf("\n===== 文章列表 =====\n"); Article article; while (fread(&article, sizeof(Article), 1, fp)) { printf("ID: %d | 标题: %s | 分类: %s | 作者ID: %d | 浏览量: %d\n", article.id, article.title, get_category_name(article.category_id), article.author_id, article.view_count); } fclose(fp); int article_id; printf("\n输入要查看的文章ID (0返回): "); scanf("%d", &article_id); if (article_id > 0) { view_article(user, article_id); } } // 文章管理 void manage_articles(User *user) { if (!check_permission(user, 1)) { printf("权限不足!需要管理员权限\n"); return; } int choice; do { printf("\n===== 文章管理 =====\n"); printf("1. 删除文章\n2. 返回\n选择操作: "); scanf("%d", &choice); switch (choice) { case 1: delete_article(user); break; case 2: return; default: printf("无效选择!\n"); } } while (choice != 2); } // 分类管理 void manage_categories(User *user) { if (!check_permission(user, 1)) { printf("权限不足!需要管理员权限\n"); return; } int choice; do { printf("\n===== 分类管理 =====\n"); printf("1. 添加分类\n2. 删除分类\n3. 修改分类\n4. 返回\n选择操作: "); scanf("%d", &choice); switch (choice) { case 1: add_category(); break; case 2: delete_category(); break; case 3: modify_category(); break; case 4: return; default: printf("无效选择!\n"); } } while (choice != 4); } // 数据统计 void generate_statistics() { // 用户统计 int user_count = 0, admin_count = 0; FILE *user_fp = fopen(USER_FILE, "rb"); if (user_fp) { User user; while (fread(&user, sizeof(User), 1, user_fp)) { user_count++; if (user.role == 1) admin_count++; } fclose(user_fp); } // 文章统计 int article_count = 0, total_views = 0; FILE *article_fp = fopen(ARTICLE_FILE, "rb"); if (article_fp) { Article article; while (fread(&article, sizeof(Article), 1, article_fp)) { article_count++; total_views += article.view_count; } fclose(article_fp); } // 分类统计 int category_count = 0; FILE *category_fp = fopen(CATEGORY_FILE, "rb"); if (category_fp) { Category category; while (fread(&category, sizeof(Category), 1, category_fp)) { category_count++; } fclose(category_fp); } printf("\n===== 系统统计信息 =====\n"); printf("用户总数: %d (管理员: %d)\n", user_count, admin_count); printf("文章总数: %d\n", article_count); printf("分类总数: %d\n", category_count); printf("总浏览量: %d\n", total_views); } // 权限检查 int check_permission(User *user, int required_role) { if (user == NULL) return 0; // 未登录 if (user->role >= required_role) return 1; // 权限足够 return 0; // 权限不足 } // 用户注册 void user_register() { User new_user; printf("请输入用户名: "); scanf("%s", new_user.username); // 检查用户名是否已存在 FILE *check_fp = fopen(USER_FILE, "rb"); if (check_fp) { User user; while (fread(&user, sizeof(User), 1, check_fp)) { if (strcmp(user.username, new_user.username) == 0) { printf("用户名已存在!\n"); fclose(check_fp); return; } } fclose(check_fp); } printf("请输入密码: "); scanf("%s", new_user.password); // 生成用户ID和注册时间 new_user.id = generate_user_id(); get_current_time(new_user.register_date); new_user.role = 0; // 默认普通用户 // 保存到文件 FILE *fp = fopen(USER_FILE, "ab"); if (fp) { fwrite(&new_user, sizeof(User), 1, fp); fclose(fp); printf("注册成功!用户ID: %d\n", new_user.id); } else { printf("注册失败!\n"); } } // 用户登录 User *user_login() { char username[50], password[50]; printf("用户名: "); scanf("%s", username); printf("密码: "); scanf("%s", password); FILE *fp = fopen(USER_FILE, "rb"); if (!fp) { printf("用户数据库不存在!\n"); return NULL; } User user; while (fread(&user, sizeof(User), 1, fp)) { if (strcmp(user.username, username) == 0 && strcmp(user.password, password) == 0) { fclose(fp); User *logged_user = malloc(sizeof(User)); *logged_user = user; printf("登录成功!欢迎 %s\n", username); return logged_user; } } fclose(fp); printf("用户名或密码错误!\n"); return NULL; } // 发布文章 void publish_article(User *author) { Article new_article; printf("文章标题: "); scanf(" %[^\n]", new_article.title); // 读取带空格的标题 printf("文章内容: "); scanf(" %[^\n]", new_article.content); // 设置文章信息 new_article.id = generate_article_id(); new_article.author_id = author->id; new_article.view_count = 0; get_current_time(new_article.publish_date); // 选择分类 list_categories(); printf("选择分类ID: "); scanf("%d", &new_article.category_id); // 保存文章 FILE *fp = fopen(ARTICLE_FILE, "ab"); if (fp) { fwrite(&new_article, sizeof(Article), 1, fp); fclose(fp); // 更新分类统计 update_category_count(new_article.category_id, 1); printf("文章发布成功!ID: %d\n", new_article.id); } else { printf("文章发布失败!\n"); } } // 查看文章 void view_article(User *user, int article_id) { // 查找文章 Article article = find_article_by_id(article_id); if (article.id == -1) { printf("文章不存在!\n"); return; } // 显示文章内容 printf("\n===== 文章详情 =====\n"); printf("标题: %s\n", article.title); printf("分类: %s\n", get_category_name(article.category_id)); printf("发布时间: %s\n", article.publish_date); printf("浏览数: %d\n\n", article.view_count + 1); printf("内容:\n%s\n\n", article.content); // 更新浏览计数 update_article_view_count(article_id); // 记录浏览历史 if (user != NULL) { record_view_history(user->id, article_id); } } // 删除文章 void delete_article(User *user) { if (!check_permission(user, 1)) { printf("权限不足!需要管理员权限\n"); return; } int article_id; printf("输入要删除的文章ID: "); scanf("%d", &article_id); // 查找文章获取分类ID Article article = find_article_by_id(article_id); if (article.id == -1) { printf("文章不存在!\n"); return; } // 临时文件用于删除操作 FILE *fp = fopen(ARTICLE_FILE, "rb"); FILE *tmp = fopen("temp.dat", "wb"); if (!fp || !tmp) { printf("操作失败!\n"); return; } Article current; int found = 0; while (fread(&current, sizeof(Article), 1, fp)) { if (current.id != article_id) { fwrite(&current, sizeof(Article), 1, tmp); } else { found = 1; } } fclose(fp); fclose(tmp); if (found) { // 替换原文件 remove(ARTICLE_FILE); rename("temp.dat", ARTICLE_FILE); // 更新分类文章计数 update_category_count(article.category_id, -1); printf("文章 %d 已删除\n", article_id); } else { remove("temp.dat"); printf("文章不存在!\n"); } } // 添加分类 void add_category() { Category new_category; printf("输入分类名称: "); scanf(" %[^\n]", new_category.name); new_category.id = generate_category_id(); new_category.article_count = 0; FILE *fp = fopen(CATEGORY_FILE, "ab"); if (fp) { fwrite(&new_category, sizeof(Category), 1, fp); fclose(fp); printf("分类添加成功!ID: %d\n", new_category.id); } else { printf("添加失败!\n"); } } // 删除分类 void delete_category() { int category_id; printf("输入要删除的分类ID: "); scanf("%d", &category_id); // 检查分类是否存在 Category category; int found = 0; FILE *check_fp = fopen(CATEGORY_FILE, "rb"); if (check_fp) { while (fread(&category, sizeof(Category), 1, check_fp)) { if (category.id == category_id) { found = 1; break; } } fclose(check_fp); } if (!found) { printf("分类不存在!\n"); return; } if (category.article_count > 0) { printf("该分类下有文章,不能删除!\n"); return; } // 删除操作 FILE *fp = fopen(CATEGORY_FILE, "rb"); FILE *tmp = fopen("temp.dat", "wb"); if (!fp || !tmp) { printf("操作失败!\n"); return; } while (fread(&category, sizeof(Category), 1, fp)) { if (category.id != category_id) { fwrite(&category, sizeof(Category), 1, tmp); } } fclose(fp); fclose(tmp); remove(CATEGORY_FILE); rename("temp.dat", CATEGORY_FILE); printf("分类 %d 已删除\n", category_id); } // 修改分类 void modify_category() { int category_id; printf("输入要修改的分类ID: "); scanf("%d", &category_id); // 查找分类 FILE *fp = fopen(CATEGORY_FILE, "rb+"); if (!fp) { printf("分类数据库不存在!\n"); return; } Category category; int found = 0; long position = 0; while (fread(&category, sizeof(Category), 1, fp)) { if (category.id == category_id) { found = 1; break; } position = ftell(fp); } if (!found) { printf("分类不存在!\n"); fclose(fp); return; } printf("当前名称: %s\n", category.name); printf("输入新名称: "); scanf(" %[^\n]", category.name); // 定位并更新 fseek(fp, position, SEEK_SET); fwrite(&category, sizeof(Category), 1, fp); fclose(fp); printf("分类修改成功!\n"); }
06-20
<think>我们正在分析一个用C语言编写的文章管理系统。这个系统具有用户管理、文章发布、分类管理、浏览记录和统计等功能。代码结构清晰,使用了结构体来定义数据模型,并通过文件进行数据持久化。首先,我们注意到代码中已经实现了以下功能:1.用户注册和登录(普通用户和管理员)2.发布文章(需要登录)3.浏览文章列表和查看文章详情(记录浏览历史和更新浏览量)4.文章管理(删除文章,需要管理员权限)5.分类管理(添加、删除、修改分类,需要管理员权限)6.数据统计(用户数、文章数、分类数、总浏览量)然而,在浏览文章功能中,我们发现当用户查看文章详情时,系统会更新文章的浏览计数,并记录浏览历史(如果用户已登录)。但是,在浏览文章列表时,我们只能看到文章的标题、分类、作者ID和浏览量,而没有显示作者的用户名,这不太友好。我们可以改进:在浏览文章列表时,显示作者的用户名而不是ID。这需要我们在显示文章列表时,根据文章中的作者ID去用户文件中查找对应的用户名。但是,由于用户文件可能很大,每次显示文章列表都去遍历用户文件可能会影响性能。我们可以考虑在发布文章时,将作者的用户名也存储在文章结构体中?但这样会导致数据冗余,如果用户修改了用户名,那么所有已发布的文章中的作者名都需要更新。另一种方法:在显示文章列表时,先读取所有用户到一个数组中(如果用户数量不是特别大的话),然后根据作者ID快速查找用户名。或者,我们可以构建一个用户ID到用户名的映射。由于这个系统是小型系统,用户数量不会太大,我们可以采用以下方法:在`browse_articles`函数中,我们先读取所有用户到内存中,然后创建一个映射(例如,使用数组或链表),这样在显示每篇文章时,我们可以快速查找作者的用户名。但是,我们需要考虑内存使用。如果用户数量很大,可能会占用较多内存。不过,对于小型系统,这是可以接受的。修改步骤:1.在`browse_articles`函数开头,读取用户文件,将用户数据存储在一个数组中(动态分配内存)。2.遍历文章时,对于每篇文章,遍历用户数组,找到匹配作者ID的用户,获取其用户名。3.显示文章信息时,使用用户名代替作者ID。4.释放分配的内存。注意:如果用户数量为0,或者没有找到对应的用户,则显示“未知用户”。另外,我们还可以考虑将用户ID到用户名的映射构建成一个哈希表以提高查找效率,但考虑到用户数量不会太大,线性查找也是可以接受的。我们修改`browse_articles`函数如下:但是,我们也要注意,如果用户文件不存在,则跳过用户加载,显示ID。由于代码较长,我们只展示修改后的`browse_articles`函数:注意:由于用户文件可能不存在,或者读取失败,我们需要处理这些情况。修改后的代码:```cvoidbrowse_articles(User*user){//先读取所有用户到内存User*users=NULL;intuser_count=0;FILE*user_fp=fopen(USER_FILE,"rb");if(user_fp){//获取用户数量fseek(user_fp,0,SEEK_END);longfile_size=ftell(user_fp);fseek(user_fp,0,SEEK_SET);user_count=file_size/sizeof(User);//分配内存users=(User*)malloc(file_size);if(users){fread(users,sizeof(User),user_count,user_fp);}else{user_count=0;}fclose(user_fp);}FILE*fp=fopen(ARTICLE_FILE,"rb");if(!fp){printf("暂无文章\n");if(users)free(users);return;}printf("\n=====文章列表=====\n");Articlearticle;while(fread(&article,sizeof(Article),1,fp)){//查找作者用户名charauthor_name[50]="未知用户";if(users){for(inti=0;i<user_count;i++){if(users[i].id==article.author_id){strcpy(author_name,users[i].username);break;}}}printf("ID:%d|标题:%s|分类:%s|作者:%s|浏览量:%d\n",article.id,article.title,get_category_name(article.category_id),author_name,article.view_count);}fclose(fp);if(users)free(users);intarticle_id;printf("\n输入要查看的文章ID(0返回):");scanf("%d",&article_id);if(article_id>0){view_article(user,article_id);}}```这样修改后,文章列表中将显示作者的用户名,而不是ID,更加友好。另外,我们注意到在`view_article`函数中,查看文章详情时,作者仍然显示的是ID。我们可以同样修改为显示用户名。我们可以复用上面的方法,但为了简化,我们也可以写一个辅助函数`get_username_by_id(intuser_id)`,该函数通过遍历用户文件来查找用户名。由于在查看单篇文章时,我们只需要查找一个用户,所以我们可以直接打开用户文件查找。修改`view_article`函数:```cvoidview_article(User*user,intarticle_id){//查找文章Articlearticle=find_article_by_id(article_id);if(article.id==-1){printf("文章不存在!\n");return;}//获取作者用户名charauthor_name[50]="未知用户";FILE*user_fp=fopen(USER_FILE,"rb");if(user_fp){Useru;while(fread(&u,sizeof(User),1,user_fp)){if(u.id==article.author_id){strcpy(author_name,u.username);break;}}fclose(user_fp);}//显示文章内容printf("\n=====文章详情=====\n");printf("标题:%s\n",article.title);printf("作者:%s\n",author_name);printf("分类:%s\n",get_category_name(article.category_id));printf("发布时间:%s\n",article.publish_date);printf("浏览数:%d\n\n",article.view_count+1);//因为这次查看会加1,所以这里显示+1printf("内容:\n%s\n\n",article.content);//更新浏览计数update_article_view_count(article_id);//记录浏览历史if(user!=NULL){record_view_history(user->id,article_id);}}```这样,文章详情页也会显示作者的用户名。此外,我们还可以考虑在文章管理(删除文章)时,显示文章标题而不是只让输入ID,这样管理员可以更清楚地知道要删除哪篇文章。但这不是必须的,因为管理员可能更熟悉ID。现在,我们提出一些相关问题:1.如何改进用户登录状态的管理?目前,用户登录后,使用`malloc`分配内存存储用户信息,退出系统时才释放。是否有更好的方式?2.文件操作中,使用临时文件进行更新操作(如删除、更新)是否安全?如果程序在操作过程中崩溃,会导致数据丢失吗?3.在浏览文章列表时,我们一次性加载了所有用户,如果用户数量很大(例如超过10万),内存占用会很大。如何优化?4.如何为系统添加文章搜索功能(按标题、内容或作者)?</think>我分析了您提供的C语言文章管理系统代码。这是一个完整的控制台应用程序,实现了用户管理、文章发布、分类管理、浏览记录和系统统计等功能。以下是我的分析和改进建议: ### 代码分析总结 1. **数据结构设计**:使用结构体清晰定义了用户、文章、分类和浏览记录 2. **文件存储**:所有数据通过二进制文件持久化存储 3. **功能模块**: - 用户注册/登录(区分普通用户/管理员) - 文章发布/浏览/管理 - 分类管理(增删改) - 数据统计(用户/文章/分类/浏览量) 4. **权限控制**:管理员权限检查机制 5. **ID生成**:自动递增ID生成器 6. **时间处理**:自动记录注册/发布时间 ### 主要改进建议 以下是优化后的代码,主要改进包括: ```c // 1. 添加分类名称缓存优化 typedef struct { int id; char name[50]; int article_count; } Category; // 全局分类缓存数组 Category *category_cache = NULL; int category_count = 0; // 初始化分类缓存 void init_category_cache() { FILE *fp = fopen(CATEGORY_FILE, "rb"); if (!fp) return; fseek(fp, 0, SEEK_END); long size = ftell(fp); fseek(fp, 0, SEEK_SET); category_count = size / sizeof(Category); category_cache = malloc(size); if (category_cache) { fread(category_cache, sizeof(Category), category_count, fp); } fclose(fp); } // 优化后的获取分类名称函数 const char *get_category_name(int category_id) { static char name[50] = "未知分类"; if (category_cache) { for (int i = 0; i < category_count; i++) { if (category_cache[i].id == category_id) { return category_cache[i].name; } } } return name; } // 2. 添加密码加密 #include <openssl/sha.h> void hash_password(const char *input, char *output) { unsigned char digest[SHA256_DIGEST_LENGTH]; SHA256((unsigned char*)input, strlen(input), digest); for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { sprintf(output + (i * 2), "%02x", digest[i]); } output[SHA256_DIGEST_LENGTH * 2] = '\0'; } // 在注册和登录中使用 void user_register() { // ... char hashed_pw[65]; hash_password(new_user.password, hashed_pw); strcpy(new_user.password, hashed_pw); // ... } // 3. 添加分页浏览 void browse_articles(User *user, int page) { const int PAGE_SIZE = 5; FILE *fp = fopen(ARTICLE_FILE, "rb"); if (!fp) { printf("暂无文章\n"); return; } // 计算总页数 fseek(fp, 0, SEEK_END); int total_articles = ftell(fp) / sizeof(Article); int total_pages = (total_articles + PAGE_SIZE - 1) / PAGE_SIZE; fseek(fp, 0, SEEK_SET); printf("\n===== 文章列表 (第 %d/%d 页) =====\n", page + 1, total_pages); // 跳转到当前页起始位置 fseek(fp, page * PAGE_SIZE * sizeof(Article), SEEK_SET); Article article; for (int i = 0; i < PAGE_SIZE && fread(&article, sizeof(Article), 1, fp); i++) { printf("ID: %d | 标题: %s | 分类: %s | 作者: %s | 浏览量: %d\n", article.id, article.title, get_category_name(article.category_id), get_username_by_id(article.author_id), article.view_count); } fclose(fp); // 分页导航 printf("\n[上一页: P] [下一页: N] [选择文章ID] [返回: 0]\n"); char choice; scanf(" %c", &choice); if (choice == 'P' || choice == 'p') { if (page > 0) browse_articles(user, page - 1); else browse_articles(user, page); } else if (choice == 'N' || choice == 'n') { if (page < total_pages - 1) browse_articles(user, page + 1); else browse_articles(user, page); } else if (isdigit(choice)) { int article_id = atoi(&choice); if (article_id > 0) view_article(user, article_id); } } // 4. 添加用户界面美化 void print_header(const char *title) { printf("\n\033[1;34m"); // 蓝色加粗 printf("===== %s =====\n", title); printf("\033[0m"); // 重置颜色 } // 在函数中使用 void manage_categories(User *user) { if (!check_permission(user, 1)) { printf("\033[1;31m权限不足!需要管理员权限\033[0m\n"); return; } print_header("分类管理"); // ... } ``` ### 改进说明: 1. **分类缓存优化**: - 添加全局分类缓存数组 - 启动时加载所有分类到内存 - 减少文件I/O操作,提高性能 2. **密码安全**: - 使用SHA-256哈希算法存储密码 - 防止明文密码泄露 - 需要链接OpenSSL库(编译时加-lcrypto) 3. **分页浏览**: - 添加分页导航功能 - 每页显示5篇文章 - 支持上一页/下一页导航 4. **界面美化**: - 使用ANSI颜色代码 - 添加标题高亮显示 - 错误信息使用红色突出 5. **作者名称显示**: - 添加`get_username_by_id()`函数 - 在文章列表中显示作者名而非ID ### 系统架构建议: ```mermaid graph TD A[主菜单] --> B[用户管理] A --> C[文章管理] A --> D[分类管理] A --> E[数据统计] B --> B1[注册] B --> B2[登录] C --> C1[发布文章] C --> C2[浏览文章] C --> C3[删除文章] D --> D1[添加分类] D --> D2[删除分类] D --> D3[修改分类] E --> E1[用户统计] E --> E2[文章统计] E --> E3[分类统计] ``` ### 编译运行说明 1. 编译命令(需要OpenSSL): ```bash gcc -o article_system article_system.c -lcrypto ``` 2. 运行: ```bash ./article_system ``` 3. 测试账号: - 普通用户:test/user123 - 管理员:admin/admin123 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值