#include <stdio.h> #include <stdlib.h> #include <string.h>

// 定义最大段落长度 #define MAX_SIZE 100 // 定义每页显示字符数 #define PAGE_SIZE 10

// 定义小说结点结构体 typedef struct Node { char content[MAX_SIZE]; // 存储段落内容 struct Node* next; // 指向下一个结点 struct Node* prev; // 指向前一个结点 } Node;

// 定义小说编辑器结构体 typedef struct { Node* head; // 指向链表头结点 Node* current; // 指向当前结点 int totalNodes; // 结点总数 } NovelEditor;

// 定义用户结构体 typedef struct { char username[20]; // 用户名 char password[20]; // 密码 int is_author; // 是否为作者,1代表作者,0代表读者 } User;

// 初始化小说编辑器 void init(NovelEditor* editor) { editor->head = NULL; // 初始化头结点为NULL editor->current = NULL; // 初始化当前结点为NULL editor->totalNodes = 0; // 初始化结点总数为0 }

// 定位到指定段落 void locate(NovelEditor* editor, int segment, int offset) { Node* curr = editor->head; // 从头结点开始遍历链表 while (curr != NULL && segment > 1) { // 定位到指定段号 curr = curr->next; // 移动到下一个结点 segment--; // 段号减1 }

if (curr != NULL && offset <= MAX_SIZE) { // 检查段内偏移是否有效
    editor->current = curr; // 更新当前结点
    printf('定位成功到段号 %d,段内偏移 %d\n', segment, offset);
} else {
    printf('定位失败\n');
}

}

// 在当前位置插入字符串 void insert(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'; // 在字符串末尾添加结束符 '\0'

if (str[i] != '\0') { // 存在剩余未插入的字符串
    newNode->content[0] = '\0'; // 初始化新结点的内容为空字符串
    newNode->next = editor->current->next; // 将新结点链接到当前结点的后面
    newNode->prev = editor->current;
    editor->current->next = newNode;
    if (newNode->next != NULL) {
        newNode->next->prev = newNode;
    }
    editor->current = newNode; // 更新当前结点
    editor->totalNodes++; // 结点总数加1

    i++;
    while (str[i] != '\0' && i < MAX_SIZE) { // 拷贝剩余字符串到新结点
        editor->current->content[i - MAX_SIZE] = str[i];
        i++;
    }
    editor->current->content[i - MAX_SIZE] = '\0'; // 在字符串末尾添加结束符 '\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; // 连接当前结点的下一个结点
        if (nextNode->next != NULL) {
            nextNode->next->prev = editor->current; // 连接下一个结点的上一个结点
        }
        free(nextNode); // 释放下一个结点内存
        editor->totalNodes--; // 结点总数减1
    }
}

printf('字符串删除成功\n');

}

// 显示小说内容 void displayNovel(NovelEditor* editor) { Node* curr = editor->head; // 从头结点开始遍历链表 int segment = 1; // 段号 int i = 0; char str[100]; while (curr != NULL) { // 遍历输出链表中的内容 printf('段号 %d', segment); for (i = 0; i < strlen(curr->content); i++) { printf('%c', curr->content[i]); } curr = curr->next; // 移动到下一个结点 segment++; // 段号加1 } }

// 显示当前位置前m个字符的内容 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++; // 字符计数加1
    curr = curr->next; // 移动到下一个结点
}
printf('\n');

}

// 在小说中查找字符串 void search(NovelEditor* editor, char* searchString) { 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++; // 出现次数加1
        printf('字串 \'%s\' 在文章中的坐标为 (段序号: %d, 段内偏移: %d)\n', searchString, segment, offset + (int)(ptr - curr->content));
        ptr += strlen(searchString); // 移动到下一个字符
    }

    curr = curr->next; // 移动到下一个结点
    segment++; // 段号加1
    offset += MAX_SIZE; // 偏移量加最大段落长度
}

printf('字串 \'%s\' 在文章中的出现次数为 %d\n', searchString, count);

}

