Regex,wyrazenia regularne

Odpowiedz Nowy wątek
2017-03-18 22:21
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
0

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

Pozostało 580 znaków

2017-03-18 22:48
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


01010100 01110101 01110100 01100001 01101010 00100000 01101110 01101001 01100101 00100000 01101101 01100001 00100000 01101110 01101001 01100011 00100000 01100011 01101001 01100101 01101011 01100001 01110111 01100101 01100111 01101111 00101110 00100000 01001001 01100011 00100000 01110011 01110100 01101111 01101110 01110100 00101110
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
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
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
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
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
Liczba odpowiedzi na stronę

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