不知你们搜这个的时候是不是帝国理工的人,反正我是,我当初想上网搜一下别人的代码参考,但是很多都是对不上的,大多数的代码都是英文字符串的。自己也是找了很久办法,算法也是自己用笔画图慢慢推的,期间太辛苦了,所以也不想让你们那么辛苦,纯纯造福学弟学妹们好吧,全代码在下边,自己去参考吧!(千万不要懒得写就全抄,你能搜到的东西,别人也肯定能,查重出来还是挺严重的好吧)
代码很长,我写的算法可能比较绕,但是我已经尽量多一些注释了,就凑合着看吧
bug的话……我已经试了一些了,已经写的我好烦了,目前还没有试出来什么bug,你们看着办吧
不过我估计这个代码只适合文件里只有中文的,混杂着英文跟数字的话就会出一些问题,因为如果要辨识中英文数字的话,很多地方又要分别辨识ascall码的正负性,我觉得好麻烦,就算了,毕竟这只是作业不用于商业用途。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE 50 //预设定一行25个字(一个字占两个字节)
#define PAGE 5 //预设定一页最多显示5行字
#define MAXSIZE 100 //预设定一个结点最大存放100个元素
typedef struct novel{
char data[MAXSIZE]; //存放数据元素的数组
int number; //结点号,方便分页显示
int para; //段号
int lnum; //行号,规定一行50个字即一个结点为一行,刚好为一个结点
struct novel* Llink;//前指针
struct novel* Rlink;//后指针
}Novel;
//编辑器大标题,永远出现在程序的最顶端
void HeadWord()
{
printf("_____________________________________________________________________________________________________\n\n");
printf("******** 欢迎使用欢乐小说编辑器! ********\n");
printf("_____________________________________________________________________________________________________\n\n");
}
//文件读入
void ReadNovel(Novel *head, Novel *next, Novel *info)
{
int i = 0, para = 1, lnum = 1; //para用于记录当前段号
char c;
FILE* fp; //文件指针
if ((fp = fopen("novel.txt", "r")) == NULL)
{
printf("\n文件无法打开!\n");
exit(0);
}
printf("\n正在装入文件!\n");
while ((c = fgetc(fp)) != EOF)
{
if (i == MAXSIZE || c == '\n') //当结点空间用完或检测到换行,则创建新结点
{
if (c == '\n') //若检测到是换行,则段数加一
{
info->data[i] = '\0'; //表明这个结点的有效内容完结了,后面都是无效内容
para++;
lnum = 1;
c = fgetc(fp);
}
else lnum++; //否则就是结点满了,行号加一,段数不变
if (c != EOF) //若未读完文件则申请结点
{
next = (Novel*)malloc(sizeof(Novel)); //申请结点,连接上新结点并让info指向新节点
info->Rlink = next;
next->Llink = info;
next->Rlink = NULL;
next->para = para;
next->lnum = lnum;
next->number = info->number + 1;
info = next;
i = 0;
}
else //若已读完则令最后为‘\0’表示后面为无效内容(文件最后一个为换行符)
{
info->data[i] = '\0';
break;
}
}
info->data[i] = c;
i++;
}
if(i != MAXSIZE) info->data[i] = '\0'; //以免文件最后一位不是换行符就不加结束符
info->Rlink = NULL; //读取文件完毕
info = head; //指针回归到头结点方便后续其他操作
next = head;
printf("\n读取文件完毕!\n\n");
fclose(fp);
}
//从链表里找出对应长度的字符串
int findstr(char str[], char* p, Novel* info, int i)
{
int str_len = 0, j = 0, k, have; //have用于记录保存取出数组中已经有的数据数量
str_len = strlen(str); //记录输入字符串的长度
if (i <= MAXSIZE - str_len) //若i大于,则说明结点剩余文字不足
{
k = 0; //k为暂存取出字符串的数组的数组下标
for (j = i; j < str_len + i; j++) //从结点中取出来与输入字符串同等长度的字符串
{
if (info->data[j] == '\0') //若检测到结束符则不需要继续检测下去
{
return 1;
}
else
{
p[k] = info->data[j];
k++;
}
}
}
else if (info->Rlink != NULL && info->para == info->Rlink->para) //取出文字需要跨越两个同一段的结点
{
k = 0; //k为暂存取出字符串的数组的数组下标
for (j = i; j < MAXSIZE; j++) //从第一个结点中取出字符,直到取完
{
p[k] = info->data[j];
k++;
}
have = k;
info = info->Rlink; //info指向下个结点
for (j = 0; j < str_len - have; j++) //从第二个结点中取出剩余数量的字符
{
p[k] = info->data[j];
k++;
}
info = info->Llink;
return 1;
}
else return 1; //结点剩余字符串少于输入的字符串,且与下个结点不为同一段,或已经是最后一段
return 0;
}
//搜查小说内容
void SearchNovel(Novel* head, Novel* info, char str[])
{
int choice = -1, i, detm = 0; //str_len用于记录输入字符串的长度,detm=1则说明已循环完一个结点,将i置回初值
char takestr[20] = { '\0' }; //暂存从结点中取出来的字符串,再去与str做比较
int found = 0; //found = 0代表还没找到该字符串
i = 0; //i记录从结点中取出文字的位置
while (info != NULL) //字符串匹对,直到找完文章为止
{
detm = findstr(str, takestr, info, i); //返回值返回当前链表中