2015-05-27 4 views
0

Я делаю программу в C, которая может искать определенную строку в большом файле .txt и посчитайте его, а затем распечатайте его. Но кажется, что что-то пошло не так, потому что выход моей программы отличается от вывода из двух текстовых редакторов. Согласно текстовому редактору, есть всего 3000 слов, в этом случае я ищу слово «make» в этом файле .txt. Но выход моей программы составляет всего 2970.Поиск определенной строки в большом файле

Я не могу найти проблему с моей программой. Итак, я интересуюсь тем, как текстовый редактор может найти определенную строку так точно? Как люди это реализуют? Может ли кто-нибудь показывать мне код на C?

Чтобы все было ясно: это большой файл .txt, 20M или около того, содержащий множество символов. Поэтому я думаю, что это не так хорошо читать в памяти все сразу. Я реализую свою программу, разбивая мою программу на куски, а затем просматриваю все те, которые используются для разбора. Однако это не так.

Возможно, мне стоит ввести код здесь. Минуточку, пожалуйста.

Код длинный, 70 строк или около того. Я положил его на свой github, если у вас есть интерес, пожалуйста, помогите. https://github.com/walkerlala/searchText отмечает, что только соответствующий файл wordCount.c и testfile.txt, который идет как:

#include<stdio.h> 
#include<stdlib.h> 
#include<stdbool.h> 
char arr[51]; 
int flag=0; 
int flag2=0; 
int flag3=0; 
int flag4=0; 
int pieceCount(FILE*); 
int main() 
{ 
    //the file in which I want to search the word is testfile.txt 
    //I have formatted the file so that it contain no newlins any more 
    FILE* fs=fopen("testfile.txt","r"); 
    int n=pieceCount(fs); 
    printf("%d\n",n);   



    rewind(fs);   //refresh the file... 

    static bool endOfPiece1=false,endOfPiece2=false,endOfPiece3=false; 
    bool begOfPiece1,begOfPiece2,begOfPiece3; 

    for(int start=0;start<n;++start){ 
      fgets(arr,sizeof(arr),fs); 
      for(int i=0;i<=46;++i){ 
       if((arr[i]=='M'||arr[i]=='m')&&(arr[i+1]=='A'||arr[i+1]=='a')&&(arr[i+2]=='K'||arr[i+2]=='k')&&(arr[i+3]=='E'||arr[i+3]=='e')){ 
        flag+=1; 
        //continue; 
       } 
     } 


    //check the border 
     begOfPiece1=((arr[1]=='e'||arr[1]=='E')); 
     if(begOfPiece1==true&&endOfPiece1==true) 
      flag2+=1; 
     endOfPiece1=((arr[47]=='m'||arr[47]=='M')&&(arr[48]=='a'||arr[48]=='A')&&(arr[49]=='k'||arr[49]=='K')); 

     begOfPiece2=((arr[1]=='k'||arr[1]=='K')&&(arr[2]=='e'||arr[2]=='E')); 
     if(begOfPiece2==true&&endOfPiece2==true) 
      flag3+=1; 
     endOfPiece2=((arr[48]=='m'||arr[48]=='M')&&(arr[49]=='a'||arr[49]=='A')); 

     begOfPiece3=((arr[1]=='a'||arr[1]=='A')&&(arr[2]=='k'||arr[2]=='K')&&(arr[3]=='e'||arr[3]=='E')); 
     if(begOfPiece3==true&&endOfPiece3==true) 
      flag4+=1; 
     endOfPiece3=(arr[49]=='m'||arr[49]=='M'); 

} 
    printf("%d\n%d\n%d\n%d\n",flag,flag2,flag3,flag4); 
    getchar(); 
    return 0; 
} 

//the function counts how many pieces have I split the file into 
int pieceCount(FILE* file){ 
    static int count=0; 
    char arr2[51]={'\0'}; 
    while(fgets(arr2,sizeof(arr),file)){ 
     count+=1; 
     continue; 
    } 

    return count; 
} 
+0

Без просмотра кода мы можем только догадываться. Возможно, слова, которые вы не нашли, находятся на границе между двумя «кусками», которые вы читаете, например: вы ищете «ABC», часть 1: «123AB», часть 2: «CDEXYZ» –

+1

попробуйте меньший вход. Найдите наименьший вход, для которого ваш выход программы отличается от vim. Отлаживаем/пытаемся выяснить, что испортило ваш алгоритм. Почини это. Будь счастлив. – bolov

+0

@MichaelWalz Я бы хотел. подождите минутку – walkerlala

ответ

5

Вы можете сделать это достаточно просто только при наличии качения буфера. Вам не нужно разбивать файл на разделы.

#include <stdio.h> 
#include <string.h> 

int main(void) { 

    char buff [4];         // word buffer 
    int count = 0;         // occurrences 
    FILE* fs=fopen("test.txt","r");     // open the file 
    if (fs != NULL) {        // if the file opened 
     if (4 == fread(buff, 1, 4, fs)) {   // fill the buffer 
      do {         // if it worked 
       if (strnicmp(buff, "make", 4) == 0) // check for target word 
        count++;      // tally 
       memmove(buff, buff+1, 3);   // shift the buffer down 
      } while (1 == fread(buff+3, 1, 1, fs)); // fill the last position 
     }           // end of file 
     fclose(fs);         // close the file 
    } 
    printf("%d\n", count);       // report the result 
    return 0; 
} 

Для простоты я осекся сделать поисковое слово «мягче» и выделением правильного буфера и различных размеров, так что не было в этом вопросе. И я должен оставить что-то для OP.

+0

Это так здорово !!! особенно когда вы смещаете буфер на один байт на один байт, используя 'do {...} while (1 == (fread (buff + 3,1,1, fs))' ... Однако, мне интересно, замедлить скорость, чтобы загружать данные косвенно из файла (потока), а не memeory? Первоначально, причина, по которой я разложил текст и загрузил его в массив из 51 байта, заключался в том, что я думаю, что мне будет быстрее загружать данные CPU из памяти, а не из файла (потока). – walkerlala

+0

Хотя ваш заголовок вопроса относится к ** текстовому редактору **, мой ответ был направлен на деталь вопроса при поиске файла для строки. текстовый редактор, но @KeithThompson написал хорошее замечание: «Текстовые редакторы обычно хранят весь файл в памяти». Также обратите внимание, что текстовый поиск в редакторе не будет искать слова, которое пересекает разрыв строки. –

+0

не будет ли он потреблять (или использовать слишком много) памяти, если текстовый редактор хранит весь файл в памяти? .... ps, я делал небольшой проект, который является rel приложен к текстовому редактору. Но я думаю, что хорошо изменить название. – walkerlala

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