关于scanf(“%[^\n]“,m.content);

本文解释了scanf函数如何从键盘读取字符串,以及其使用格式控制符的原理。同时指出scanf可能导致的缓冲区溢出风险,并推荐使用fgets函数以提高安全性。

这句代码的意思是从标准输入(键盘)读取一行字符串,不包括换行符,然后存储到变量 a 中。

scanf 是一个格式化输入函数,它可以根据指定的格式控制符,将输入的字符转换为相应的数据类型,并存储到对应的参数中。

这里的格式控制符是 "%[^\n]",它表示读取一个字符集合,其中包含除了换行符以外的所有字符。

a 是一个输入参数,它应该是一个字符数组或者指针,用来存储读取到的字符串。

注意,这句代码可能存在缓冲区溢出的风险,如果输入的字符串长度超过了 a 的大小,就会造成内存泄漏或者程序崩溃。

为了避免这种情况,建议使用 fgets 函数代替 scanf 函数,或者在格式控制符中指定最大长度,例如 "%99[^\n]" 表示最多读取 99 个字符。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <conio.h> #define MAX_USERS 100 #define MAX_ARTICLES 200 #define FILENAME_USERS "users.txt" #define FILENAME_ARTICLES "articles.txt" // 角色枚举 typedef enum { ROLE_ADMIN, ROLE_AUTHOR, ROLE_READER } UserRole; // 文章类型枚举 typedef enum { TYPE_POETRY, TYPE_NOVEL, TYPE_FAIRY_TALE } ArticleType; // 用户结构体 typedef struct { char username[50]; char password[50]; UserRole role; char gender; int age; } User; // 文章结构体 typedef struct { char title[100]; char author[50]; char publish_date[20]; ArticleType type; char content[500]; } Article; // 全局变量 User users[MAX_USERS]; Article articles[MAX_ARTICLES]; int userCount = 0; int articleCount = 0; User currentUser; // 当前登录用户 // 函数声明 void loadData(); void saveData(); void registerUser(); int login(); void showUserMenu(); void manageProfile(); void manageArticles(); void publishArticle(); void editArticle(); void viewArticles(); void searchArticle(); void viewMyArticles(); void browseArticles(); void displayArticle(int index); void deleteArticle(); void listAllUsers(); const char *getRoleName(UserRole role) { switch (role) { case ROLE_ADMIN: return "管理员"; case ROLE_AUTHOR: return "作者"; case ROLE_READER: return "读者"; default: return "未知"; } } const char *getArticleTypeName(ArticleType type) { switch (type) { case TYPE_POETRY: return "诗歌"; case TYPE_NOVEL: return "小说"; case TYPE_FAIRY_TALE: return "童话"; default: return "未知"; } } // 加载数据 void loadData() { // 加载用户数据 FILE *userFile = fopen(FILENAME_USERS, "r"); if (userFile) { while (fscanf(userFile, "%49[^|]|%49[^|]|%d|%c|%d\n", users[userCount].username, users[userCount].password, &users[userCount].role, &users[userCount].gender, &users[userCount].age) == 5) { userCount++; } fclose(userFile); } // 加载文章数据 FILE *articleFile = fopen(FILENAME_ARTICLES, "r"); if (articleFile) { while (fscanf(articleFile, "%99[^|]|%49[^|]|%19[^|]|%d|%499[^\n]\n", articles[articleCount].title, articles[articleCount].author, articles[articleCount].publish_date, &articles[articleCount].type, articles[articleCount].content) == 5) { articleCount++; } fclose(articleFile); } } // 保存数据 void saveData() { // 保存用户数据 FILE *userFile = fopen(FILENAME_USERS, "w"); for (int i = 0; i < userCount; i++) { fprintf(userFile, "%s|%s|%d|%c|%d\n", users[i].username, users[i].password, users[i].role, users[i].gender, users[i].age); } fclose(userFile); // 保存文章数据 FILE *articleFile = fopen(FILENAME_ARTICLES, "w"); for (int i = 0; i < articleCount; i++) { fprintf(articleFile, "%s|%s|%s|%d|%s\n", articles[i].title, articles[i].author, articles[i].publish_date, articles[i].type, articles[i].content); } fclose(articleFile); } // 用户注册 void registerUser() { if (userCount >= MAX_USERS) { printf("用户数量已达上限!\n"); return; } User newUser; printf("\n=== 用户注册 ===\n"); printf("请输入用户名: "); scanf("%49s", newUser.username); // 检查用户名是否已存在 for (int i = 0; i < userCount; i++) { if (strcmp(users[i].username, newUser.username) == 0) { printf("用户名已存在!\n"); return; } } printf("请输入密码: "); scanf("%49s", newUser.password); int roleChoice; printf("选择角色 (0-管理员, 1-作者, 2-读者): "); scanf("%d", &roleChoice); newUser.role = (UserRole)roleChoice; printf("性别 (M/F): "); scanf(" %c", &newUser.gender); newUser.gender = toupper(newUser.gender); printf("年龄: "); scanf("%d", &newUser.age); users[userCount++] = newUser; saveData(); printf("注册成功!\n"); } // 用户登录 int login() { char username[50], password[50]; printf("\n=== 用户登录 ===\n"); printf("用户名: "); scanf("%49s", username); printf("密码: "); scanf("%49s", password); for (int i = 0; i < userCount; i++) { if (strcmp(users[i].username, username) == 0 && strcmp(users[i].password, password) == 0) { currentUser = users[i]; printf("登录成功!欢迎 %s (%s)\n", currentUser.username, getRoleName(currentUser.role)); return 1; } } printf("用户名或密码错误!\n"); return 0; } // 修改个人信息 void manageProfile() { printf("\n=== 个人信息管理 ===\n"); printf("当前信息: \n"); printf("用户名: %s\n", currentUser.username); printf("性别: %c\n", currentUser.gender); printf("年龄: %d\n", currentUser.age); int choice; printf("\n1. 修改密码\n2. 修改性别\n3. 修改年龄\n0. 返回\n选择: "); scanf("%d", &choice); switch (choice) { case 1: printf("新密码: "); scanf("%49s", currentUser.password); break; case 2: printf("新性别 (M/F): "); scanf(" %c", &currentUser.gender); currentUser.gender = toupper(currentUser.gender); break; case 3: printf("新年龄: "); scanf("%d", &currentUser.age); break; case 0: return; default: printf("无效选择!\n"); } // 更新全局用户数组 for (int i = 0; i < userCount; i++) { if (strcmp(users[i].username, currentUser.username) == 0) { users[i] = currentUser; break; } } saveData(); printf("信息更新成功!\n"); } // 发布文章 void publishArticle() { if (articleCount >= MAX_ARTICLES) { printf("文章数量已达上限!\n"); return; } Article newArticle; printf("\n=== 发布新文章 ===\n"); printf("标题: "); scanf(" %[^\n]", newArticle.title); // 读取整行 // 检查标题是否已存在 for (int i = 0; i < articleCount; i++) { if (strcmp(articles[i].title, newArticle.title) == 0) { printf("标题已存在!\n"); return; } } strcpy(newArticle.author, currentUser.username); printf("发布日期 (YYYY-MM-DD): "); scanf("%19s", newArticle.publish_date); int typeChoice; printf("类型 (0-诗歌, 1-小说, 2-童话): "); scanf("%d", &typeChoice); newArticle.type = (ArticleType)typeChoice; printf("内容 (不超过500字符): "); getchar(); // 清除缓冲区 fgets(newArticle.content, sizeof(newArticle.content), stdin); newArticle.content[strcspn(newArticle.content, "\n")] = '\0'; // 移除换行符 articles[articleCount++] = newArticle; saveData(); printf("文章发布成功!\n"); } // 编辑文章 void editArticle() { printf("\n=== 编辑文章 ===\n"); viewMyArticles(); if (articleCount == 0) return; int index; printf("输入要编辑的文章编号 (-1取消): "); scanf("%d", &index); if (index < 0 || index >= articleCount) { printf("无效编号!\n"); return; } // 检查权限:作者只能编辑自己的文章,管理员可以编辑所有 if (currentUser.role != ROLE_ADMIN && strcmp(articles[index].author, currentUser.username) != 0) { printf("无权编辑此文章!\n"); return; } Article *art = &articles[index]; printf("\n当前标题: %s\n新标题: ", art->title); getchar(); fgets(art->title, sizeof(art->title), stdin); art->title[strcspn(art->title, "\n")] = '\0'; printf("新内容: "); fgets(art->content, sizeof(art->content), stdin); art->content[strcspn(art->content, "\n")] = '\0'; saveData(); printf("文章修改成功!\n"); } // 浏览文章目录 void browseArticles() { printf("\n=== 文章目录 ===\n"); printf("%-5s %-30s %-15s %-10s %-10s\n", "ID", "标题", "作者", "类型", "发布日期"); for (int i = 0; i < articleCount; i++) { printf("%-5d %-30s %-15s %-10s %-10s\n", i, articles[i].title, articles[i].author, getArticleTypeName(articles[i].type), articles[i].publish_date); } } // 查看文章详情 void displayArticle(int index) { if (index < 0 || index >= articleCount) { printf("无效文章ID!\n"); return; } Article art = articles[index]; printf("\n=== 文章详情 ===\n"); printf("标题: %s\n", art.title); printf("作者: %s\n", art.author); printf("类型: %s\n", getArticleTypeName(art.type)); printf("发布日期: %s\n", art.publish_date); printf("内容:\n%s\n", art.content); } // 搜索文章 void searchArticle() { char title[100]; printf("\n=== 文章搜索 ===\n"); printf("输入文章标题: "); scanf(" %[^\n]", title); int found = 0; for (int i = 0; i < articleCount; i++) { if (strstr(articles[i].title, title) != NULL) { displayArticle(i); found = 1; break; } } if (!found) { printf("未找到相关文章!\n"); } } // 查看我的文章 void viewMyArticles() { printf("\n=== 我的文章 ===\n"); int count = 0; for (int i = 0; i < articleCount; i++) { if (strcmp(articles[i].author, currentUser.username) == 0) { printf("[%d] %s (%s)\n", i, articles[i].title, articles[i].publish_date); count++; } } if (count == 0) { printf("您还没有发布文章!\n"); } } // 删除文章 void deleteArticle() { viewMyArticles(); if (articleCount == 0) return; int index; printf("输入要删除的文章编号 (-1取消): "); scanf("%d", &index); if (index < 0 || index >= articleCount) { printf("无效编号!\n"); return; } // 检查权限 if (currentUser.role != ROLE_ADMIN && strcmp(articles[index].author, currentUser.username) != 0) { printf("无权删除此文章!\n"); return; } // 删除文章 for (int i = index; i < articleCount - 1; i++) { articles[i] = articles[i + 1]; } articleCount--; saveData(); printf("文章删除成功!\n"); } // 列出所有用户(管理员) void listAllUsers() { if (currentUser.role != ROLE_ADMIN) { printf("权限不足!\n"); return; } printf("\n=== 用户列表 ===\n"); printf("%-20s %-10s %-6s %-4s\n", "用户名", "角色", "性别", "年龄"); for (int i = 0; i < userCount; i++) { printf("%-20s %-10s %-6c %-4d\n", users[i].username, getRoleName(users[i].role), users[i].gender, users[i].age); } } // 文章管理菜单 void manageArticles() { int choice; do { printf("\n=== 文章管理 ===\n"); printf("1. 发布文章\n"); printf("2. 编辑文章\n"); printf("3. 查看我的文章\n"); printf("4. 删除文章\n"); printf("0. 返回主菜单\n"); printf("选择: "); scanf("%d", &choice); switch (choice) { case 1: publishArticle(); break; case 2: editArticle(); break; case 3: viewMyArticles(); break; case 4: deleteArticle(); break; case 0: break; default: printf("无效选择!\n"); } } while (choice != 0); } // 主菜单 void mainMenu() { int choice; do { printf("\n=== 主菜单 ===\n"); printf("1. 浏览文章\n"); printf("2. 搜索文章\n"); if (currentUser.role == ROLE_ADMIN || currentUser.role == ROLE_AUTHOR) { printf("3. 文章管理\n"); } printf("4. 个人信息管理\n"); if (currentUser.role == ROLE_ADMIN) { printf("5. 用户管理\n"); } printf("0. 退出系统\n"); printf("选择: "); scanf("%d", &choice); switch (choice) { case 1: browseArticles(); break; case 2: searchArticle(); break; case 3: if (currentUser.role == ROLE_ADMIN || currentUser.role == ROLE_AUTHOR) { manageArticles(); } else { printf("权限不足!\n"); } break; case 4: manageProfile(); break; case 5: if (currentUser.role == ROLE_ADMIN) { listAllUsers(); } else { printf("权限不足!\n"); } break; case 0: printf("感谢使用!\n"); exit(0); default: printf("无效选择!\n"); } } while (1); } // 用户菜单 void showUserMenu() { int choice; do { printf("\n=== 主界面 ===\n"); printf("1. 登录\n"); printf("2. 注册\n"); printf("0. 退出\n"); printf("选择: "); scanf("%d", &choice); switch (choice) { case 1: if (login()) { mainMenu(); } break; case 2: registerUser(); break; case 0: printf("感谢使用!\n"); exit(0); default: printf("无效选择!\n"); } } while (1); } int main() { loadData(); showUserMenu(); return 0; } 浏览文章可以查看文章详情
06-27
// 用户结构体 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; // 用户注册 void user_register() { User new_user; printf("请输入用户名: "); scanf("%s", new_user.username); 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("users.dat", "ab"); fwrite(&new_user, sizeof(User), 1, fp); fclose(fp); printf("注册成功!用户ID: %d\n", new_user.id); } // 用户登录 User *user_login() { char username[50], password[50]; printf("用户名: "); scanf("%s", username); printf("密码: "); scanf("%s", password); FILE *fp = fopen("users.dat", "rb"); 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("articles.dat", "ab"); fwrite(&new_article, sizeof(Article), 1, fp); fclose(fp); // 更新分类统计 update_category_count(new_article.category_id, 1); printf("文章发布成功!ID: %d\n", new_article.id); } // 权限检查函数 int check_permission(User *user, int required_role) { if (user == NULL) return 0; // 未登录 if (user->role >= required_role) return 1; // 权限足够 return 0; // 权限不足 } // 管理员操作示例 void delete_article(User *user) { if (!check_permission(user, 1)) { printf("权限不足!需要管理员权限\n"); return; } int article_id; printf("输入要删除的文章ID: "); scanf("%d", &article_id); // 删除操作实现... printf("文章 %d 已删除\n", article_id); } // 浏览文章 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标题: %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("%s\n\n", article.content); // 更新浏览计数 update_article_view_count(article_id); // 记录浏览历史 if (user != NULL) { record_view_history(user->id, article_id); } } // 记录浏览历史 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("views.dat", "ab"); fwrite(&record, sizeof(ViewRecord), 1, fp); fclose(fp); } 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: return 0; default: printf("无效选择!\n"); } } return 0; } 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: return 0; default: printf("无效选择!\n"); } } return 0; }
06-20
#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
#include <stdio.h> #include <stdlib.h> #define N 193 //每月最大字符数量 char content[2652]; //大字符组 int content_i=0; char month_table[12][N]; int month_days[12]={31,28,31,30,31,30,31,31,30,31,30,31}; void label() { char a[]="日 一 二 三 四 五 六"; for(int i=0;a[i];++i){ content[content_i++]=a[i]; } } int first_day(int c,int y,int m,int sit) //某年某月第一天所对应的星期数 { m+=1; int w=c/4-c*2+y+y/4+(m+1)*13/5; return (w-sit)%7; } void convert(int day,char *out) //数字转字符函数 { out[0]=(day/10)+'0'; out[1]=(day%10)+'0'; } void write(int m,int w) //写入某月的日期表 { char *month=month_table[m]; int i=0; //在字符组中的位置 int day=1; //日期 for(int k=w;k>0;k--){ for(int j=0;j<4;++j) month[i++]=' '; } int row=0; //行数特定 for(;day<=month_days[m];++day){ char e[2]; convert(day,e); month[i++]=e[0]; month[i++]=e[1]; if((++w)%7==0){ month[i++]='x'; ++row; } else for(int j=0;j<2;++j) month[i++]=' '; } for(;row<7;++row){ for(;(++w)%7;){ for(int j=0;j<5;++j) month[i++]=' '; } month[i++]='x'; ++w; } while(i<N){ month[i++]=' '; } } void output(int *order) //根据次序,写进大字符组 { int k=order[12]; //用于"\t"和"\n"的替换 int k_bak=k; int i=0; int j[4]={0,0,0,0}; int b=0; while(b<=11){ int a=0; for(;a<4;++a){ j[a]=0; } for(a=0;a<=k_bak;++a){ label(); if(a<k_bak) content[content_i++]='\t'; } content[content_i++]='\n'; i=0; for(a=0;a<6;){ for(;j[i]<N;++j[i]){ if(month_table[order[i+b]][j[i]]=='x'){ if(k--){ content[content_i++]='\t'; if(!a) content[content_i++]=' '; } else{ content[content_i++]='\n'; k=k_bak; ++a; } if(++i>k_bak)i=0; } else{ content[content_i++]=month_table[order[i+b]][j[i]]; } } k=k_bak; } content[content_i++]='\n'; b+=(k_bak+1); } content[content_i]='\0'; } int* mode_select(int mode) //模式选择 { switch(mode){ case 1:{ static int temp[13]={0,1,2,3,4,5,6,7,8,9,10,11,0}; return temp; } case 2:{ static int temp[13]={0,6,1,7,2,8,3,9,4,10,5,11,1}; return temp; } case 3:{ static int temp[13]={0,4,8,1,5,9,2,6,10,3,7,11,2}; return temp; } case 4:{ static int temp[13]={0,3,6,9,1,4,7,10,2,5,8,11,3}; return temp; } case 5:{ static int temp[13]={0,2,4,6,8,10,1,3,5,7,9,11,5}; return temp; } case 6:{ static int temp[13]={0,1,2,3,4,5,6,7,8,9,10,11,11}; return temp; } case 7:{ static int temp[13]={0,1,2,3,4,5,6,7,8,9,10,11,1}; return temp; } case 8:{ static int temp[13]={0,1,2,3,4,5,6,7,8,9,10,11,2}; return temp; } case 9:{ static int temp[13]={0,1,2,3,4,5,6,7,8,9,10,11,3}; return temp; } case 0:{ static int temp[13]={0,1,2,3,4,5,6,7,8,9,10,11, 5}; return temp; } default: break; } } int main() { printf("输入年份:"); int y; scanf("%d",&y); int situation=1; //二月有特殊情况,需要调整 if ((y%4==0&&y%100!=0)||y%400==0){ //计算平闰年 month_days[1]=29; situation=2; } int c=y/100; y%=100; //此时年份为c*100+y for(int m=0;m<12;++m) { //计算并写入某月的日期表 int w; if (!m){ w=first_day(c,y-1,m+12,0); } else if(m==1){ w=first_day(c,y,m+12,situation); } else{ w=first_day(c,y,m,0); } write(m,w); } printf("输入以下序号,选择想要的打印格式\n"); printf(" 1. 12行1列\n 2. 6行2列(竖向)\n 3. 4行3列(竖向)\n 4. 3行4列(竖向)\n"); printf(" 5. 2行6列(竖向)\n 6. 1行12列\n 7. 6行2列(横向)\n 8. 4行3列(横向)\n"); printf(" 9. 3行4列(横向)\n 0. 2行6列(横向)\n"); int selection; scanf("%d",&selection); int *mode=mode_select(selection); output(mode); FILE *fp = fopen("target.txt", "w"); //打开文件 if (fp == NULL) { //检查文件是否成功打开 perror("无法打开文件"); return 1; } fprintf(fp,"%s",content); printf("%s",content); fclose(fp); return 0; } 以上是我的代码,我不想使用char month_table[12][N]了,改成 typedef struct { char data[N]; // 存储格式化后的日历行,以 'x' 分隔每行 } Month; // 年结构体:包含12个月 typedef struct { Month months[12]; } Year; 请修改一些变量
最新发布
11-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值