字符串的查找和替换,要求用c语言编写,最好发到我的邮箱[email protected]

打开一篇英文文章,在该文章中找出所有给定的单词,然后对所有给定的单词替换为另外一个单词,再存盘。

/* Filename: word-replace.c
* Last Modified: 2009-01-08 20:21:55
* Description: 替换文件中指定的单词为其他字符串并输出到指定的文件中
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define MAX_WORDS_LEN 50 // 单词的最大长度限制

typedef enum { FALSE = 0, TRUE = 1 } BOOL;

struct Word {
char str[MAX_WORDS_LEN + 1]; // 存储字符串
BOOL isWord; // 是否为单词
};

typedef struct Node { // 使用链表存储解析后的字符串
struct Word word;
struct Node *next;
} *List;

enum Option { // 单词替换选项
MATCH_WORD_CASE, // 精确匹配单词区分大小写
MATCH_WORD_NOCASE, // 匹配单词但不区分大小写
};

// 函数功能:出错处理方法,打印出错信息并退出程序
void complain(const char *msg)
{
printf("%s\n", msg);
exit(EXIT_FAILURE);
}

// 函数功能:将结构体单词 w 插入不带头节点的单向不循环链表 L 的末尾
// 参数L:不带头节点的单向不循环链表的表头指针
// 参数w:指向待插入链表 L 的结构体单词信息的指针
void insert_list(List * L, const struct Word *w)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
node->word = *w, node->next = NULL;

if (*L != NULL) { // 链表非空,则寻找链表的末尾并插入
struct Node *p;
for (p = *L; p->next != NULL; p = p->next) ;
p->next = node;
} else // 链表为空,直接插入
*L = node;
}

// 函数功能:打印不带头节点的单向不循环链表,参数L为该链表的表头指针
void print_list(List L)
{
for (struct Node * p = L; p; p = p->next)
printf("%s|%d\n", p->word.str, p->word.isWord);
}

// 函数功能:销毁不带头节点的单向不循环链表,参数L为该链表的表头指针
void dump_list(List L)
{
for (struct Node * p = L, *n; p; p = n) {
n = p->next;
free(p);
}
}

// 函数功能:不区分大小写的字符串比较函数,该函数不是标准C语言的库函数
int stricmp(const char *dst, const char *src)
{
int ch1, ch2;

do {
if (((ch1 = (unsigned char)(*(dst++))) >= 'A') && (ch1 <= 'Z'))
ch1 += 0x20;
if (((ch2 = (unsigned char)(*(src++))) >= 'A') && (ch2 <= 'Z'))
ch2 += 0x20;
} while (ch1 && (ch1 == ch2));

return (ch1 - ch2);
}

// 函数功能:解析文件指针fp_ro所指文件中的字符串,将其中的单词和非单词分离
// 出来,并将分离的结果存储到不带头节点的单向不循环链表L中。如果
// 函数成功执行,返回TRUE,否则返回FALSE。
BOOL word_parse(FILE * fp_ro, List * L)
{
if (fseek(fp_ro, 0L, SEEK_END))
return FALSE;

const long fsize = ftell(fp_ro);

if (fseek(fp_ro, 0L, SEEK_SET))
return FALSE;

char *buf = (char *)malloc(fsize + 1);

if (buf && fread(buf, fsize, 1, fp_ro) != 1 && ferror(fp_ro))
complain("Internal error.");

struct Word w;
char pword[MAX_WORDS_LEN + 1];
for (size_t i = 0, index = 0; i < (size_t) fsize;) {
index = 0;
while (!isalpha(buf[i]) && i < (size_t) fsize) { // 非字母
pword[index++] = buf[i++];
if (index == MAX_WORDS_LEN) { // 缓冲区溢出情况的处理
pword[index] = '\0'; // strncpy不自动添加'\0'
strncpy(w.str, pword, index + 1);
w.isWord = FALSE;
insert_list(L, &w);
index = 0;
}
}

if (index != 0) {
pword[index] = '\0'; // strncpy不自动添加'\0'
strncpy(w.str, pword, index + 1);
w.isWord = FALSE;
insert_list(L, &w);
}

index = 0;
while (isalpha(buf[i]) && i < (size_t) fsize) { // 单词
pword[index++] = buf[i++];
if (index == MAX_WORDS_LEN) // 缓冲区溢出情况的处理
complain("Too long word in source file.");
}

if (index != 0) {
pword[index] = '\0'; // strncpy不自动添加'\0'
strncpy(w.str, pword, index + 1);
w.isWord = TRUE;
insert_list(L, &w);
}
}

free(buf);
return TRUE;
}

// 函数功能:根据替换选项opt,替换在不带头节点的单向不循环链表L中的
// 单词fnd为新的字符串rep,并返回替换的次数。
int word_replace(List L, enum Option opt, const char *fnd, const char *rep)
{
int rep_cnt = 0; // 替换发生的次数

switch (opt) {
case MATCH_WORD_CASE:
for (struct Node * p = L; p; p = p->next)
if (p->word.isWord == TRUE && strcmp(p->word.str, fnd) == 0)
strcpy(p->word.str, rep), rep_cnt++;
break;

case MATCH_WORD_NOCASE:
for (struct Node * p = L; p; p = p->next)
if (p->word.isWord == TRUE && stricmp(p->word.str, fnd) == 0)
strcpy(p->word.str, rep), rep_cnt++;
break;

default:
fprintf(stderr, "Invalid option for function %s.", __func__);
}

return rep_cnt;
}

// 函数功能:将不带头节点的单向不循环链表 L 中的单词(字符串)按顺序存入由
// fp_wr所指的文件中。如果函数成功执行,返回TRUE,否则返回FALSE。
BOOL word_save(FILE * fp_wr, List L)
{
if (fseek(fp_wr, 0L, SEEK_SET))
return FALSE;
for (struct Node * p = L; p; p = p->next)
fprintf(fp_wr, "%s", p->word.str);
return TRUE;
}

// 程序功能:以文件为单位,执行单词替换
// 参数格式:命令 源文件 目标文件 查找的单词 替换的单词
int main(int argc, const char *argv[])
{
// 参数合法性检查
if (argc != 5 || strcmp(argv[1], argv[2]) == 0 ||
strlen(argv[3]) > MAX_WORDS_LEN || strlen(argv[4]) > MAX_WORDS_LEN)
complain("参数错误!\n"
"参数格式:命令 源文件 目标文件 查找的单词 替换的单词");

FILE *fin = fopen(argv[1], "rt");
FILE *fout = fopen(argv[2], "wt");
const char *const fnd = argv[3];
const char *const rep = argv[4];

if (fin == NULL || fout == NULL)
complain("文件输入输出错误!\n");

List L = NULL; // 不带头结点的单向链表的表头指针

if (word_parse(fin, &L) == FALSE)
complain("Parse error.");
print_list(L);
int rep_cnt = word_replace(L, MATCH_WORD_CASE, fnd, rep);
printf("共发生替换 %d 次。\n", rep_cnt);
word_save(fout, L);
dump_list(L);
fclose(fin);
fclose(fout);
return 0;
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2009-06-25
strstr //查找
strcpy //复制
fread //读文件
fwrite //写文件
相似回答