Szukanie ciągu znaków w pliku na podstawie wzoru

0

Witam,

Mam za zadanie napisać program, który wykona następujące rzeczy:

  1. Wczyta plik tekstowy do pamięci (~1100000 znaków)

  2. Przeanalizuje cały plik, szukając ciągów znaków według konkretnego wzoru (np. "Wypłacono [liczba1] w wysokości [liczba2] z ID: [string1]".

  3. Ze znalezionych ciągów znaków odpowiadających wzorowi ma wyciągnąć konkretne zmienne - [liczba1] [liczba2] [string1] i zapisać je do odpowiednich tablic.

  4. Przeanalizować zapisane zmienne prostym algorytmem i wypisać je do pliku w odpowiedniej strukturze. (to już łatwe)

Mam do tego zadania następujące pytania.

  1. Jakiej funkcji użyć do wczytania pliku i w jakiej zmiennej go zapisać? (plik ma około miliona znaków). Myślę, że tą część można by pomijać i analizować na bieżąco w trakcie wczytywania pliku.

  2. Według mnie najtrudniejsze - jak zadać programowi by wyszukiwał określone ciągi znaków według wzoru i wyciągał z nich konkretne zmienne?


Za wszelką pomoc z góry dziękuję!
~Tomek</u></u>

0

Rozwiązań jest kilka. Wszystko zależy jakiego arsenału możesz użyć. Czy algorytm wyszukujący musisz sam napisać czy możesz użyć gotowej biblioteki np Boost.Regex?.

0

Znaj łaskę Pana:

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>

using namespace std;

int main() {
  ifstream plik;
  string linia;
  size_t found, found2;
  int liczba1, liczba2;

  plik.open("c:\\plik.txt");
  while(!plik.eof()) {
    getline(plik,linia);
    found = linia.find("Wypłacono");
    if (found!=string::npos) {
      found2 = linia.find("w wysokości",found+1);
      if (found2!=string::npos) {
        liczba1 = atoi(linia.substr(found+11,linia.find(" ",found+11)).c_str()); //te 11 to długość ciągu znaków "wypłacono"
        liczba2 = atoi(linia.substr(found2+12,linia.find(" ",found2+12)).c_str()); //te 12 to długość ciągu znaków "w wysokości"
        cout << liczba1 << " " << liczba2 << endl;
      }
    }
  }
  plik.close();

  cin >> linia;

  return 0;
}

0

@AdamPL, Poczynileś kilka założeń w swoim programie które nie koniecznie mogą być słuszne - np skąd wiesz że w jednej linii może być tylko jedno wystąpienie szukanego ciągu?

Pamiętaj że Wymaganie!=Założenie

0

A więc tak:
Muszę wydobyć 3 stringi z jednego stringa danych:
PR 00415899 spłacił w całości pożyczkę (KZPA, 01) w okresie 05. Proszę

Doszedłem do takiej formy programu, lecz nie działa on - może mi ktoś powiedzieć co jest nie tak?

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>

using namespace std;

int main() {
ifstream plik;  ofstream wynik;
string pracownik[65535]; string pozyczka[65535]; string okres[65535]; string linia; 
size_t found, found2, found3;
int i=0, l=0;

  plik.open("logi.txt");                              // Otwieranie strumienia pliku
  while(!plik.eof()) {                           // Analiza dopóki nie napotka końca pliku
    getline(plik,linia);                         // Pobieranie lini tekstu     
    found = linia.find("PR "); 
    if (found!=string::npos) {
      found2 = linia.find(" spłacił w całości pożyczkę ("); 
      if (found2!=string::npos) {
        found3 = linia.find(") w okresie ");
        if (found3!=string::npos) {
          pracownik[i]=linia.substr(found+3,8);   // Zapisywanie numeru pracownika
          pozyczka[i]=linia.substr(found2+29,8);  // Zapisywanie typu pozyczki
          okres[i]=linia.substr(found3+12,2);     // Zapisywanie okresu pozyczki                   
          i++;
        }
      }    
    }         
  }
  plik.close();

  if(i>0) 
  {
    cout<<"Znaleziono "<<(i-1)<<" zakonczonych pozyczek.";
    wynik.open("logi_przeanalizowane.txt");
    if (wynik.is_open())
    {
      wynik << "Znaleziono "<< (i+1) <<" splaconych pozyczek.\n\n";      
      wynik << "ID pracownika   Typ pozyczki   Okres pozyczki";
      while(l<=i)
      {
        wynik << pracownik[l] << "        " << pozyczka[l] << "       " << okres[l] << "\n";
        l++;
      }
    }
    wynik.close();     
  }
  
  
  system("Pause");
  return 0;
}

Z góry dzięki za pomoc! ;)

0

A co Ci w nim "nie dziala"?
0) po getline() powinienes sprawdzac czy strumien jest nadal 'dobry'. getline moglo sie nie powiesc, jezeli byles na samym koncu pliku i wtedy ostatnia LINIE przetworzysz i naliczysz dwa razy

  1. uzywasz stringa i fstreamow, a nie slyszales o std::vector i/lub std::list? przerob te swoje tabele po 60tys elementow (btw. po co to -1 od 65536?) na vector albo liste, program bedzie lzejszy, biedny stos odetchnie (te 1.5mega tablic na stosie to ZŁY pomysl, nie mowiac o gornym limicie rozmiaru, chyba ze zleceniodawca Ci gwarantuje pod grozba kary pienieznej ze wiecej wpisow w pliku nie bedzie..), a i kod bedzie troche 'ladniejszy'
  2. jesli nie dziala Ci szukanie w pliku, moze byc to dlatego, ze sa rozne kodowania znakow. musisz bardzo uwazac na wszelkie Ą Ę Ł itede ktore umieszczasz w kodzie. to że wygladaja tak samo jak te w pliku tekstowym, to nie znaczy ze kompilator je skompiluje do tych samych kodow ascii. Twoje Ą moze byc w programie zapisane jako rowne, strzelam win1250/0xA5, podczas gdy w pliku tekstowym masz ISO8859/0xA1 i nijak tego Ci program nie uzna za rowne.. mozesz sprobowac wczytywac i przerabiac na unicode a swoje napisy trzymac jako L'ngi (+ wchar_t, mbstowcs, wcstombs) acz imho, zwykle lepiej w ogole nie porownywac polskich liter i je przeskakiwac jako dowolny znak. reszta liter zwyklych w wiekszosci wypadkow wystarcza do identyfikacji lini
  3. to samo sie tyczy bialych znakow. jesli masz pecha, spacja w tekscie pliku moze nie byc spacja, tylko byc twarda spacja o innym kodzie.. ale to juz bys musial miec ogromny niefart

1 użytkowników online, w tym zalogowanych: 0, gości: 1