// 替换小说中的字符串 void replace(NovelEditor* editor, char* searchString, char* replacement) { 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++; // 替换次数加1
        int searchLength = strlen(searchString); // 查找字符串长度
        int replaceLength = strlen(replacement); // 替换字符串长度
        int shift = replaceLength - searchLength; // 替换前后字符串长度差

        if (shift != 0) { // 需要插入或删除结点以适应替换后的字符串
            Node* newNode = (Node*)malloc(sizeof(Node)); // 创建新的结点
            newNode->next = curr->next; // 连接新的结点到下一个结点
            newNode->prev = curr; // 连接新的结点到上一个结点
            curr->next = newNode; // 连接上一个结点到新的结点
            if (newNode->next != NULL) {
                newNode->next->prev = newNode; // 连接下一个结点到新的结点
            }
            editor->totalNodes++; // 结点总数加1

            char* temp = ptr + searchLength; // 指向查找字符串后的字符
            while (*temp != '\0') { // 将后续字符串拷贝到新结点
                newNode->content[temp - ptr - searchLength] = *temp;
                *temp = '\0'; // 替换为'\0'以避免重复拷贝
                temp++; // 指向下一个字符
            }
            newNode->content[temp - ptr - searchLength] = '\0'; // 在字符串末尾添加结束符 '\0'
        }

        strncpy(ptr, replacement, replaceLength); // 将替换字符串拷贝到结点中
        ptr += replaceLength; // 移动到下一个字符
    }

    curr = curr->next; // 移动到下一个结点
    segment++; // 段号加1
    offset += MAX_SIZE; // 偏移量加最大段落长度
}

printf('字串替换成功\n');

}

// 保存小说到文件 void saveNovel(NovelEditor* editor) { FILE* file = fopen('小说.txt', 'w'); // 打开名为'novel.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 readNovel(NovelEditor* editor) { FILE* file = fopen('C:\Users\djw\Desktop\小说.txt', 'r'); // 打开名为'novel.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)); // 创建新的结点
    strncpy(newNode->content, content, MAX_SIZE); // 使用strncpy复制内容
    newNode->next = NULL; // 初始化下一个结点为NULL
    newNode->prev = prev; // 连接上一个结点

    if (prev == NULL) { // 这是第一个结点
        editor->head = newNode; // 将第一个结点设置为头结点
    } else {
        prev->next = newNode; // 连接上一个结点到新的结点
    }

    prev = newNode; // 更新上一个结点
    editor->totalNodes++; // 结点总数加1
}

fclose(file); // 关闭文件

printf('小说读取成功\n');

}

// 统计小说中的字符数量 void countCharacters(NovelEditor* editor) { Node* curr = editor->head; // 从头结点开始遍历链表 int wordCount = 0; // 单词数量 int numberCount = 0; // 数字数量 int punctuationCount = 0; // 标点符号数量

while (curr != NULL) { // 遍历链表中的每个结点
    for (int i = 0; curr->content[i] != '\0'; i++) { // 遍历结点内容
        if ((curr->content[i] >= 'A' && curr->content[i] <= 'Z') || (curr->content[i] >= 'a' && curr->content[i] <= 'z')) {
            wordCount++; // 单词数量加1
        } else if (curr->content[i] >= '0' && curr->content[i] <= '9') {
            numberCount++; // 数字数量加1
        } else if (curr->content[i] == '.' || curr->content[i] == ',' || curr->content[i] == ':' || curr->content[i] == ';' || curr->content[i] == '!' || curr->content[i] == '?') {
            punctuationCount++; // 标点符号数量加1
        }
    }

    curr = curr->next; // 移动到下一个结点
}

printf('单词数量: %d\n', wordCount);
printf('数字数量: %d\n', numberCount);
printf('标点符号数量: %d\n', punctuationCount);

}

// 删除指定段落 void deleteParagraph(NovelEditor* editor, int segment) { Node* curr = editor->head; // 从头结点开始遍历链表 int currSegment = 1; // 当前段号

