2010-08-09 3 views
0

Проблема была в найти и заменить строку в файле C.Найти и заменить в файле C

Я новичок в файлах C. Я пробовал следующий код, но я не получил никакого вывода:

#include<stdio.h> 
    #include<string.h> 
    int main() 
    { 
     FILE *f1,*f2; 
     char *src,*dest,*s1,ch,ch1,ch2,ch3; 
     int i; 
     f1=fopen("input.txt","rw"); 
     f2=fopen("dummy.txt","rw"); 
     src="mor"; 
     dest="even"; 
     while(ch!=EOF) 
     { 
     ch=fgetc(f1); 
     if(ch==src[0])      //Finding 1st char of src 
     { 
     fgets(s1,strlen(src),f1); 
     if(strcmp(src+1,s1)==0)   //Finding occurance of "src" in file 
     { 
      fseek(f1,strlen(src)-1,SEEK_CUR); 
      while(ch1!=EOF)    //Copying remaining data into another file 
      { 
      ch1=fgetc(f1); 
      fputc(ch1,f2); 
      } 
     fseek(f1,-strlen(src),SEEK_CUR); 
     for(i=0;i<strlen(dest);i++) //replacing "src" with "dest" 
     { 
      ch2=dest[i]; 
      fputc(ch2,f1); 
     } 
     fclose(f1); 
     f1=fopen("input.txt","a"); 
     while(ch3!=EOF)  //Appending previosly copied data into 1st file 
     { 
      ch3=fgetc(f2); 
      fputc(ch3,f1); 
     } 
    } 
    } 
} 
    fclose(f1); 
    fclose(f2); 
} 

содержимое input.txt является «утро».

Просьба указать ОШИБКА в логике, а также дать эффективный код для этого же.

Спасибо заранее.

+2

Наиболее очевидный эффективный код будет выглядеть примерно так: 'sed 's/src/dest/g" input.txt'. Выполнение этого непосредственно в C не имеет большого смысла (по крайней мере, на мой взгляд). –

+2

@ Jerry Coffin ... Сэр, но вопрос попросил проверить наше понимание работы с файлами в C !!! –

+0

«вопрос был прошен, чтобы проверить наше понимание работы с файлами в C». Это вопрос домашней работы? Если это так, вы можете добавить тег «домашняя работа». –

ответ

3

Чтение файлов на C обычно немного беспорядочно. Первая проблема, которую я вижу, - это способ ch используется в основном цикле. Первый раз

while (ch != EOF) 

выполняется, ч не инициализирован, и если это произойдет, держать EOF, основной цикл не будет выполняться на всех. Я обычно использую следующую структуру для чтения файлов:

FILE *fInput = fopen("input.txt", "r"); 
int ch; /* need an int to hold EOF */ 

for (;;) 
{ 
    ch = fgetc(fInput); 
    if (ch == EOF) break; 

    ... 
} 

Кроме того, вам может понадобиться прочитать на концепции указателя файла. Например, после прочтения оставшейся части src вы отправите fseek() вперед и пропустите еще несколько символов, прежде чем копировать данные в f2. По существу, вы читаете m, читаете orfgets() - и в нераспределенный буфер s1, который в ближайшее время пойдет на вас на ка-бум), пропустите еще 2 символа (теперь ваш указатель находится в конце n «утра»,), скопируйте «ng» в f2, попробуйте записать EOF в f2 в этом цикле (следовательно, вышеприведенный шаблон для чтения до EOF), найдите два символа назад (что может закончиться с ошибкой после достижения EOF, мои функции C-файла немного ржавые в эти дни), напишите «ровный» в f1 (который должен, если я ошибаюсь в поиске после EOF, задайте входной файл «mornieven» и не измените его, если я прав). Таким образом, я не думаю, что код делает то, что вы намерены делать.

Я бы рекомендовал вам создать свою функцию.Каждый один из следующих может быть записана в виде программы, которую вы должны проверить и закончить перед переходом к следующему шагу:

  1. читать файл безопасно, и распечатать его
  2. обнаружить содержимое src и печати остальные ввода
  3. сохранить остальную часть входа на второй файл вместо печати
  4. заменить src с dest в первом файле, и игнорировать остальные (так как вы открыть входной файл с «RW», это будет укоротить остальные вход). Возможно, вам понадобится fseek(), чтобы очистить статус EOF. Также обратите внимание на ftell() записать позицию, вы можете перейти назад к использованию fseek()
  5. наконец, скопировать все, что вы сохранили на второй файл после замены src с dest (нет необходимости закрывать f1 здесь. Но лучше открыть f2 как писать, закрыть после копирования из первого файла и снова открыть, как читать, чтобы вернуть копию в f1).

