C语言实现的小说编辑器系统 - 代码优化与功能增强
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 100
// 结点数据结构
typedef struct Node {
char content[MAX_SIZE];
struct Node* next;
} Node;
// 小说编辑器系统数据结构
typedef struct NovelEditor {
Node* head; // 头结点
Node* current; // 当前结点
int totalNodes; // 结点总数
} NovelEditor;
// 初始化小说编辑器系统
void init(NovelEditor* editor) {
editor->head = NULL;
editor->current = NULL;
editor->totalNodes = 0;
}
// 定位功能
void locate(NovelEditor* editor, int segment, int offset) {
Node* curr = editor->head; // 从头结点开始遍历链表
while (curr != NULL && segment > 1) { // 定位到指定段号
curr = curr->next;
segment--;
}
if (curr != NULL && offset <= MAX_SIZE) { // 检查段内偏移是否有效
editor->current = curr; // 更新当前结点
printf('定位成功到段号 %d,段内偏移 %d\n', segment, offset);
}
else {
printf('定位失败\n');
}
}
// 字符串插入功能
void insertString(NovelEditor* editor, char* str) {
if (editor->current == NULL) {
printf('请先定位到位置再插入字符串\n');
return;
}
int i = 0;
Node* newNode = (Node*)malloc(sizeof(Node)); // 创建新结点
while (str[i] != '\0' && editor->current->content[i] != '\0' && i < MAX_SIZE) { // 拷贝字符串到当前结点
editor->current->content[i] = str[i];
i++;
}
editor->current->content[i] = '\0';
if (str[i] != '\0') { // 存在剩余未插入的字符串
newNode->content[0] = '\0';
newNode->next = editor->current->next;
editor->current->next = newNode;
editor->current = newNode;
editor->totalNodes++;
i++;
while (str[i] != '\0' && i < MAX_SIZE) { // 拷贝剩余字符串到新结点
editor->current->content[i - MAX_SIZE] = str[i];
i++;
}
editor->current->content[i - MAX_SIZE] = '\0';
}
printf('字符串插入成功\n');
}
// 字符串删除功能
void deleteString(NovelEditor* editor, int length) {
if (editor->current == NULL) {
printf('请先定位到位置再删除字符串\n');
return;
}
int i = 0;
while (editor->current->content[i] != '\0' && i < length && i < MAX_SIZE) { // 删除指定长度的字符串
editor->current->content[i] = '\0';
i++;
}
if (editor->current->content[i] == '\0') { // 当前结点已删除完毕
Node* nextNode = editor->current->next;
if (nextNode != NULL && nextNode->content[0] != '\0') { // 合并下一个结点
while (i - MAX_SIZE < MAX_SIZE && nextNode->content[i - MAX_SIZE] != '\0') {
editor->current->content[i - MAX_SIZE] = nextNode->content[i - MAX_SIZE];
nextNode->content[i - MAX_SIZE] = '\0';
i++;
}
}
else { // 删除下一个结点
editor->current->next = nextNode->next;
free(nextNode);
editor->totalNodes--;
}
}
printf('字符串删除成功\n');
}
// 小说显示功能
void displayNovel(NovelEditor* editor) {
Node* curr = editor->head; // 从头结点开始遍历链表
int segment = 1; // 段号
while (curr != NULL) { // 遍历输出链表中的内容
printf('段号 %d: %s\n', segment, curr->content);
curr = curr->next;
segment++;
}
}
// 翻页显示功能
void displayPage(NovelEditor* editor, int m) {
if (editor->current == NULL) {
printf('请先定位到位置再显示页面\n');
return;
}
Node* curr = editor->current;
int count = 0; // 统计字符数
printf('当前位置前 %d 个字符内容为一页:\n', m);
while (curr != NULL && count < m) { // 输出 m 个字符
printf('%s', curr->content);
count++;
curr = curr->next;
}
printf('\n');
}
// 字符串查找和替换功能
void searchAndReplace(NovelEditor* editor, char* searchString, char* replaceString) {
Node* curr = editor->head; // 从头结点开始遍历链表
int segment = 1; // 段号
int offset = 0; // 段内偏移
int count = 0; // 字串出现次数
while (curr != NULL) { // 遍历链表中的每个结点
char* ptr = curr->content;
while ((ptr = strstr(ptr, searchString)) != NULL) { // 在结点内容中查找字串
count++;
printf('字串 '%s' 在文章中的坐标为 (段序号: %d, 段内偏移: %d)\n', searchString, segment, offset + (int)(ptr - curr->content));
ptr += strlen(searchString);
}
curr = curr->next;
segment++;
offset += MAX_SIZE;
}
printf('字串 '%s' 在文章中的出现次数为 %d\n', searchString, count);
printf('是否替换该字串?(Y/N): ');
char choice;
scanf(' %c', &choice);
if (choice == 'Y' || choice == 'y') {
curr = editor->head;
segment = 1;
offset = 0;
while (curr != NULL) { // 遍历链表中的每个结点
char* ptr = curr->content;
while ((ptr = strstr(ptr, searchString)) != NULL) { // 在结点内容中查找字串
count++;
int searchLength = strlen(searchString);
int replaceLength = strlen(replaceString);
int shift = replaceLength - searchLength;
if (shift != 0) { // 需要插入或删除结点以适应替换后的字符串
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->next = curr->next;
curr->next = newNode;
editor->totalNodes++;
char* temp = ptr + searchLength;
while (*temp != '\0') { // 将后续字符串拷贝到新结点
newNode->content[temp - ptr - searchLength] = *temp;
*temp = '\0';
temp++;
}
newNode->content[temp - ptr - searchLength] = '\0';
}
strncpy(ptr, replaceString, replaceLength); // 将替换字符串拷贝到结点中
ptr += replaceLength;
}
curr = curr->next;
segment++;
offset += MAX_SIZE;
}
printf('字串替换成功\n');
}
}
// 小说保存功能
void saveNovel(NovelEditor* editor) {
FILE* file = fopen('小说.txt', 'w'); // 打开名为'小说.txt'的文件以写入模式
if (file == NULL) {
printf('无法保存文件\n');
return;
}
Node* curr = editor->head; // 从头结点开始遍历链表
while (curr != NULL) { // 将链表中的内容写入文件
fprintf(file, '%s', curr->content);
curr = curr->next;
}
fclose(file); // 关闭文件
printf('小说保存成功\n');
}
// 小说读取功能
void loadNovel(NovelEditor* editor) {
FILE* file = fopen('小说.txt', 'r'); // 打开名为'小说.txt'的文件以读取模式
if (file == NULL) {
printf('无法读取文件\n');
return;
}
char content[MAX_SIZE];
Node* prev = NULL;
while (fgets(content, MAX_SIZE, file) != NULL) { // 从文件中逐行读取内容
Node* newNode = (Node*)malloc(sizeof(Node));
strcpy(newNode->content, content);
newNode->next = NULL;
if (prev == NULL) {
editor->head = newNode;
}
else {
prev->next = newNode;
}
prev = newNode;
editor->totalNodes++;
}
fclose(file); // 关闭文件
printf('小说读取成功\n');
}
// 统计功能
void countCharacters(NovelEditor* editor) {
Node* curr = editor->head; // 从头结点开始遍历链表
int wordCount = 0, digitCount = 0, symbolCount = 0;
while (curr != NULL) { // 遍历链表中的每个结点
for (int i = 0; curr->content[i] != '\0' && i < MAX_SIZE; i++) { // 统计每个字符的类型
if ((curr->content[i] >= 'a' && curr->content[i] <= 'z') || (curr->content[i] >= 'A' && curr->content[i] <= 'Z')) {
wordCount++;
}
else if (curr->content[i] >= '0' && curr->content[i] <= '9') {
digitCount++;
}
else {
symbolCount++;
}
}
curr = curr->next;
}
printf('单词数量: %d\n', wordCount);
printf('数字数量: %d\n', digitCount);
printf('标点符号数量: %d\n', symbolCount);
}
// 段落删除功能
void deleteParagraph(NovelEditor* editor, int segment) {
Node* curr = editor->head; // 从头结点开始遍历链表
Node* prev = NULL; // 当前结点的前一个结点
int currentSegment = 1; // 当前段号
while (curr != NULL && currentSegment < segment) { // 定位到指定段号
prev = curr;
curr = curr->next;
currentSegment++;
}
if (curr == NULL) {
printf('段落不存在\n');
return;
}
if (currentSegment == 1) { // 删除头结点
editor->head = curr->next;
}
else {
prev->next = curr->next; // 删除中间或末尾结点
}
free(curr); // 释放内存
editor->totalNodes--;
printf('段落删除成功\n');
}
// 段落复制功能
void copyParagraph(NovelEditor* editor) {
if (editor->current == NULL) {
printf('请先定位到段落再复制\n');
return;
}
Node* newNode = (Node*)malloc(sizeof(Node));
strcpy(newNode->content, editor->current->content);
newNode->next = NULL;
Node* curr = editor->head;
if (curr == NULL) {
editor->head = newNode; // 复制到空链表中
}
else {
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = newNode; // 复制到链表末尾
}
editor->totalNodes++;
printf('段落复制成功\n');
}
// 用户登录
void login(NovelEditor* editor, int userType) {
if (userType == 1) {
printf('作者登录成功\n');
}
else if (userType == 2) {
printf('读者登录成功\n');
}
else {
printf('无效的用户类型\n');
}
}
int main() {
NovelEditor editor;
init(&editor);
// 示例使用
int userType;
printf('选择用户类型进行登录 (1 - 作者, 2 - 读者): ');
scanf('%d', &userType);
login(&editor, userType);
int choice;
do {
printf('\n小说编辑器系统主菜单\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('9. 统计功能\n');
printf('10. 段落删除功能\n');
printf('11. 段落复制功能\n');
printf('0. 退出\n');
printf('请选择操作: ');
scanf('%d', &choice);
switch (choice) {
case 1:
int segment, offset;
printf('输入段号和段内偏移: ');
scanf('%d %d', &segment, &offset);
locate(&editor, segment, offset);
break;
case 2:
char insertString[MAX_SIZE];
printf('输入要插入的字符串: ');
scanf('%s', insertString);
insertString(&editor, insertString);
break;
case 3:
int length;
printf('输入要删除的字符串长度: ');
scanf('%d', &length);
deleteString(&editor, length);
break;
case 4:
displayNovel(&editor);
break;
case 5:
int m;
printf('输入每页字符数 m: ');
scanf('%d', &m);
displayPage(&editor, m);
break;
case 6:
char searchString[MAX_SIZE], replaceString[MAX_SIZE];
printf('输入要查找的字符串: ');
scanf('%s', searchString);
printf('输入要替换的字符串: ');
scanf('%s', replaceString);
searchAndReplace(&editor, searchString, replaceString);
break;
case 7:
saveNovel(&editor);
break;
case 8:
loadNovel(&editor);
break;
case 9:
countCharacters(&editor);
break;
case 10:
int deleteSegment;
printf('输入要删除的段落号: ');
scanf('%d', &deleteSegment);
deleteParagraph(&editor, deleteSegment);
break;
case 11:
copyParagraph(&editor);
break;
case 0:
printf('退出小说编辑器系统\n');
break;
default:
printf('无效的选择\n');
break;
}
} while (choice != 0);
return 0;
}
现在,保存的文件名固定为'小说.txt',并且小说读取功能将从该文件中读取内容。
原文地址: https://www.cveoy.top/t/topic/bbcq 著作权归作者所有。请勿转载和采集!