您的位置:首页 > 编程语言 > C语言/C++

用指针对文本进行字符串替换操作

2018-02-05 22:20 267 查看
指针是C语言的精髓,用指针进行文本内容解析等处理在开发过程中非常常见,这里我写了一个”指针对文本进行字符串替换操作的代码“,作为练习。

用VS2017环境编译,因为本人偏爱日志调试的方法,所以代码里日志打印内容占了一定的行数。代码运行前要在对应目录(见代码里的宏定义)下建立文本文档,用于调试。

File operation by pointer.c 代码

#include "stdafx.h"

#define srcpath "E:\\CCODE\\TEST1\\replace src file.txt"
#define dstpath "E:\\CCODE\\TEST1\\replace dest file.txt"
#define logpath "E:\\CCODE\\TEST1\\log.txt"
#define  pre_replace_string  "emperor"
#define  aft_replace_string  "Emperor"

int main()
{
FILE *fp_srcfile;
FILE *fp_dstfile;
struct stat lstat;
errno_t err;
int srcsize;
int readsize;
char szName[MAX_NAME];
char logbody[MAX_LOG];

//用文件句柄打开需要做字符串替换处理的源文件
strcpy_s(szName, MAX_NAME, srcpath);
stat(szName, &lstat);
srcsize = lstat.st_size;//获取源文件的大小
err = fopen_s(&fp_srcfile,szName,"r+");
if (0 != err)
{
snprintf(logbody, MAX_LOG, "line:[%d] Open file failed ,errno is : [%d]. \r\n", __LINE__, err);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
else
{
snprintf(logbody, MAX_LOG, "line:[%d] Open file [%s] succ.", __LINE__, srcpath);
write_log_file((char*)logpath, logbody, strlen(logbody));
}

//用文件句柄读取需要做字符串替换处理的源文件内容,并放置于before_process_content[MAX_UNIT]中
char before_process_content[MAX_UNIT] = { 0 };
char after_process_content[MAX_UNIT] = { 0 };

readsize= fread(before_process_content, 1, srcsize, fp_srcfile);
if (0 == readsize)
{
snprintf(logbody, MAX_LOG, "Read file failed ,errno is : [%d]. \r\n", err);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
else
{
snprintf(logbody, 128, "line:[%d] Read file [%s] succ.", __LINE__, srcpath);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
printf("content of source file is : [%s]", before_process_content);

//文件句柄用完后需要关闭并置NULL
if (fp_srcfile != NULL)
{
//		fclose(fp_srcfile);
fp_srcfile = NULL;
}

//处理文件内容,将before_process_content处理成after_process_content
if (0 != contentprocess(before_process_content, srcsize, after_process_content))
{
snprintf(logbody, MAX_LOG, "line:[%d] Content process failed!", __LINE__);
write_log_file((char*)logpath, logbody, strlen(logbody));
return -1;
}
else
{
snprintf(logbody, MAX_LOG, "line:[%d] Content process succ! ", __LINE__);
write_log_file((char*)logpath, logbody, strlen(logbody));
}

//处理后的文件内容写入目标文件中
memset(szName, 0, sizeof(szName));
strcpy_s(szName, MAX_NAME, dstpath);

//用文件句柄打开需要储存字符串替换处理后结果的文件
err = fopen_s(&fp_dstfile, szName, "at+");
if (0 != err)
{
snprintf(logbody, MAX_LOG, "line:[%d] Open file failed ,errno is : [%d]", __LINE__, err);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
else
{
snprintf(logbody, MAX_LOG, "line:[%d] Open file [%s]succ.", __LINE__, dstpath);
write_log_file((char*)logpath, logbody, strlen(logbody));
}

if (fp_dstfile != NULL)
{
//用文件句柄将替换后的内容写入文件
err = fwrite(after_process_content, strlen(after_process_content), 1, fp_dstfile);
if (1!=err)
{
snprintf(logbody, MAX_LOG,"line:[%d] Write file to[%s] failed ,errno is : [%d]. ", __LINE__, dstpath, err);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
else
{
snprintf(logbody, MAX_LOG, "line:[%d] Wtite file to [%s] succ.\n", __LINE__, dstpath);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
//文件句柄用完后需要关闭并置NULL
fclose(fp_dstfile);
fp_dstfile = NULL;
}

return 0;
}

//获取此刻时间用于日志打印
void get_local_time(char* buffer)
{
struct tm rawtime;
time_t time_seconds = time(0);
localtime_s(&rawtime, &time_seconds);
snprintf(buffer, 100, "%04d-%02d-%02d %02d:%02d:%02d",
(rawtime.tm_year + 1900), rawtime.tm_mon, rawtime.tm_mday,
rawtime.tm_hour, rawtime.tm_min, rawtime.tm_sec);
}

// 写日志文件
int write_log_file(char* filename, char* buffer, int buf_size)
{

FILE *fp_log;
errno_t err;
char logcontent[MAX_LOG];

//获取日志打印时间
char now[64] = { 0 };
get_local_time(now);

//将日志所有内容写入logcontent,以备打印到日志文件中
snprintf(logcontent, MAX_LOG, "time:%s %s\n", now, buffer);

//调用文件句柄fp_log打开日志文件logpath
err = fopen_s(&fp_log, (char*)filename, "at+");
if (0 != err)
{
printf("Open log file failed ,errno is : [%d]", err);
return -1;
}
if (fp_log != NULL)
{
//调用文件句柄将日志内容logcontent打印到日志文件中
err = fwrite(logcontent, strlen(logcontent) + 1, 1, fp_log);

//文件句柄用完后需要关闭并置NULL
fclose(fp_log);
fp_log = NULL;
}
else
return -1;

return 0;
}

int contentprocess(char* inbuffer, int size, char* outbuffer)
{
int count = 0;
int i = 0;
char src_string[32] = { 0 };
char dst_string[32] = { 0 };
strcpy_s(src_string, sizeof(pre_replace_string), pre_replace_string);
strcpy_s(dst_string, sizeof(aft_replace_string), aft_replace_string);

char* p;
char logbody[MAX_LOG];

snprintf(logbody, MAX_LOG, "line:[%d] Entering contentprocess procedure, contentsize:[%d]", __LINE__, size);
write_log_file((char*)logpath, logbody, strlen(logbody));

//搜索第一个被替换字符串
memcpy(outbuffer, inbuffer, strlen(inbuffer));
p = strstr(outbuffer, src_string);

//用while循环去 搜索 替换 计数
while (p)
{
count++;
str_replace(p, strlen(src_string), dst_string);
p = p + strlen(dst_string);
p = strstr(p, src_string);
}

if (0 == count)    //搜索第一个被替换字符串就失败,未进入while循环
{
snprintf(logbody, MAX_LOG, "line:[%d] Can not find %s in source file .", __LINE__, pre_replace_string);
write_log_file((char*)logpath, logbody, strlen(logbody));
}
else
{
snprintf(logbody, MAX_LOG, "line:[%d] [%s] is replaced by [%s], replace count number is :[%d].", __LINE__, pre_replace_string, aft_replace_string, count);
write_log_file((char*)logpath, logbody, strlen(logbody));
}

return 0;
}

void str_replace(char * cp, int length_of_srcstr, char * dst_str)
{
int length_of_dststr;
char * tmp;
length_of_dststr = strlen(dst_str);
//若被替换字符串的长度大于替换字符串的长度,在替换操作里源文件内容部分需要整体往前移动
if (length_of_dststr< length_of_srcstr)
{
tmp = cp + length_of_srcstr;
while (*tmp)
{
*(tmp - (length_of_srcstr - length_of_dststr)) = *tmp; //整体向前移动两个字符串的差值位,这样为字符替换留恰好的空间
tmp++;
}
*(tmp - (length_of_srcstr - length_of_dststr)) = *tmp; //把末尾的 '\0'  也要移动
}
else
//若被替换字符串的长度小于替换字符串的长度,在替换操作里源文件内容部分需要整体往后移动
if (length_of_dststr> length_of_srcstr)
{
tmp = cp;
while (*tmp) tmp++;
while (tmp >= cp + length_of_srcstr)
{
*(tmp + (length_of_dststr - length_of_srcstr)) = *tmp;//整体向后移动两个字符串的差值位,这样为字符替换留恰好的空间
tmp--;
}
}
//在之前移动产生的位置里填上替换字符
memcpy(cp, dst_str, length_of_dststr);
}


头文件stdafx.h

#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<time.h>

#define MAX_LOG 256
#define MAX_NAME 128
#define MAX_UNIT 10240

int write_log_file(char* filename, char* buffer, int buf_size);
int contentprocess(char* inbuffer, int size, char* outbuffer);
void str_replace(char * cp, int length_of_srcstr, char * dst_str);


选取一篇翻译界佳作(英文版出师表)来作为测试文本内容,将emperor替换为E mperor

replace src file:

Permit me to observe: the late emperor was taken from us before he could finish his life's work, the restoration of the Han. Today, the empire is still divided in three, and our very survival is threatened.

Y
af85
et still the officials at court and the soldiers throughout the realm remain loyal to you, your majesty. Because they remember the late emperor, all of them, and they wish to repay his kindness in service to you.

This is the moment to extend your divine influence, to honor the memory of the late emperor and strengthen the morale of your officers. It is not the time to listen to bad advice, or close your ears to the suggestions of loyal men.

The emperors of the Western Han chose their courtiers wisely, and their dynasty flourished. The emperors of the Eastern Han chose poorly, and they doomed the empire to ruin.

Whenever the late emperor discussed this problem with me, he lamented the failings of emperors Huan and Ling.

I began as a common man, farming in my fields in Nanyang, doing what I could to survive in an age of chaos. I never had any interest in making a name for myself as a noble.

The late emperor was not ashamed to visit my cottage and seek my advice. Grateful for his regard, I responded to his appeal and threw myself into his service.

The late emperor always appreciated my caution and, in his final days, entrusted me with his cause.

Since that moment, I have been tormented day and night by the fear that I might let him down. That is why I crossed the Lu river at the height of summer, and entered the wastelands beyond.

Now the south has been subdued, and our forces are fully armed. I should lead our soldiers to conquer the northern heartland and attempt to remove the hateful traitors, restore the house of Han, and return it to the former capital.

This is the way I mean to honor my debt to the late emperor and fulfill my duty to you.

My only desire is to be permitted to drive out the traitors and restore the Han. If I should let you down, punish my offense and report it to the spirit of the late emperor.

Your Majesty, consider your course of action carefully. Seek out good advice, and never forget the late words of the late emperor. I depart now on a long expedition, and I will be forever grateful if you heed my advice. Blinded by my own tears, I know not what
I write.

replace dest file:

Permit me to observe: the late Emperor was taken from us before he could finish his life's work, the restoration of the Han. Today, the empire is still divided in three, and our very survival is threatened.

Yet still the officials at court and the soldiers throughout the realm remain loyal to you, your majesty. Because they remember the late Emperor, all of them, and they wish to repay his kindness in service to you.

This is the moment to extend your divine influence, to honor the memory of the late Emperor and strengthen the morale of your officers. It is not the time to listen to bad advice, or close your ears to the suggestions of loyal men.

The Emperors of the Western Han chose their courtiers wisely, and their dynasty flourished. The Emperors of the Eastern Han chose poorly, and they doomed the empire to ruin.

Whenever the late Emperor discussed this problem with me, he lamented the failings of Emperors Huan and Ling.

I began as a common man, farming in my fields in Nanyang, doing what I could to survive in an age of chaos. I never had any interest in making a name for myself as a noble.

The late Emperor was not ashamed to visit my cottage and seek my advice. Grateful for his regard, I responded to his appeal and threw myself into his service.

The late Emperor always appreciated my caution and, in his final days, entrusted me with his cause.

Since that moment, I have been tormented day and night by the fear that I might let him down. That is why I crossed the Lu river at the height of summer, and entered the wastelands beyond.

Now the south has been subdued, and our forces are fully armed. I should lead our soldiers to conquer the northern heartland and attempt to remove the hateful traitors, restore the house of Han, and return it to the former capital.

This is the way I mean to honor my debt to the late Emperor and fulfill my duty to you.

My only desire is to be permitted to drive out the traitors and restore the Han. If I should let you down, punish my offense and report it to the spirit of the late Emperor.

Your Majesty, consider your course of action carefully. Seek out good advice, and never forget the late words of the late Emperor. I depart now on a long expedition, and I will be forever grateful if you heed my advice. Blinded by my own tears, I know not what
I write.

测试日志:

time:2018-01-05 22:09:06 line:[36] Open file [E:\CCODE\TEST1\replace src file.txt] succ.

time:2018-01-05 22:09:06 line:[52] Read file [E:\CCODE\TEST1\replace src file.txt] succ.

time:2018-01-05 22:09:06 line:[178] Entering contentprocess procedure, contentsize:[2335]

time:2018-01-05 22:09:06 line:[201] [emperor] is replaced by [Emperor], replace count number is :[12].

time:2018-01-05 22:09:06 line:[73] Content process succ!

time:2018-01-05 22:09:06 line:[91] Open file [E:\CCODE\TEST1\replace dest file.txt]succ.

time:2018-01-05 22:09:06 line:[106] Wtite file to [E:\CCODE\TEST1\replace dest file.txt] succ.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