去除源文件中的重复行的程序流程及其C代码实现
(本人正在参加2015博客之星评选,诚邀你来投票,谢谢:http://vote.blog.csdn.net/blogstar2015/candidate?username=zhouzxi)
一、需求描述
要求对一个包含若干行记录且某几条记录相同的文件(源文件)实现去重操作,并将去重之后的记录写入到另外一个文件(目的文件)中。也即最后生成的文件中没有内容相同的两行记录。如果源文件中两条记录之间有空行,则在目的文件中一并将其去掉。
两条记录相同的标准是:
1) 字符个数及内容完全相同。
2) 去除空格及回车换行符之后的内容完全相同。
示例:
源文件样例:
ABCD
EFGH
abcd
AB CD
abcd12345
对应的目的文件样例:
ABCD
EFGH
abcd
12345
二、程序总体流程
为了实现去重操作,我们考虑使用链表数据结构。先将源文件中的记录内容逐条读取,与链表中已经存在的记录内容相比较,如果没有与之相同的,则将该条记录加入链表。当源文件中的所有记录内容都读取完成之后,再将链表中的记录内容写入到目的文件中。
程序的总体流程如图1所示。
图1 程序的总体流程
三、重要程序流程及数据结构介绍
1.存放记录内容的链表
本程序使用链表来存放从源文件中读取到的每条记录,该链表的结构如下:
typedef struct T_FileInfoStruct
{UINT8 szContentLine[256];struct T_FileInfoStruct *pNext;
} T_FileInfo;
2.判断某条记录是否已存在于链表的函数
每当读取到一条记录,就要判断该条记录是否已经存在于链表中了(第一条记录除外)。判断操作非常的简单,只需要遍历整个链表就可以了。该操作由IsInList函数实现,其具体代码如下:
UINT32 IsInList(T_FileInfo *ptContentListHead, UINT8 *pszContentLine)
{T_FileInfo *pTmpInfo = ptContentListHead;if (ptContentListHead == NULL || pszContentLine == NULL){printf("IsInList: input parameter(s) is NULL!\n");return 0;}while (pTmpInfo != NULL){if (strncmp(pszContentLine, pTmpInfo->szContentLine, strlen(pszContentLine)) == 0) // 存在于链表中{return 1;}pTmpInfo = pTmpInfo->pNext; }if (pTmpInfo == NULL) // 不存在于链表中{return 0;}
}
3.去除记录的回车换行符、去除记录中的空格的函数
RmNewLine函数用于去除记录的回车换行符,RemoveSpaceInStr函数用于去除记录中的空格。这两个函数的程序代码请见附录。
四、程序编译及执行结果
将RemoveRepeatLine.c(详细的代码请见附录)程序上传到Linux机器上,使用gcc -g -o RemoveRepeatLine RemoveRepeatLine.c命令对其编译,生成RemoveRepeatLine。
在本程序中,我们使用的源文件为TestFile.txt,位于当前用户的zhouzhaoxiong/zzx/RemoveRepeatLine/TestFile目录下;生成的目的文件为ResultFile.txt,与源文件位于相同的目录之下。
本人使用的源文件TestFile.txt的内容为:
ABCD
EFGH
AB CD
1243565
dfbfdj
dgbsjn1234 n
dsaghhnzvbvcawsswgh
EFGHzvb1234 n
fedhhEFG H
运行RemoveRepeatLine命令之后,生成结果文件ResultFile.txt,其内容为:
ABCD
EFGH
1243565
dfbfdj
dgbsjn
1234n
dsaghhn
zvb
vc
awsswgh
fedhh
可见,程序满足了需求,去除了重复的行,同时将多余的空行也去掉了。
五、总结
关于本程序,有如下几点说明:
第一,链表这种数据结构在实际的软件开发项目中应用得非常的广泛,大家一定要熟练掌握其用法,特别是如何向链表中插入数据、如何遍历整个链表、如何清空链表等。
第二,写文件函数WriteToFile中,在“strncpy(szContentBuf, ptContentListHead->szContentLine, strlen(ptContentListHead->szContentLine));”语句之前,一定要加上“memset(szContentBuf, 0x00, sizeof(szContentBuf));”语句,否则写入文件中的内容可能不是我们想要的。大家也可以在自己的机器上试试,看加与不加“memset(szContentBuf, 0x00, sizeof(szContentBuf));”语句,生成的结果文件有何区别。
第三,在有关话单生成及处理的程序中,对源话单文件进行去重操作是大家必须考虑的问题。本文中的程序为相关项目的开发人员提供了参考。
附:完整的程序代码
/**********************************************************************
* 版权所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名称:RemoveRepeatLine.c
* 文件标识:无
* 内容摘要:去除源文件中的重复行
* 其它说明:无
* 当前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20151209
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 数据类型重定义
typedef unsigned char UINT8;
typedef signed int INT32;
typedef unsigned int UINT32;// 存放文件每行内容的链表
typedef struct T_FileInfoStruct
{
UINT8 szContentLine[256];
struct T_FileInfoStruct *pNext;
} T_FileInfo;// 函数声明
void RemRepLineAndWriResFile(UINT8 *pszTestFile);
void RmNewLine(UINT8 *pInStr);
UINT32 IsInList(T_FileInfo *ptContentListHead, UINT8 *pszContentLine);
void WriteToFile(T_FileInfo *ptContentListHead);
void ClearList(T_FileInfo *ptContentListHead);
void RemoveSpaceInStr(UINT8 *pszStr, UINT32 iStrLen);/**********************************************************************
* 功能描述:主函数
* 输入参数:无
* 输出参数:无
* 返 回 值:无
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
* ---------------------------------------------------------------
* 20151209 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
INT32 main()
{
UINT8 szTestFile[128] = {0}; // 拼装配置文件路径
snprintf(szTestFile, sizeof(szTestFile)-1, "%s/zhouzhaoxiong/zzx/RemoveRepeatLine/TestFile/TestFile.txt", getenv("HOME")); RemRepLineAndWriResFile(szTestFile); // 调用函数完成去重及写文件的操作 return 0;
}/**********************************************************************
* 功能描述:去除源文件中的重复行, 并将去重之后的内容写入结果文件中
* 输入参数:pszTestFile-带路径的测试文件名
* 输出参数:无
* 返 回 值:无
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
* ---------------------------------------------------------------
* 20151209 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
void RemRepLineAndWriResFile(UINT8 *pszTestFile)
{
UINT8 szContentLine[256] = {0};
UINT32 iLineLen = 0;
UINT32 iRetVal = 0; FILE *fp = NULL;
T_FileInfo *ptContentListHead = NULL;
T_FileInfo *ptContentListTail = NULL;
T_FileInfo *ptCurrentContent = NULL; if (pszTestFile == NULL)
{ printf("RemRepLineAndWriResFile: pszTestFile is NULL!\n");
return;
} printf("RemRepLineAndWriResFile: now, begin to process file %s\n", pszTestFile); if ((fp = fopen(pszTestFile, "r")) == NULL)
{ printf("RemRepLineAndWriResFile: open file %s failed!\n", pszTestFile);
return;
}
else
{ ptContentListHead = NULL;
ptContentListTail = NULL; while (feof(fp) == 0 && ferror(fp) == 0)
{ memset(szContentLine, 0x00, sizeof(szContentLine));
if (fgets(szContentLine, sizeof(szContentLine), fp) == NULL) // 从源文件中读取一行内容
{ printf("RemRepLineAndWriResFile: get line null, break.\n");
break;
}
else
{ printf("RemRepLineAndWriResFile: get content line: %s\n", szContentLine);
} RmNewLine(szContentLine); // 去掉字符串后面的回车换行符
RemoveSpaceInStr(szContentLine, strlen(szContentLine)); // 去掉字符串中的空格 iLineLen = strlen(szContentLine);
if (iLineLen == 0) // 如果该行的有效长度为0, 则继续读取下一行
{ printf("RemRepLineAndWriResFile: the length of line is 0, continue to read the next content line.\n");
continue;
} if (ptContentListHead != NULL) // 判断当前行是否已经存在了
{ iRetVal = IsInList(ptContentListHead, szContentLine);
if (iRetVal == 1) // 已经存在
{ printf("RemRepLineAndWriResFile: this content line has already existed.\n");
continue;
}
} // 将当前行加入链表中
ptCurrentContent = (T_FileInfo *)malloc(sizeof(T_FileInfo));
if (ptCurrentContent == NULL)
{ printf("RemRepLineAndWriResFile: exec malloc failed, memory may be not enough.\n");
return;
} memcpy(ptCurrentContent->szContentLine, szContentLine, strlen(szContentLine)); if (ptContentListHead == NULL) // 链表为空时作为链表头
{
ptContentListHead = ptCurrentContent;
ptContentListTail = ptCurrentContent;
}
else
{ if (ptContentListTail != NULL) // 插入链表尾部
{ ptContentListTail->pNext = ptCurrentContent;
ptContentListTail = ptCurrentContent;
}
}
}
// 源文件使用完毕
fclose(fp);
fp = NULL;
} // 将去重之后的结果写入文件中
WriteToFile(ptContentListHead); // 清空链表
ClearList(ptContentListHead);
ptContentListHead = NULL;
}/**********************************************************************
* 功能描述:去掉字符串后面的回车换行符
* 输入参数:pInStr-输入字符串
* 输出参数:无
* 返 回 值:无
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
* ---------------------------------------------------------------
* 20151209 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
void RmNewLine(UINT8 *pInStr)
{
UINT32 iStrLen = 0; if (pInStr == NULL)
{ printf("RmNewLine: pInStr is NULL!\n");
return;
} iStrLen = strlen(pInStr);
while (iStrLen > 0)
{ if (pInStr[iStrLen-1] == '\n' || pInStr[iStrLen-1] == '\r')
{ pInStr[iStrLen-1] = '\0';
}
else
{ break;
} iStrLen --;
}
}/**********************************************************************
* 功能描述:判断某行内容是否已经存在于链表中了
* 输入参数:pInStr-输入字符串
* 输出参数:无
* 返 回 值:1-存在 0-不存在
* 其它说明:无
* 修改日期 版本号 修改人 修改内容
* ---------------------------------------------------------------
* 20151209 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
UINT32 IsInList(T_FileInfo *ptContentListHead, UINT8 *pszContentLine)
{
T_FileInfo *pTmpInfo = ptContentListHead; if (ptContentListHead == NULL || pszContentLine == NULL)
{ printf("IsInList: input parameter(s) is NULL!\n");
return 0;
} while (pTmpInfo != NULL)
{ if (strncmp(pszContentLine, pTmpInfo->szContentLine, strlen(pszContentLine)) == 0) // 存在于链表中
{ return 1;
}
pTmpInfo = pTmpInfo->pNext;
} if (pTmpInfo == NULL) // 不存在于链表中
{ return 0;
}
}/*********************************************************************** 功能描述: 把内容写到文件中* 输入参数: ptContentListHead-文件记录链表* 输出参数: 无* 返 回 值: 无* 其它说明: 无* 修改日期 版本号 修改人 修改内容* ----------------------------------------------------------------------* 20151209 V1.0 Zhou Zhaoxiong 创建************************************************************************/
void WriteToFile(T_FileInfo *ptContentListHead)
{
FILE *fp = NULL;
UINT8 szLocalFile[500] = {0};
UINT8 szContentBuf[256] = {0}; if (ptContentListHead == NULL)
{ printf("WriteToFile: input parameter is NULL!\n");
return;
} snprintf(szLocalFile, sizeof(szLocalFile)-1, "%s/zhouzhaoxiong/zzx/RemoveRepeatLine/TestFile/ResultFile.txt", getenv("HOME"));
fp = fopen(szLocalFile, "a+");
if (fp == NULL)
{ printf("WriteToFile: open local file failed, file=%s\n", szLocalFile);
return;
} while (ptContentListHead != NULL)
{ memset(szContentBuf, 0x00, sizeof(szContentBuf));
strncpy(szContentBuf, ptContentListHead->szContentLine, strlen(ptContentListHead->szContentLine));
printf("WriteToFile: LocalFile=%s, ContentBuf=%s\n", szLocalFile, szContentBuf); fputs(szContentBuf, fp);
fputs("\r\n", fp); // 加上回车换行符
fflush(fp); ptContentListHead = ptContentListHead->pNext;
} fclose(fp);
fp = NULL; return;
}/**********************************************************************
* 功能描述: 清除链表
* 输入参数: ptContentListHead-链表指针
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期 版本号 修改人 修改内容
* ------------------------------------------------------
* 20151209 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
void ClearList(T_FileInfo *ptContentListHead)
{
T_FileInfo *ptContentList = NULL;
T_FileInfo *pTmpData = NULL; if (ptContentListHead == NULL)
{ printf("ClearList: input parameter is NULL!\n");
return;
} ptContentList = ptContentListHead;
while (ptContentList != NULL)
{ pTmpData = ptContentList;
ptContentList = ptContentList->pNext;
free(pTmpData);
}
}/**********************************************************************
* 功能描述: 清除字符串中的空格
* 输入参数: pszStr-输入的字符串
iStrLen-最大长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期 版本号 修改人 修改内容
* ------------------------------------------------------
* 20151209 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
void RemoveSpaceInStr(UINT8 *pszStr, UINT32 iStrLen)
{
UINT8 szResult[256] = {0};
UINT8 szBuf[256] = {0};
UINT32 iLoopFlagSrc = 0;
UINT32 iLoopFlagDst = 0; if (pszStr == NULL)
{ return;
} memcpy(szBuf, pszStr, iStrLen); for (iLoopFlagSrc = 0; iLoopFlagSrc < strlen(szBuf); iLoopFlagSrc ++)
{ if (szBuf[iLoopFlagSrc] != ' ')
{ szResult[iLoopFlagDst] = szBuf[iLoopFlagSrc];
iLoopFlagDst ++;
}
} szResult[iLoopFlagDst+1] = 0; memcpy(pszStr, szResult, iStrLen); return;
}
(本文中的程序已提交到了GitHub上,欢迎下载阅读:https://github.com/zhouzxi/RemoveRepeatLine)
去除源文件中的重复行的程序流程及其C代码实现相关推荐
- python去重复行_python 去除Excel中的重复行数据
原博文 2019-08-05 16:15 − 导入pandasimport pandas as pd1.读取excel中的数据:frame = pd.DataFrame(pd.read_csv('ex ...
- NPP++去除文本中的重复行
方法一: 使用正则表达是的方式: ^(.*?)$\s+?^(?=.*^\1$) 如下图格式 方法二: 选择菜单TextFX -- TextFX Tools: 1.选择"TextFx ...
- 【SQL】去除表中的重复行
去除emp表中相同的行: SCOTT@LGR> delete from emp a where rowid not in (select max(rowid) from emp b where ...
- C++ 实现去除文本中的重复行
例题:有一个文本1.txt,内容有N行: 1111 3333 1111 3333 2222-- 写一段c++的代码可以将重复行去除,内容变为: 1111 3333 2222-- 代码如下: #incl ...
- 如何去除Excel中的重复的行数据
转自:https://blog.csdn.net/fox009521/article/details/78116816 很多时候我们在处理EXCEL表格的数据时,需要去除重复的行数据.假如数据不多,可 ...
- python二维数组去重复_python 去除二维数组/二维列表中的重复行方法
python 去除二维数组/二维列表中的重复行方法 之前提到去除一维数组中的重复元素用unique()函数,如果要去除二维数组中的重复行该怎么操作呢? import numpy as np arr = ...
- linux sed去除重复,删除文本中的重复行(sort+uniq/awk/sed)
在进行文本处理的时候,我们经常遇到要删除重复行的情况.那怎么解决呢? 下面就是三种常见方法? 第一,用sort+uniq,注意,单纯uniq是不行的. shell> sort file | un ...
- linux去除内容重复行,Linux删除文本中的重复行 - 米扑博客
在进行文本处理的时候,我们经常遇到要删除重复行的情况.那怎么解决呢? 下面就是三种常见方法? 第一,用sort+uniq,注意,单纯uniq是不行的,uniq对于重复行不上下连续时不起作用 因此,先对 ...
- sql删除表中重复记录_SQL从SQL表中删除重复行的不同方法
sql删除表中重复记录 This article explains the process of performing SQL delete activity for duplicate rows f ...
最新文章
- 9行Python代码搭建神经网络
- mysql 怎么查询结果补0_mysql查询连续时间数据——无数据补0
- python3.12答案_编程常见问题
- 《WinForm开发系列之控件篇》Item3 BindingSource (暂无)
- DotDensityRenderer
- <读书笔记> Thinking in python (Python 设计模式) 3. Proxy and State模式
- python—csv模块处理单字符分隔符文件
- 解决DEFINE_string(result_path, result, Path for results) NameError:name 'os' is not defined
- 190623每日一句
- Biobank genetic data探析(一)
- pyhon3 爬取河海大学URP教务系统,爬取个人成绩,和本学期的成绩GPA,保存到excel
- _ZN10tensorflow8internal21CheckOpMessageBuilder9NewStringB5cxx11Ev
- 学计算机的数学一定要好吗,学计算机一定要数学好吗?
- VS编译错误:mt.exe : general error c101008d: Failed to write the updated manifest to the resource of file
- 万能的小镇市场能否成为悟空问答的救命良药?
- 力扣(20.232)补9.6
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 进程管理 进程的调度
- 高性能风控数据平台设计
- Display Port 1.4 link Training 过程