Regex,wyrazenia regularne

Regex,wyrazenia regularne
WO
  • Rejestracja:ponad 9 lat
  • Ostatnio:prawie 8 lat
  • 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:ponad 9 lat
  • Ostatnio:prawie 8 lat
  • Postów:23
0

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

stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 10 godzin
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


λλλ
edytowany 5x, ostatnio: stivens
Zobacz pozostały 1 komentarz
stivens
biały znak to \s+ chyba, że C++ ma troche inne patterny to wtedy możliwe
pasasap
W C++ \ to znak specjalny, dlatego by go użyć np. w tablicy znaków, trzeba go wpisać podwójnie. https://msdn.microsoft.com/en-us/library/6aw8xdf2.aspx
stivens
yup, już sam z ciekawości wygooglowałem - my bad
spartanPAGE
ludzie, raw string literalsy a nie jakis cyrk..
MO
raw string literal co pisał @spartanPAGE, podzielić wzorzec na sekcje i bazować na łączeniu stringów w C++ a w odpowiednich liniach dodać komentarz (z praktyki.. to jedno z tych miejsc gdzie komentarz jest obowiązkowy), odpowiednio ustawić flagi wzorca. Jakoś nie widzę "ustosunkowania się" np. do konsumpcji nowych linii w przeszukiwanym string'u oraz klasy znaków \X występujących w ECMAScript...
pasasap
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad rok
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
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:minuta
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);

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:minuta
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;
}

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22
MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:minuta
0

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


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

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.