先把代码贴上吧,还有好多地方要完善,以后有时间再一点儿一点儿的完善吧
// 加这个全局变量为了避免一个bug,由于时间紧张,
//暂时就先这么来避免,有时间一定找到这个bug
bool g_bNovalNameNeedFind = true;
// 枚举小说内部信息的类型
typedef enum _tagInfoType
{
Noval_Name, // 小说名字
Noval_Author, // 小说作者
Noval_Set, // 小说集
Noval_Chapter, // 小说章
Noval_Text, // 小说正文
} eInfoType;
// 枚举显示界面的类型
typedef enum _tagUIType
{
}eUIType;
/**************************************************************
* 函数名字:my_strcmp
* 函数功能:比较两个字符串是否相等,相等则返回0,不相等则返回非零值
* 函数参数:const char *str1,要比较的第一个字符串,const char *str2,要
比较的第二个字符串
* 返回值 :相等返回 0, 不相等返回 非0值
**************************************************************/
int my_strcmp(const char *str1, const char *str2);
/**************************************************************
* 函数名字:my_strncmp
* 函数功能:比较两个字符串指定字符是否相等,相等则返回0,不相等则返回非零值
* 函数参数:const char *str1,要比较的第一个字符串,const char *str2,要
比较的第二个字符串,int maxNumber最多比较的字符的个数
* 返回值 :相等返回 0, 不相等返回 非0值
**************************************************************/
int my_strncmp(const char *str1, const char *str2, int maxNumber);
/**************************************************************
* 函数名字:my_strstr
* 函数功能:查找第二个字符串在第一个字符串中的位置
* 函数参数:char *str,第一个字符串 char *substr,第二个字符串
* 返回值 :第一个字符串的首地址
**************************************************************/
char *my_strstr(char *str, char *substr);
/**************************************************************
* 函数名字:showMainPage
* 函数功能:显示主页面
* 函数参数:无
* 返回值 :无
**************************************************************/
void showHomePage();
/**************************************************************
* 函数名字:acceptInput
* 函数功能:接受用户输入
* 函数参数:无
* 返回值 :无
**************************************************************/
void acceptInput();
/**************************************************************
* 函数名字:showCatLog
* 函数功能:显示目录
* 函数参数:无
* 返回值 :无
**************************************************************/
void showCatLog();
/**************************************************************
* 函数名字:printSameChars
* 函数功能:打印相同指定个数的字符到屏幕上
* 函数参数:c 要打印的字符,num 要打印的个数
* 返回值 :无
**************************************************************/
void printSameChars(char c, int num);
/**************************************************************
* 函数名字:printSameChars
* 函数功能:加载要阅读的文件,从而提取小说的名字和作者,分割章节等,如果
小说已存在,那么提示用户是否还要继续分割,根据用户的需求进行
相应的操作。
* 函数参数:无
* 返回值 :无
**************************************************************/
bool loadFile();
/**************************************************************
* 函数名字:splitFile
* 函数功能:分割文件,按照 小说名字-》小说作者-》集-》章-》.txt文件的形式
对原文件进行划分
* 函数参数:FILE *fp,要进行分解的文件指针
* 返回值 :成功返回 true,失败返回 false
**************************************************************/
bool splitFile(FILE *fp);
/**************************************************************
* 函数名字:determineType
* 函数功能:根据传过来的一行内容,确定这一行内容是什么类型的
* 函数参数:char *line_text,传过来的一行内容
* 返回值 :Noval_Name, // 小说名字
Noval_Author, // 小说作者
Noval_Set, // 小说集
Noval_Chapter, // 小说章
Noval_Text, // 小说正文
**************************************************************/
eInfoType determineType(char *line_text);
/**************************************************************
* 函数名字:isNovalName
* 函数功能:判断一行内容是否是小说名字
* 函数参数:const char *text_line一行内容的指针
* 返回值 :是小说的名字 返回true,不是小说的名字 返回false
**************************************************************/
bool isNovalName(char *text_line);
/**************************************************************
* 函数名字:isNovalAuthor
* 函数功能:判断一行内容是否是小说作者
* 函数参数:char *text_line一行内容的指针
* 返回值 :是小说的作者 返回true,不是小说的作者 返回false
**************************************************************/
bool isNovalAuthor(char *text_line);
/**************************************************************
* 函数名字:isNovalSet
* 函数功能:判断一行内容是否是小说的集
* 函数参数:char *text_line一行内容的指针
* 返回值 :是小说的集 返回true,不是小说的集 返回false
**************************************************************/
bool isNovalSet(char *text_line);
/**************************************************************
* 函数名字:isNovalChapter
* 函数功能:判断一行内容是否是小说的章
* 函数参数:char *text_line一行内容的指针
* 返回值 :是小说的章 返回true,不是小说的章 返回false
**************************************************************/
bool isNovalChapter(char *text_line);
/**************************************************************
* 函数名字:isNovalChapter
* 函数功能:判断一行内容是否是小说的章
* 函数参数:char *text_line一行内容的指针
* 返回值 :是小说的章 返回true,不是小说的章 返回false
**************************************************************/
bool isNumberChar(const char c);
/**************************************************************
* 函数名字:getNovalName
* 函数功能:获取小说的名字
* 函数参数:char *text_line一行内容的指针,char *novalName,输出参数,用于
保存得到小说名字
* 返回值 :得到小说的名字 返回true,没有得到小说的名字 返回false
**************************************************************/
bool getNovalName(char *text_line, char *novalName);
/**************************************************************
* 函数名字:getNovalAuthor
* 函数功能:获取小说的名字
* 函数参数:char *text_line一行内容的指针,char *novalName,输出参数,用于
保存得到小说作者
* 返回值 :得到小说的作者 返回true,没有得到小说的作者 返回false
**************************************************************/
bool getNovalAuthor(char *text_line, char *novalAuthor);
/**************************************************************
* 函数名字:getNovalSet
* 函数功能:获取小说的集名
* 函数参数:char *text_line一行内容的指针,char *novalSet,输出参数,用于
保存得到小说集名
* 返回值 :得到小说的集名 返回true,没有得到小说的集名 返回false
**************************************************************/
bool getNovalSet(char *text_line, char *novalSet);
/**************************************************************
* 函数名字:findNovalSet
* 函数功能:查找小说的集名
* 函数参数:char *text_line一行内容的指针,char *novalSet,输出参数,用于
保存得到小说集名
* 返回值 :得到小说的集名 返回true,没有得到小说的集名 返回false
**************************************************************/
bool cutOutNovalSet(char *text_line, char *novalChapter);
/**************************************************************
* 函数名字:getNovalChapter
* 函数功能:获取小说的章名
* 函数参数:char *text_line一行内容的指针,char *novalChapter,输出参数,用于
保存得到小说章名
* 返回值 :得到小说的章名 返回true,没有得到小说的章名 返回false
**************************************************************/
bool getNovalChapter(char *text_line, char *novalChapter);
/**************************************************************
* 函数名字:dirCat
* 函数功能:拼接目录
* 函数参数:const char *topLevelDir 上一级目录名字, const char *curDir 当
前目录名字,char *dstDir 拼接后的目录
* 返回值 :拼接成功 返回true,拼接失败 返回false
**************************************************************/
bool dirCat(const char *topLevelDir, const char *curDir, char *dstDir);
/**************************************************************
* 函数名字:dirCatFile
* 函数功能:拼接目录和文件
* 函数参数:const char *curDir 当前目录名字, const char *fileName 文件名
字, char *filePath 生成的文件路径
* 返回值 :拼接成功 返回true,拼接失败 返回false
**************************************************************/
bool dirCatFile(const char *curDir, const char *fileName, char *filePath);
/**************************************************************
* 函数名字:createDir
* 函数功能:创建目录
* 函数参数:const char *dirName 要创建的目录名字
* 返回值 :创建成功 返回true,创建失败 返回false
**************************************************************/
bool createDir(const char *dirName);
/*
需要分析一下,主要有几个界面,一个是主界面
*/
int main()
{
char cInput = 0;
// 加载小说文件
if (loadFile())
{
// // 显示主界面
// showHomePage();
// // 接受用户输入
// acceptInput();
do
{
if (_kbhit())
{
cInput = _getch();
}
switch (cInput)
{
default:
break;
}
} while (cInput);
}
system("pause");
return 0;
}
void showHomePage()
{
system(“cls”);
printSameChars(‘*’, 99);
printf(“\r\n\r\n”);
printSameChars(’ ‘, 33);
printf(“txt电子书阅读器 1.0版本”);
printf(“\r\n\r\n”);
printSameChars(’ ‘, 25);
printf(“请输入…\r\n\r\n”);
printSameChars(’ ‘, 25);
printf(“0. 退出\r\n\r\n”);
printSameChars(’ ‘, 25);
printf(“1. 显示目录\r\n\r\n”);
printSameChars(’ ‘, 25);
printf(“2. 开始阅读\r\n\r\n”);
printSameChars(’ ‘, 25);
printf(“3. 接着上次阅读\r\n\r\n”);
printSameChars(‘*’, 99);
printf(“\r\n\r\n”);
printSameChars(’ ‘, 20);
printf(“>>> “);
}
void acceptInput()
{
char c = 0;
while (true)
{
if (_kbhit())
{
c = _getch();
switch (c)
{
case '0':
// 退出
exit(0);
break;
case '1':
// 显示目录
printf("\r\n\r\n");
showCatLog();
break;
case '2':
// 开始阅读
// beginRead();
break;
case '3':
// 继续阅读
//continueRead();
break;
default:
break;
}
}
}
}
void showCatLog()
{
bool bComplet = false;
char text_line[MAX_STR_LEN] = { 0 };
char novalSetName[MAX_STR_LEN] = { 0 };
char tmpNovalSetName[MAX_STR_LEN] = { 0 };
FILE *fp = NULL;
fp = fopen(“catlog.txt”, “r”);
if (fp)
{
while (true)
{
for (int i = 0; i < 3; )
{
if (NULL == fgets(text_line, MAX_STR_LEN, fp))
{
bComplet = true;
break;
}
cutOutNovalSet(text_line, novalSetName);
if (my_strcmp(novalSetName, tmpNovalSetName))
{
printf("%-20s", novalSetName);
memcpy(tmpNovalSetName, novalSetName, MAX_STR_LEN);
i++;
}
}
if (bComplet)
{
break;
}
printf("\r\n\r\n");
}
}
}
void printSameChars(char c, int num)
{
for (int i = 0; i < num; i++)
{
printf(“%c”, c);
}
}
char *my_strstr(char *str, char *substr)
{
while (*str != ‘\0’)
{
char *strTmp = str;
char *substrTmp = substr;
while (*strTmp++ == *substrTmp++)
{
if (*substrTmp == '\0')
{
return str;
}
}
str++;
}
return NULL;
}
int my_strcmp(const char *str1, const char *str2)
{
while ((*str1 == *str2) && (*str1 != ‘\0’))
{
str1++;
str2++;
}
return *str1 < *str2 ? -1 : *str1 == *str2 ? 0 : 1;
}
int my_strncmp(const char *str1, const char *str2, int maxNumber)
{
int iCount = 0;
while ((*str1 == *str2) && (*str1 != ‘\0’))
{
iCount++;
if (iCount == maxNumber)
{
break;
}
str1++;
str2++;
}
return *str1 < *str2 ? -1 : *str1 == *str2 ? 0 : 1;
}
bool loadFile()
{
bool bRet = false;
FILE *fp = NULL;
char szFileName[MAX_STR_LEN] = { 0 };
while (true)
{
printf("请输入要阅读的小说的文件名字...\r\n");
scanf_s("%s", szFileName, MAX_STR_LEN);
getchar();
fp = fopen(szFileName, "r");
if (fp)
{
// 对打开的文件进行文件分割,在分割的过程中,可能会发现小说的目录已经存在
// 那么我们会认为这个小说已经被加载过,应该就不需要重新加载了,但是为了保
// 险起见,还是需要让用户重新确认一遍是否需要重新加载
if (splitFile(fp))
{
printf("小说分割完成,是否进入阅读主界面?输入 yes 表示进入,其它表示退出...\r\n");
scanf_s("%s", szFileName, MAX_STR_LEN);
getchar();
if (!my_strcmp(szFileName, "yes"))
{
bRet = true;
}
break;
}
}
else
{
printf("您输入的文件名不存在,是否继续,退出请输入 yes, 继续请输入任意字符串...\r\n");
scanf_s("%s", szFileName, MAX_STR_LEN);
getchar();
if (!my_strcmp(szFileName, "yes"))
{
break;
}
else
{
continue;
}
}
}
return bRet;
}
bool splitFile(FILE *fp)
{
FILE *fpSplitFile = NULL;
eInfoType eRet = Noval_Text;
bool bRet = false;
char text_line[MAX_STR_LEN] = { 0 };
char strTmp[MAX_STR_LEN] = { 0 };
char dirNovalName[MAX_STR_LEN] = { 0 };
char dirAuthorName[MAX_STR_LEN] = { 0 };
char dirSetName[MAX_STR_LEN] = { 0 };
char fileName[MAX_STR_LEN] = { 0 };
if (fp)
{
while (true)
{
if (NULL == fgets(text_line, MAX_STR_LEN, fp))
{
break;
}
eRet = determineType(text_line);
switch (eRet)
{
case Noval_Name:
{
// 如果是小说的名字,那么就要以小说名字来创建一个存放小说文件的目录
if (getNovalName(text_line, dirNovalName))
{
if (!createDir(dirNovalName))
{
// 创建目录失败,说明已经存在,暂时先认为不用再分割了
bRet = true;
}
}
}
break;
case Noval_Author:
{
// 在创建小说作者目录的时候,必须要知道小说的名字,否则没有办法创建
// 可以用一个数组保存它们
if (getNovalAuthor(text_line, strTmp))
{
if (dirCat(dirNovalName, strTmp, dirAuthorName))
{
createDir(dirAuthorName);
}
}
}
break;
case Noval_Set:
{
// 在创建小说集的目录的时候,肯定已经有了前面的小说的作者目录
if (getNovalSet(text_line, strTmp))
{
if (dirCat(dirAuthorName, strTmp, dirSetName))
{
createDir(dirSetName);
}
}
}
break;
case Noval_Chapter:
{
// 在创建小说章的文件的时候,肯定已经有了前面的小说的集目录
if (getNovalChapter(text_line, strTmp))
{
if (fpSplitFile)
{
fclose(fpSplitFile);
}
if (dirCatFile(dirSetName, strTmp, fileName))
{
fpSplitFile = fopen(fileName, "a+");
}
FILE *fpCatlog = fopen("catlog.txt", "a+");
if (fpCatlog)
{
fprintf(fpCatlog, "%s\r\n", fileName);
fclose(fpCatlog);
}
}
}
break;
case Noval_Text:
{
// 在创建小说文件的时候,肯定已经有了前面的小说的集目录
if (fpSplitFile)
{
fprintf(fpSplitFile, "%s", text_line);
}
}
break;
default:
break;
}
if (bRet)
{
break;
}
}
if (fpSplitFile)
{
fclose(fpSplitFile);
}
}
return bRet;
}
eInfoType determineType(char *line_text)
{
// 默认情况下是小说的正文
eInfoType eRet = Noval_Text;
if (isNovalName(line_text))
{
if (g_bNovalNameNeedFind)
{
g_bNovalNameNeedFind = false;
eRet = Noval_Name;
}
}
else if (isNovalAuthor(line_text))
{
eRet = Noval_Author;
}
else if (isNovalSet(line_text))
{
eRet = Noval_Set;
}
else if (isNovalChapter(line_text))
{
eRet = Noval_Chapter;
}
return eRet;
}
bool isNovalName(char *text_line)
{
bool bRet = false;
char *strBegin = NULL;
char *strEnd = NULL;
strBegin = my_strstr(text_line, "《");
if (strBegin)
{
strEnd = my_strstr(text_line, "》");
if (strEnd)
{
if (strBegin < strEnd + 7)
{
bRet = true;
}
}
}
return bRet;
}
bool isNovalAuthor(char *text_line)
{
bool bRet = false;
if (my_strstr(text_line, "作者:"))
{
bRet = true;
}
return bRet;
}
bool isNovalSet(char *text_line)
{
bool bRet = false;
char *strBegin = NULL;
char *strEnd = NULL;
strBegin = my_strstr(text_line, "第");
if (strBegin)
{
strEnd = my_strstr(text_line, "集");
if (strEnd)
{
// 这里的判断可能还可以再优化
if ((strEnd > strBegin) && (strEnd < strBegin + 7))
{
bRet = true;
}
}
}
return bRet;
}
bool isNovalChapter(char *text_line)
{
bool bRet = false;
char *strBegin = NULL;
strBegin = my_strstr(text_line, "第");
if (strBegin)
{
strBegin += 2;
while (isNumberChar(*strBegin))
{
strBegin++;
}
if (!my_strncmp(strBegin, "章", 2))
{
bRet = true;
}
}
return bRet;
}
bool isNumberChar(const char c)
{
bool bRet = false;
if ((c >= '0') && (c <= '9'))
{
bRet = true;
}
return bRet;
}
bool getNovalName(char *text_line, char *novalName)
{
bool bRet = false;
char *strBegin = NULL;
char *tmp = novalName;
int iCount = 0;
strBegin = my_strstr(text_line, "《");
if (strBegin)
{
strBegin += 2;
while (*strBegin != '\n')
{
if (!my_strncmp(strBegin, "》", 2))
{
bRet = true;
break;
}
tmp[iCount] = *strBegin;
iCount++;
strBegin++;
}
tmp[iCount] = '\0';
}
return bRet;
}
bool getNovalAuthor(char *text_line, char *novalAuthor)
{
bool bRet = false;
char *strBegin = NULL;
char *tmp = novalAuthor;
int iCount = 0;
strBegin = my_strstr(text_line, "作者:");
if (strBegin)
{
strBegin += 6;
while (*strBegin != '\n')
{
tmp[iCount] = *strBegin;
iCount++;
strBegin++;
bRet = true;
}
tmp[iCount] = '\0';
}
return bRet;
}
bool getNovalSet(char *text_line, char *novalSet)
{
bool bRet = false;
char *strBegin = text_line;
char *tmp = novalSet;
int iCount = 0;
if (strBegin)
{
while (*strBegin != '\n')
{
tmp[iCount++] = *strBegin++;
}
tmp[iCount] = '\0';
bRet = true;
}
return bRet;
}
bool cutOutNovalSet(char *text_line, char *novalSet)
{
bool bRet = false;
char *strBegin = NULL;
char *tmp = novalSet;
int iCount = 0;
strBegin = my_strstr(text_line, "第");
if (strBegin)
{
while (*strBegin != '\\')
{
tmp[iCount] = *strBegin;
iCount++;
strBegin++;
}
tmp[iCount] = '\0';
bRet = true;
}
return bRet;
}
bool getNovalChapter(char *text_line, char *novalChapter)
{
bool bRet = false;
char *strBegin = text_line;
char *tmp = novalChapter;
int iCount = 0;
while (*strBegin != '\n')
{
tmp[iCount++] = *strBegin++;
bRet = true;
}
tmp[iCount] = '\0';
return bRet;
}
bool dirCat(const char *topLevelDir, const char *curDir, char *dstDir)
{
bool bRet = false;
if (topLevelDir && curDir)
{
char *tmp = dstDir;
int iCount = 0;
while (*topLevelDir)
{
tmp[iCount++] = *topLevelDir++;
}
tmp[iCount++] = '\\';
while (*curDir)
{
tmp[iCount++] = *curDir++;
}
tmp[iCount] = '\0';
bRet = true;
}
return bRet;
}
bool dirCatFile(const char *curDir, const char *fileName, char *filePath)
{
bool bRet = false;
if (curDir && curDir)
{
char *tmp = filePath;
int iCount = 0;
while (*curDir)
{
tmp[iCount++] = *curDir++;
}
tmp[iCount++] = '\\';
while (*fileName)
{
tmp[iCount++] = *fileName++;
}
tmp[iCount++] = '.';
tmp[iCount++] = 't';
tmp[iCount++] = 'x';
tmp[iCount++] = 't';
tmp[iCount] = '\0';
bRet = true;
}
return bRet;
}
bool createDir(const char *dirName)
{
bool bRet = false;
char mkdirName[64] = { 0 };
sprintf(mkdirName, "md %s", dirName);
if (!system(mkdirName))
{
bRet = true;
}
return bRet;
}