Кроме того, если вам нужен буфер (например, s1), просто использовать достаточно большой массив сейчас, но заглянуть в malloc() и free() функций для выполнения динамического распределения памяти для подобных ситуаций.

+0

Большое спасибо за усилия ue в анализе всего этого. Я не могу поблагодарить U достаточно. Я использовал fseek после обнаружения появления «src» bcos, я не знал, что fgets перемещает указатель файла. Я должен был лучше ознакомиться с концепциями. Итак, если об этом позаботиться, программа делает то, что я намерен делать правильно? Я также попробую метод U дал ... Еще раз спасибо !!!! –

1

Вы печатаете неправильную вещь в своем выходе. Распечатайте «ch», а не указатель файла.

 
while(ch!=EOF) 
{ 
    ch=getc(f1); 
    printf("%c",ch); 
} 
while(ch!=EOF) 
{ 
    ch=getc(f2); 
    printf("%c",ch); 
} 

Кроме того, f2 закрывается в конце во время вывода. Вы должны открыть его (так же, как вы делаете с f1.)

+0

@Starsky, у меня есть ур. Сэр. Я изменил его в коде. Я удалил печатную деталь. Просьба проверить на наличие ошибок в логике замены. Файл input.txt не изменяется при запуске, а исходное содержимое сохраняется .... Спасибо за помощь ур ... –

2

Один простой способ сделать то заменить было бы сначала прочитать в весь файл в буфер

например

FILE* fpIn = fopen("file.txt","rb"); 
fseek(fpIn, 0L, SEEK_END); 
size_t s = ftell(fpIn); 
fseek(fpIn, 0L, SEEK_SET); 
void* buf = malloc(s); 
fread(buf,s,1,fpIn); 

Теперь при записи файла, проверьте для строки

char src[] = "mor"; 
char dest[] = "even"; 
int lenSrc = strlen(src); 
int lenDest = strlen(dest); 
for (char* ch = buf; ch < buf + s; ++ch) 
{ 
    if (!memcmp(ch, src, lenSrc)) 
    { 
    fwrite(dest, 1,lenDest, fpOut); 
    ch += lenSrc; 
    } 
    else 
    { 
    fputc(*ch, fp); 
    } 
} 

отказ от ответственности: не компилируется этот

+0

@ Андрес К., спасибо большое сэр ... Я попробую метод, который дал сэр, Я думаю, что это будет проще, чем поиск и замена файлов! –

1

На первый взгляд, я вижу, что ваш код для вызова fgets неправильно. Вы не выделили какую-либо память, и вы читаете строку в неинициализированный указатель. Чтение в массив или динамически распределенная память.

+0

, кажется, нет проблем с fgets, как и указал. Он компилируется правильно и выполняется правильно. Я читаю его в строку, которая ранее была объявлена ​​..... –

+1

@Shyam. Ваш 'fgets' неверен. 's1' не является строкой, это указатель на массив символов, и он не инициализирован. Вы пишете нераспределенную память. Это не ошибка компиляции; это гораздо более серьезная логическая ошибка, которая приведет к неопределенному поведению. – meagar

+0

@meager .... s1 не инициализирован и логически неверен .. я знаю tat. Но так как я не получаю никаких ошибок, я оставляю это как есть. Может ли U PLS проверять любые ошибки в логике, которые я использовал в программе. Thnaks –

1

Другая проблема заключается в том, что вы объявляете ch как char. fgetc() возвращает int, и не без оснований. Хорошо иметь возможность вернуть любой возможный символ или EOF, поэтому EOF не должен быть символом, поэтому в идеале fgetc() возвращает более крупный тип, чем char.

Результат состоит в том, что цикл может никогда не заканчиваться, поскольку ch не может содержать EOF по некоторой стандартной реализации. Заявить (и ch1 и ch3) как int.

Смежные вопросы