继续我的评论,永远不要使用gets(),它非常不安全并且容易被缓冲区溢出利用。相反,对于 面向行的 输入,请使用 fgets 或 POSIX getline。
在读取文本文件作为输入时,您在 99% 的情况下查看面向行的 输入函数是正确的。它在这里可以正常工作,但您必须确保行缓冲区足以容纳您预期的最大行。
您也不应该尝试通过“就地”修改您正在搜索的文件。如果要查找和替换的单词的长度可能完全相同,但您必须小心,否则会损坏文件。写入新文件时,您可以随意设置“查找”和“替换”字词的长度。
假设您的单词将完全包含在您阅读的行中(而不是连字符或以其他方式拆分为多行),您可以简单地阅读每一行,将 a 指针分配给该行中的起始字符,然后步行 -向下行的指针,当字符与查找单词中的字符匹配时保持索引,并在字符不同时输出替换。您必须考虑如何处理重置索引和处理部分匹配,但这只是一点算术。
例如,如果您有一个指向打开文件流的指针(例如fp),将每一行读入buf,并在find 中找到您的单词,在repl 中查找替换字符串,您可以这样做类似于以下内容:
lfind = strlen (find); /* length of replacement */
while (fgets (buf, MAXCH,fp)) { /* read each line in file */
p = buf; /* pointer to buf */
while (*p) {
if (*p == find[ndx]) /* if matches char in find */
ndx++; /* advance index */
else { /* otherwise */
if (ndx) { /* if find chars matched */
if (ndx == lfind) /* if full word found */
fputs (repl, stdout); /* output replacement */
else { /* otherwise */
int tmp = repl[ndx]; /* save char at ndx */
repl[ndx] = 0; /* nul-terminate repl */
fputs (repl, stdout); /* output replacement */
repl[ndx] = tmp; /* restore char at ndx */
}
ndx = 0; /* zero index */
}
putchar (*p); /* output current char */
}
p++;
}
}
fclose (fp); /* close file */
if (ndx) { /* if partial match at end of file */
repl[ndx] = 0; /* nul-terminate repl at index */
fputs (repl, stdout); /* output final chars */
}
(您应该进一步检查每行的strlen 是否合适并且没有被截断,否则您可能会冒着将要查找的单词的不同部分放在两个不同缓冲区中的风险-留给您)
还要注意循环退出后的检查,如果ndx 不为零,则检查是否输出任何最终字符。
放入一个简短的示例,将文件名作为参数 1、2、3 读取和查找/repl 字符串作为程序的参数(或者如果未作为参数提供,则会提示 find/repl),您可以执行类似的操作以下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCH 1024
#define MAXWD 128
void handle_args (int argc, char **argv, char *find, char *repl);
int main (int argc, char **argv) {
size_t lfind, ndx = 0;
char buf[MAXCH], find[MAXWD] = "", repl[MAXWD] = "", *p;
FILE *fp = NULL;
if (argc < 2 ) { /* validate at least one argument given */
fprintf (stderr, "error: insufficient input, usage: "
"%s filename [find, repl]\n", argv[0]);
return 1;
}
if (!(fp = fopen (argv[1], "r"))) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
handle_args (argc, argv, find, repl); /* set/prompt for find/repl */
lfind = strlen (find); /* length of replacement */
while (fgets (buf, MAXCH,fp)) { /* read each line in file */
p = buf; /* pointer to buf */
while (*p) {
if (*p == find[ndx]) /* if matches char in find */
ndx++; /* advance index */
else { /* otherwise */
if (ndx) { /* if find chars matched */
if (ndx == lfind) /* if full word found */
fputs (repl, stdout); /* output replacement */
else { /* otherwise */
int tmp = repl[ndx]; /* save char at ndx */
repl[ndx] = 0; /* nul-terminate repl */
fputs (repl, stdout); /* output replacement */
repl[ndx] = tmp; /* restore char at ndx */
}
ndx = 0; /* zero index */
}
putchar (*p); /* output current char */
}
p++;
}
}
fclose (fp); /* close file */
if (ndx) { /* if partial match at end of file */
repl[ndx] = 0; /* nul-terminate repl at index */
fputs (repl, stdout); /* output final chars */
}
return 0;
}
/* simple function to set find/repl from command line, or
* prompt for input if no arguments given.
*/
void handle_args (int argc, char **argv, char *find, char *repl)
{
if (argc < 3) {
fputs ("enter find word: ", stdout);
if (scanf ("%127s", find) != 1) {
fputs ("error: invalid input.\n", stderr);
exit (EXIT_FAILURE);
}
}
else {
size_t len = strlen (argv[2]);
if (len < MAXWD)
memcpy (find, argv[2], len + 1);
else {
fputs ("error: find argument too long.\n", stderr);
exit (EXIT_FAILURE);
}
}
if (argc < 4) {
fputs ("enter repl word: ", stdout);
if (scanf ("%127s", repl) != 1) {
fputs ("error: invalid input.\n", stderr);
exit (EXIT_FAILURE);
}
}
else {
size_t len = strlen (argv[3]);
if (len < MAXWD)
memcpy (repl, argv[3], len + 1);
else {
fputs ("error: repl argument too long.\n", stderr);
exit (EXIT_FAILURE);
}
}
}
输入文件示例
$ cat ../dat/qbfox3.txt
A quick brown fox jumps over the lazy dog.
A slow green dog jumps on top of the blue cat.
A quick blue bird flew over the lazy dog too.
使用/输出示例
$ ./bin/file_replace_fgets_stdout ../dat/qbfox3.txt dog duck
A quick brown fox jumps over the lazy duck.
A slow green duck jumps on top of the blue cat.
A quick blue bird flew over the lazy duck too.
或检查第一个和最后一个字符替换的极端情况,例如
$ ./bin/file_replace_fgets_stdout ../dat/qbfox3.txt "." "*"
A quick brown fox jumps over the lazy dog*
A slow green dog jumps on top of the blue cat*
A quick blue bird flew over the lazy dog too*
$ ./bin/file_replace_fgets_stdout ../dat/qbfox3.txt A B
B quick brown fox jumps over the lazy dog.
B slow green dog jumps on top of the blue cat.
B quick blue bird flew over the lazy dog too.
查看一下,如果您还有其他问题,请告诉我。