Regex,wyrazenia regularne

Regex,wyrazenia regularne
WO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 23
0

Mam problem z wyrażeniem regularnym, próbuje napisać odpowiedni pattern który na onlinowym regex matcher wyświtalo jako poprawny, jednak mam problem z imprementacją go do programu, ponieważ nie wyszukuje nic, ciągle smatch empty.

Kopiuj
	if (czyWczytano(r));
	{
		fseek(stream, 0, SEEK_END);
		int w = ftell(stream);
		char*napis = new char[w + 1];
		fseek(stream, 0, SEEK_SET);																														
		fread(napis, w, 1, stream);
		napis[w] = 0;
		string tekst(napis);
		smatch m;
		 regex e("Nazwa:\\s+(\\w+|\\w+\\s+\\w+)\\s+Rodzaj:\\s+(\\w+|\\w+\\s+\\w+)\\s+Waga:\\s+(\\d+|\\d+\\.\\d+)\\s\\[kg\\]\\s+Cena:\\s(\\d+|\\d+\\.\\d+)\\szl\\.\\s+Kolor:\\s(\\w+)\\s+");
	
		cout << m.size();
		sleeper();
		while (regex_search(tekst, m, e))
		{
			sTowar pom;
			pom.nazwa = m[1];
			pom.rodzaj = m[2];
			string val_wagi = m[3];
			pom.waga = atof(val_wagi.c_str());
			string val_ceny = m[4];
			pom.cena = atof(val_ceny.c_str());
			pom.kolor = m[5];
			t.push_back(pom);
			tekst = m.suffix().str();


		}
		delete[] napis;
		fclose(stream);

	}
 

Stricte jesli chodzi o pattern to

Kopiuj
  regex e("Nazwa:\\s+(\\w+|\\w+\\s+\\w+)\\s+Rodzaj:\\s+(\\w+|\\w+\\s+\\w+)\\s+Waga:\\s+(\\d+|\\d+\\.\\d+)\\s\\[kg\\]\\s+Cena:\\s(\\d+|\\d+\\.\\d+)\\szl\\.\\s+Kolor:\\s(\\w+)\\s+");

Natomiast dane pobierane z pliku sa takim wyrazeniem

Kopiuj
 Nazwa: japko
Rodzaj: owoc
Waga: 10 [kg]
Cena: 3.5 zl.
Kolor: zielony
Nazwa: banani
Rodzaj: owoc
Waga: 14 [kg]
Cena: 4 zl.
Kolor: zolty

Bardzo dziękuje za pomoc.

WO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 23
0

Dokładnie z tą stroną sprawdzałem :) I pattern był zgodny z danymi.

stivens
  • Rejestracja: dni
  • Ostatnio: dni
0

nie widzę na co odpisujesz, chyba ktoś skasował, spróbuj tutaj http://regexr.com/

dodam jeszcze, że nie mam pojęcia czy C++ ma swój własny pattern regexów, ale nie podobają mi się te podwójne backslashe
\\s+ oznacza, ze szukasz takiego ciągu "\s"

EDIT: rzeczywiście w C++ używa się podwójnego backslasha, nie było pytania

pasasap
  • Rejestracja: dni
  • Ostatnio: dni
0

Sprawdź co masz na wejściu. Pattern jest poprawny.

Inna sprawa: daj minimalny przykład który pozwala się skompilować i zreprodukować twój problem. Nie używaj tablicy typu char, po to masz std::string. fopen i fclose w C++ to chyba nie tu, od tego masz std::istream
Zapewne się uczysz dopiero, dlatego nie ucz się złych praktyk, zacznij od początku pisać poprawny i ładny kod, bo ktoś go potem będzie czytał. Popatrz na https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0
  1. w przypadku regexp lepiej używać raw strinng.
  2. masz UB przy tworzeniu string
  3. rzeczy na małe funkcje.
  4. średnik po if
  5. takich danych nie parsuje się regexp, ale kodem.
Kopiuj
auto LoadFileToString(FILE* file) -> std::string
{
    fseek(stream, 0, SEEK_END);
    int len = ftell(stream);
    fseek(stream, 0, SEEK_SET);

    auto result = std::string(len + 1, '\0');                                                                                                         
    fread(&result[0], len, 1, stream);
    return result;
}

… … …
     auto teks = LoadFileToString(stream);
     regex e(R"regexp(Nazwa:\s+(\w+|\w+\s+\w+)\s+Rodzaj:\s+(\w+|\w+\s+\w+)\s+Waga:\s+(\d+|\d+\.\d+)\s\[kg\]\s+Cena:\s(\d+|\d+\.\d+)\szl\.\s+Kolor:\s(\w+)\s+)regexp");

        sleeper();
        smatch m;
        while (regex_search(tekst, m, e))
        {
            sTowar pom;
            pom.nazwa = m[1];
            pom.rodzaj = m[2];
            string val_wagi = m[3];
            pom.waga = atof(val_wagi.c_str());
            string val_ceny = m[4];
            pom.cena = atof(val_ceny.c_str());
            pom.kolor = m[5];
            t.push_back(pom);
            tekst = m.suffix().str();
        }
        fclose(stream);
MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0

Odnośnie 5 parsowanie kodem w C++ może wyglądać tak:

Kopiuj
std::istream& operator>>(std::istream& in, sTowar& towar)
{
    std::string fieldName;
    towar.name = std::string();

    auto rollbackPos = in.tellg();
    while (std::getline(in >> std::ws, fieldName, ':'))
    {
          std::getline(in , fieldValue);
          if (fieldName == "Nazwa")
          {
                if (!towar.name.empty())
                {
                     in.seekg(rollbackPos);
                     break;
                }
                towar.name = fieldName;
          }
          else if (fieldName == "Rodzaj")
          {
                towar.rodzaj = fieldName;
          }
          else if (fieldName == "Waga")
          {
                std::stringstream data(fieldName);
                data >> towar.waga;
          }
          else if (fieldName == "Cena")
          {
                std::stringstream data(fieldName);
                data >> towar.cenna;
          }
          else if (fieldName == "Kolor")
          {
                towar.kolor = fieldName;
          }
          rollbackPos = in.tellg();
    }
    return in;
}
MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0

Przetestowałem twój regexp i najwyraźniej działa: http://ideone.com/0x5lE9

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.