Продолжая мой комментарий, никогда не используйте gets()
, это ужасно небезопасно и может быть использовано из-за переполнения буфера.Вместо этого, для линейно-ориентированного ввода используйте fgets
или POSIX getline
.
При чтении текстового файла в качестве ввода, вы корректно смотрите на строчно-ориентированный функции ввода 99% времени.Здесь он будет работать нормально, но вы должны убедиться, что ваш буфер строки достаточен для хранения самой большой строки, которую вы ожидаете.
Вы также не должны пытаться изменить файл, который вы ищете через «на месте».Хотя возможно, что слово для поиска и замены имеет одинаковую длину, вы должны быть осторожны, иначе вы испортите файл.При записи в новый файл вы можете иметь разную длину слов «найти» и «заменить».
Предполагая, что ваше слово будет полностью содержаться в прочитанной вами строке (без переносов или других разделений).несколько строк), вы можете просто прочитать каждую строку, назначить указатель на начальный символ в строке, а затем пройти указатель вниз по строке, сохраняя индекс, когда символ соответствует символам в вашем слове поиска, и выводязамена, когда символы отличаются.Вы должны подумать о том, как вы будете обрабатывать сброс индекса и обрабатывать частичные совпадения, но это просто арифметика.
Например, если у вас есть указатель на поток открытых файлов (например, 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 для программы (или запросит поиск / реплику, если она не указана в качестве аргумента), вы можете сделать что-то вроде следующего:
#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.
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.