老师未批改
小说阅读器的章节分割部分
程序源代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h> // 使用str系列的函数
#include <conio.h> // 为了使用 _getch()
#include <direct.h> // 为了使用 _mkdir
#include <errno.h> // 为了查看错误状态和使用 strerror
#include <stdlib.h> // 为了使用 strtod
#include <time.h> // 计算用时
#define MAX_LEN 1024 // 最大数组长度
#define MID_LEN 512 // 中间的数组长度
#define MIN_LEN 255 // 最小的数组长度
#define SECTION_LEN 6 // 第 和 集 之间的最大间隔字符 也就是3个汉字
#define CHAPTER_LEN 10 // 第 和 章 之间的最大间隔字符 也就是5个汉字
// 退出状态码
typedef enum EXIT_CODE {
NORMAL = 0,
OPEN_FAILD = -1,
SPLIT_FAILD = -2
} ExitCode;
char g_strBookName[MIN_LEN] = { 0 }; // 书名
char g_sectionDir[MIN_LEN] = { 0 }; // 每一集的路径
char g_chapterName[MID_LEN] = { 0 }; // 每一章的文件路径及名称
FILE* g_fChapterFile = NULL; // 章节文件
FILE* g_fDirectoryFile = NULL; // 目录文件
// 去掉字符串中的字符
int replaceCharToNull(char* strSource, char ch)
{
int i = 0;
for (; i < strlen(strSource); i++)
{
if ((*strSource + i) == ch)
{
*(strSource + i) = '\0';
break;
}
}
return i;
}
/**
* 去掉不能当文件名的字符
*
* 参数:
* str 要建立的路径
*
* 返回值:
* 处理的字符个数
*/
int checkAndHandleName(char* str)
{
int iRet = 0;
for (int i = 0; i < strlen(str); i++)
{
char ch = *(str + i);
switch (ch)
{
// case '\\':
case '/':
case '|':
case '"':
case '?':
case ':':
case '*':
case '>':
case '<':
*(str + i) = '_';
iRet++;
break;
case '\r':
case '\n':
*(str + i) = '\0';
iRet++;
break;
default:
break;
}
}
return iRet;
}
/**
* 创建文件夹
*/
int createDir(char* str)
{
int iRet = 0;
checkAndHandleName(str);
iRet = _mkdir(str);
if (iRet < 0)
{
printf("创建文件夹[%s]失败!\n", str);
perror(strerror(errno));
}
return iRet;
}
// 获取文件大小
long getFileSize(FILE* fp)
{
long szBook = 0;
fseek(fp, 0L, SEEK_END);
szBook = ftell(fp);
return szBook;
}
// 打开文本
int openBook(FILE** file, char* strBookName)
{
int iRet = 0;
*file = fopen(strBookName, "r+");
if (*file == NULL)
{
perror(strerror(errno));
iRet = -1;
}
else
{
strncpy(g_strBookName, strBookName, strlen(strBookName) - 4);
createDir(g_strBookName);
}
return iRet;
}
// 保存目录
int saveSection(char* strLine)
{
int iRet = -1;
if (!g_fDirectoryFile)
{
g_fDirectoryFile = fopen("目录.txt", "a+");
}
else
{
fputs(strLine, g_fDirectoryFile);
iRet = 0;
}
return iRet;
}
/**
* 检查分集
*
* 参数:
* strLine : 要检查的字符串
*
* 返回值:
* 0: 是分集并且完全正确运行完成
* <0: 运行出现错误
*/
int checkSection(char* strLine)
{
int iRet = -1;
char strSection[MIN_LEN] = { 0 };
char* pFind1 = NULL;
char* pFind2 = NULL;
// 第一个字是 第
if ((pFind1 = strstr(strLine, "第")) != NULL && pFind1 == strLine) {
// 并且有 集, 并且2个字之间差的不大
pFind2 = strstr(strLine, "集");
int iFar = (pFind2 - pFind1);
if (pFind2 != NULL && (iFar <= SECTION_LEN))
{
strncpy(strSection, pFind1, strlen(pFind1)); // 连带换行一起复制
iRet = 0;
// 保存目录文件
iRet += saveSection(strSection);
// 创建分集文件夹
sprintf(g_sectionDir, "%s\\%s", g_strBookName, strSection);
iRet += createDir(g_sectionDir);
}
}
return iRet;
}
// 创建章节文件
int createChapterFile(char* strChapterName)
{
int iRet = -1;
char sPathNameTmp[MIN_LEN] = { 0 };
char sPathName[MIN_LEN] = { 0 };
sprintf(sPathNameTmp, "%s\\%s", g_sectionDir, strChapterName);
checkAndHandleName(sPathNameTmp);
sprintf(sPathName, "%s.txt", sPathNameTmp);
if (g_fChapterFile) fclose(g_fChapterFile);
g_fChapterFile = fopen(sPathName, "w");
if (g_fChapterFile)
{
strncpy(g_chapterName, sPathName, MID_LEN);
iRet = 0;
}
return iRet;
}
/**
* 保存章节文件
*/
int saveChapterFile(char* strLine)
{
int iRet = -1;
if (!g_fChapterFile)
{
iRet = -2;
}
else
{
fputs(strLine, g_fChapterFile);
iRet = 0;
}
return iRet;
}
/**
* 检查章节名
*
* 参数:
* strLine : 要检查的字符串
*
* 返回值:
* 0: 是章节名并且完全正确运行完成
* <0: 运行出现错误
*/
int checkChapter(char* strLine)
{
int iRet = -1;
char strChapter[MIN_LEN] = { 0 };
char* pFind1 = NULL;
char* pFind2 = NULL;
// 第一个字是 第
if ((pFind1 = strstr(strLine, "第")) != NULL && pFind1 == strLine) {
// 并且有 章, 并且2个字之间差的不大
pFind2 = strstr(strLine, "章");
if (pFind2 != NULL && ((pFind2 - pFind1) <= CHAPTER_LEN))
{
strncpy(strChapter, pFind1, strlen(pFind1)); // 连带换行一起复制
iRet = 0;
// 创建章节文件
iRet += createChapterFile(strChapter);
// 保存章节标题
iRet += saveChapterFile(strLine);
// 保存目录
iRet += saveSection(strLine);
}
}
return iRet;
}
/**
* 分析一行数据
*/
int analyzeLine(char* strLine)
{
int iRet = 0;
// 跳过本行前边的空格 不进行匹配
int iIdx = 0;
for (; iIdx < MAX_LEN; iIdx++)
{
if (*(strLine + iIdx) != ' ')
{
break;
}
}
// 是不是 第*集, 是的话在checkSection中保存 不是 在进行下一步判断
if (0 > checkSection(strLine + iIdx))
{
// 判断是不是 第*章, 是的话在checkChapter中保存
if (0 > checkChapter(strLine + iIdx))
{
// 正文
saveChapterFile(strLine);
}
}
return iRet;
}
/**
* 分割文件
*/
int splitBook(FILE* file, char* strFileName)
{
int iRet = 0;
char strLine[MAX_LEN] = { 0 };
printf("开始处理....\n");
clock_t start = clock();
fseek(file, 0L, SEEK_SET);
while (fgets(strLine, MAX_LEN, file) != NULL)
{
analyzeLine(strLine);
memset(strLine, 0x00, sizeof(strLine));
}
releaseAndClear();
clock_t finish = clock();
printf("\n处理完成, 耗时[%.3lf]秒.\n", ((double)finish-start)/1000);
return iRet;
}
// 清理工作
int releaseAndClear()
{
int iRet = 0;
if (g_fChapterFile) fclose(g_fChapterFile);
if (g_fDirectoryFile) fclose(g_fDirectoryFile);
return iRet;
}
int main()
{
int iExitCode = NORMAL;
printf("请输入小说名称:\n");
char strBookName[MIN_LEN] = { 0 };
scanf_s("%s", strBookName, MIN_LEN);
printf("[%s]\n", strBookName);
FILE* fBook = NULL;
if (0 != openBook(&fBook, strBookName))
{
printf("打开文件失败!程序退出....\n");
iExitCode = OPEN_FAILD;
} else if (0 != splitBook(fBook, strBookName))
{
printf("分析小说章节目录失败!程序退出....\n");
iExitCode = SPLIT_FAILD;
}
printf("请按任意键退出.....");
_getch();
if (fBook != NULL)
{
fclose(fBook);
}
return iExitCode;
}运行效果:
注: 电脑性能决定了时间, 演示效果中的时间不是每次都相同, 不同电脑的时间会有所差异.如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2016-10-12 at 04:35 pm
