(本人正在参加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代码实现相关推荐

  1. python去重复行_python 去除Excel中的重复行数据

    原博文 2019-08-05 16:15 − 导入pandasimport pandas as pd1.读取excel中的数据:frame = pd.DataFrame(pd.read_csv('ex ...

  2. NPP++去除文本中的重复行

    方法一: 使用正则表达是的方式: ^(.*?)$\s+?^(?=.*^\1$) 如下图格式 方法二: 选择菜单TextFX   --    TextFX Tools: 1.选择"TextFx ...

  3. 【SQL】去除表中的重复行

    去除emp表中相同的行: SCOTT@LGR> delete from emp a where rowid not in (select max(rowid) from emp b where ...

  4. C++ 实现去除文本中的重复行

    例题:有一个文本1.txt,内容有N行: 1111 3333 1111 3333 2222-- 写一段c++的代码可以将重复行去除,内容变为: 1111 3333 2222-- 代码如下: #incl ...

  5. 如何去除Excel中的重复的行数据

    转自:https://blog.csdn.net/fox009521/article/details/78116816 很多时候我们在处理EXCEL表格的数据时,需要去除重复的行数据.假如数据不多,可 ...

  6. python二维数组去重复_python 去除二维数组/二维列表中的重复行方法

    python 去除二维数组/二维列表中的重复行方法 之前提到去除一维数组中的重复元素用unique()函数,如果要去除二维数组中的重复行该怎么操作呢? import numpy as np arr = ...

  7. linux sed去除重复,删除文本中的重复行(sort+uniq/awk/sed)

    在进行文本处理的时候,我们经常遇到要删除重复行的情况.那怎么解决呢? 下面就是三种常见方法? 第一,用sort+uniq,注意,单纯uniq是不行的. shell> sort file | un ...

  8. linux去除内容重复行,Linux删除文本中的重复行 - 米扑博客

    在进行文本处理的时候,我们经常遇到要删除重复行的情况.那怎么解决呢? 下面就是三种常见方法? 第一,用sort+uniq,注意,单纯uniq是不行的,uniq对于重复行不上下连续时不起作用 因此,先对 ...

  9. sql删除表中重复记录_SQL从SQL表中删除重复行的不同方法

    sql删除表中重复记录 This article explains the process of performing SQL delete activity for duplicate rows f ...

最新文章

  1. 9行Python代码搭建神经网络
  2. mysql 怎么查询结果补0_mysql查询连续时间数据——无数据补0
  3. python3.12答案_编程常见问题
  4. 《WinForm开发系列之控件篇》Item3 BindingSource (暂无)
  5. DotDensityRenderer
  6. <读书笔记> Thinking in python (Python 设计模式) 3. Proxy and State模式
  7. python—csv模块处理单字符分隔符文件
  8. 解决DEFINE_string(result_path, result, Path for results) NameError:name 'os' is not defined
  9. 190623每日一句
  10. Biobank genetic data探析(一)
  11. pyhon3 爬取河海大学URP教务系统,爬取个人成绩,和本学期的成绩GPA,保存到excel
  12. _ZN10tensorflow8internal21CheckOpMessageBuilder9NewStringB5cxx11Ev
  13. 学计算机的数学一定要好吗,学计算机一定要数学好吗?
  14. VS编译错误:mt.exe : general error c101008d: Failed to write the updated manifest to the resource of file
  15. 万能的小镇市场能否成为悟空问答的救命良药?
  16. 力扣(20.232)补9.6
  17. 基于 Linux 集群环境上 GPFS 的问题诊断
  18. 进程管理 进程的调度
  19. 高性能风控数据平台设计
  20. Display Port 1.4 link Training 过程

热门文章

  1. AI如何设计,才能人类利益最大化?
  2. 高文院士:人工智能发展机遇
  3. 高文院士:中国在AI领域有哪些长板和短板
  4. 机器学习2021 | 机器学习算法如何商业落地?
  5. 《中国基础研究竞争力报告2020》发布,6图表速览报告核心结论
  6. Alpha fold: 人工智能在蛋白质结构预测上跑赢人类的启示
  7. 世界顶尖精密仪器技术都掌握在哪些国家?
  8. 2019-2020中国趋势报告,203页PPT解读16大机会
  9. 关于交通创新,这五大智慧城市做了啥?
  10. 华为自研操作系统官宣了,但有机会成功吗