Regex,wyrazenia regularne

Odpowiedz Nowy wątek
2017-03-18 22:21

Rejestracja: 4 lata temu

Ostatnio: 3 lata temu

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.

Pozostało 580 znaków

2017-03-18 22:25

Rejestracja: 4 lata temu

Ostatnio: 3 lata temu

0

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

Pozostało 580 znaków

2017-03-18 22:48

Rejestracja: 3 lata temu

Ostatnio: 10 godzin temu

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, 2017-03-18 23:10
Oznacza to, że oczekujesz co najmniej jednego białego znaku w ciągu znaków... - pasasap 2017-03-18 22:58
biały znak to \s+ chyba, że C++ ma troche inne patterny to wtedy możliwe - stivens 2017-03-18 23:02
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 - pasasap 2017-03-18 23:09
yup, już sam z ciekawości wygooglowałem - my bad - stivens 2017-03-18 23:11
ludzie, raw string literalsy a nie jakis cyrk.. - spartanPAGE 2017-03-18 23:12
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... - Mokrowski 2017-03-18 23:48

Pozostało 580 znaków

2017-03-18 22:56

Rejestracja: 8 lat temu

Ostatnio: 1 miesiąc temu

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[...]xx-kiedy-uzywac-new-i-delete/


.

Pozostało 580 znaków

2017-03-19 09:30

Rejestracja: 12 lat temu

Ostatnio: 11 godzin temu

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

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22, 2017-03-19 10:38

Pozostało 580 znaków

2017-03-19 09:53

Rejestracja: 12 lat temu

Ostatnio: 11 godzin temu

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

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2017-03-19 10:37

Pozostało 580 znaków

2017-03-19 10:36

Rejestracja: 12 lat temu

Ostatnio: 11 godzin temu

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.

Pozostało 580 znaków

Odpowiedz

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