Regex,wyrazenia regularne

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.

	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

  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

 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.

0

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

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

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/

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.
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);
0

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

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;
}
0

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

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