while (curr != NULL && currSegment < segment) { // 定位到指定段号
    curr = curr->next; // 移动到下一个结点
    currSegment++; // 当前段号加1
}

if (curr != NULL) { // 找到指定段号的结点
    if (curr->prev == NULL) { // 删除头结点
        editor->head = curr->next; // 将下一个结点设置为头结点
        if (curr->next != NULL) {
            curr->next->prev = NULL; // 连接下一个结点的上一个结点为NULL
        }
    } else { // 删除中间或尾部结点
        curr->prev->next = curr->next; // 连接上一个结点的下一个结点到下一个结点
        if (curr->next != NULL) {
            curr->next->prev = curr->prev; // 连接下一个结点的上一个结点到上一个结点
        }
    }

    free(curr); // 释放内存
    editor->totalNodes--; // 结点总数减1

    printf('段落删除成功\n');
} else {
    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 = editor->current->next; // 连接新的结点到下一个结点
newNode->prev = editor->current; // 连接新的结点到上一个结点

if (newNode->next != NULL) {
    newNode->next->prev = newNode; // 连接下一个结点的上一个结点到新的结点
}

editor->current->next = newNode; // 连接当前结点到新的结点

editor->totalNodes++; // 结点总数加1

printf('段落复制成功\n');

}

// 用户登录函数 User* login() { User* user = (User*)malloc(sizeof(User)); // 创建用户结构体

printf('请输入用户名: ');
scanf('%s', user->username);

printf('请输入密码: ');
scanf('%s', user->password);

printf('请选择用户类型(1-作者, 0-读者): ');
scanf('%d', &(user->is_author));

return user; // 返回用户结构体

}

// 主函数 int main() { NovelEditor editor; // 创建小说编辑器结构体 init(&editor); // 初始化小说编辑器

User* user = login(); // 用户登录
if (user->is_author) {
    printf('作者登录成功\n');
} else {
    printf('读者登录成功\n');
}

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);
        insert(&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);
        search(&editor, searchString);
        replace(&editor, searchString, replaceString);
        break;
    }
    case 7: // 小说保存功能
        saveNovel(&editor);
        break;
    case 8: // 小说读取功能
        readNovel(&editor);
        break;
    case 9: // 统计功能
        countCharacters(&editor);
        break;
    case 10: { // 段落删除功能
        int segment;
        printf('输入要删除的段落号: ');
        scanf('%d', &segment);
        deleteParagraph(&editor, segment);
        break;
    }
    case 11: // 段落复制功能
        copyParagraph(&editor);
        break;
    case 0: // 退出
        printf('退出小说编辑器系统\n');
        break;
    default: // 无效选择
        printf('无效的选择\n');
        break;
    }
} while (choice != 0); // 循环直到用户选择退出

return 0;

}

// 这段代码实现了一个小说编辑器系统,具有定位、插入、删除、显示、查找、替换、保存、读取、统计、删除段落和复制段落等功能。 // 通过结构体Node和NovelEditor实现了一个双向链表,每个结点存储一个段落的内容。 // init函数用于初始化NovelEditor结构体。 // locate函数用于根据给定的段号和段内偏移定位到指定位置。 // insert函数用于在当前位置插入字符串。 // deleteString函数用于删除指定长度的字符串。 // displayNovel函数用于显示整篇小说的内容。 // displayPage函数用于显示当前位置前m个字符的内容。 // search函数用于在小说中查找指定的字符串,并输出出现的次数和坐标。 // replace函数用于在小说中替换指定的字符串。 // saveNovel函数用于将小说保存到文件中。 // readNovel函数用于从文件中读取小说内容。 // countCharacters函数用于统计小说中的单词数量、数字数量和标点符号数量。 // deleteParagraph函数用于删除指定段落。 // copyParagraph函数用于复制当前段落。 // login函数用于用户登录,输入用户名、密码和用户类型。 // main函数用于程序的入口,根据用户选择调用相应的功能函数。

C语言实现小说编辑器系统:功能丰富,操作便捷

原文地址: https://www.cveoy.top/t/topic/bfWt 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录