2011-01-15 15 views

Odpowiedz

4

nr

albo trzeba zmienić rodzaj strumienia (i stąd semantyka parsowanie) lub użyć własnego typu string (a więc zmiany semantyki analizy składniowej w przeciążonej op >>) .

Zamiast rozważyć napisanie funkcji, podobny do getline, który analizuje możliwie cytowane „słowo” z potoku:

getqword(sstr, myString1); 
getqword(sstr, myString2); 
if (sstr) { /* both succeeded */ } 

Należy pamiętać, że wejście do std :: string już kończy się spacją, więc trzeba tylko poradzić wystającym do przodu na ofertę, a następnie obsługiwać przypadki krawędzi, z których jest mnóstwo:

  • ucieka (cytaty wewnątrz cudzysłowów)
    • trzy style rozpowszechnione są di odrzucony, odwrócony ukośnik i podwójny cytat; każdy ma swoje zalety i wady
  • obejmujące wiele linii (może \ n być włączone?)
    • często jest to błąd danych, więc zabronienie może być bardzo pomocne w pewnych okolicznościach
  • co się dzieje, gdy cytowane słowo kończy się obok innego słowa?
    • "\"hello world\"today"
  • Pomiń wiodącym spacje?
    • przeciwieństwie getline, ma sens, aby uczcić skipws flagę strumienia, ale widziałem, że idzie w drugą stronę w rzadkich okolicznościach
    • wartownik istream zajmie to dla ciebie
  • nie zapomnij korzystać z cech strumienia i lokalizacji, lub użyć metod, które już to robią!
    • lub dokumentować założenia
+0

Jest to łatwe do wdrożenia przy użyciu std :: getline (istream, string, terminator). Po prostu ustaw terminator na "" i zatrzyma czytanie na początku całkiem. " –

+0

@Martin: To zależy od konkretnych decyzji dotyczących ucieczki i obsługi linii, których nie zawsze chcesz. –

+0

Nie wiesz co masz na myśli. –

1

Nie. Nie w ten konkretny sposób. Można jednak napisać "silny typedef" dla napisu i zaprojektować nowego operatora >> dla tego, który zachowuje się w ten sposób.

0

To nie jest możliwe.To dlatego, że jeśli spojrzeć na realizację operator>> dla basic_istream który jest w rzeczywistości o nazwie kiedy robisz sstr >> myString1, widać to wewnątrz pętli for:

else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta))) 
    break;// whitespace, quit 

środków, gdy pojawi się „przestrzeń”, Quit. Nie możesz więc dodawać postaci do swojego myString1, gdy tylko otrzymasz miejsce.

Uwaga: jest to implementacja MSVC++, ale jestem pewien, że znajdzie się odpowiednik we wszystkich wersjach!

2

Nie bezpośrednio, potrzebujesz "opakowania" klasy, która kończy się tam, gdzie chcesz.

struct QuotedStringReader 
{ 
    std::string& str; 
    QuotedStringReader(std::string& s) : str(s) {} 
}; 

std::istream operator>>(std::istream&, const QuotedStringReader& qsr); 

std::string s, s2; 
stream >> QuotedStringReader(s) << s2; 

Należy pamiętać, że jest to rzadka okazja, gdzie można przesyłać do const - bo można napisać do ul wewnętrznego, mimo że jest const, i ten sposób mogę przekazać w tymczasowym.

W rzeczywistości, ponieważ prawdopodobnie nie wiesz, co masz zamiar przeczytać, możesz po prostu nazwać to "TokenReader", który odczytuje cokolwiek zdefiniujesz jako "token".

5

Krótka odpowiedź: Nie

Długi Odpowiedź:
Brak manipuluje, że zrobi to za Ciebie.

alternatywna Odpowiedź:

można napisać własny typ, który mógłby być używany w połączeniu z operatorami strumienia rób tego zadania.

#include <string> 
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <iterator> 


class QuotedWord 
{ 
    public: 
     operator std::string const&() const { return data;} 

    private: 
     std::string  data; 
     friend std::ostream& operator<<(std::ostream& str, QuotedWord const& value); 
     { 
     return str << value.data; 
     } 
     friend std::istream& operator>>(std::istream& str, QuotedWord& value); 
     { 
     char x; 
     str >> x; 
     if ((str) && (x == '"')) 
     { 
      std::string extra; 
      std::getline(str, extra, '"'); 
      value.data = std::string("\"").append(extra).append("\""); 
     } 
     else 
     { 
      str.putback(x); 
      str >> value.data; 
     } 
     return str; 
     } 
}; 

Następnie można go normalnie używać.

+0

Nie obsługuje przypadku '' input " '(brak interweniującego spacji między cudzysłowami) lub' "input" more', co również, jeśli jest zaimplementowane w ten sposób, wymaga więcej niż gwarantowanego zwrotu. –

+0

Zapomniałeś sprawdzić, czy str >> x powiodło się lub się nie udało i musisz pominąć wiodące białe spacje, jeśli ustawiona jest opcja skipws, co jest najłatwiejsze w przypadku istve sentry, w przeciwnym razie jest to bardzo zbliżone do tego, co sobie wymyśliłem w mojej odpowiedzi: –

+0

@Fred Nurk: wszystko naprawione. Dzięki kodowi pobranemu z @ Christian Ammer: http://stackoverflow.com/questions/4701535/changing-behaviour-double-quotes-when-a-stringstream/4701684#4701684 –

0

Można przeciążać operator strumienia wejściowego i uwzględnić tam semantykę parsowania.

std::istream& operator>>(std::istream& is, std::string& out) 
{ 
    char c; 
    is >> c; 
    if (c == '\"') 
    { 
     std::getline(is, out, '\"'); 
     return is; 
    } 
    else 
    { 
     is.putback(c); 
     return std::operator >>(is, out); 
    } 
} 

int main() 
{ 
    std::istringstream iss("\"hello world\" today"); 
    std::string test; 
    while (iss >> test) 
     std::cout << test << std::endl; 
} 
+1

Chociaż to działa. Nie podoba mi się to, ponieważ prowadzi do nieoczekiwanego zachowania. Co się dzieje, jeśli kolega modyfikuje twój kod nieświadomy, że zdefiniowałeś nowe przeciążenie operatora >> dla ciągu znaków.Problem może nie pojawić się nawet podczas testów jednostkowych, ale wysadzić w powietrze w prawdziwym świecie. –

+0

Nie należy przeciążać operatorów na typach stdlib, w których nie ma on własnego typu. –

Powiązane problemy