2016-03-30 7 views
1

die Zeichenfolge Gegeben:find(cbegin(foo), cend(foo), [](const auto& i) { return isspace(i); })Wie kann ich eine Zeichenfolge von Whitespaces meines Gebiets abrufen?

Aber ich will die Position: const auto foo = "lorem\tipsum"s

ich einen Iterator auf das Leerzeichen, indem Sie finden können. Ich habe zwei Möglichkeiten:

  1. Verwendung distance: distance(cbegin(foo), find(cbegin(foo), cend(foo), [](const auto& i) { return isspace(i); }))
  2. isspace nachschlagen und eine hartcodierte Zeichenfolge konstruiert von seinem Inhalt: foo.find_first_of(" \f\n\r\t\v")

Klar ist einfacher, und es wird wieder string::npos die ich testen muss für, aber ich würde gerne meine locale stellen Sie mir eine Zeichenfolge aus allen Leerzeichen, anstatt harcoding die Zeichenfolge. Gibt es eine Funktion, die ich verwenden könnte, um diese Zeichenfolge zu erhalten, oder eine Möglichkeit, es zu kochen?

+1

* Klar * Option 2 ist einfacher? Huh. Ich finde "Entfernung" einfach gut, obwohl das einfache 'it - cbegin (foo)' auch nicht so schlecht ist. – Voo

+0

@Voo * Offensichtlich *. Ich habe bearbeitet, um die Tatsache hinzuzufügen, dass beim Arbeiten mit Positionen "distance" nervig ist, weil ich auch überprüfen muss, ob es größer ist als 'foo.size()', also kann ich es auf 'string :: npos' setzen Falls benötigt. –

+1

Option 3: Schreiben Sie Ihre eigene Funktion ("first_space" oder etwas Ähnliches), die die 'distance' Methode verwendet und verwenden Sie diese in Ihrem Code. – molbdnilo

Antwort

1

Dies ist ein semi naiver Ansatz, aber wir können eine Funktion haben, die isspace() gegen alle möglichen Werte überprüft, die char mit einem mitgelieferten locale halten kann und gibt eine Zeichenfolge, die nur die Werte, die true zurückkehren hält. Sie können diese Zeichenfolge mit der Option 2 verwenden.

Dies ist eine O (N) -Operation mit N == std::numeric_limits<char>::max() - std::numeric_limits<char>::min(), aber wenn Sie das Gebietsschema nicht ändern, müssen Sie es nur einmal ausführen und die Zeichenfolge erfassen.

std::string whitespace_string(const std::locale& loc) 
{ 
    std::string whitespace; 
    for (char ch = std::numeric_limits<char>::min(); ch < std::numeric_limits<char>::max(); ch++) 
     if (std::isspace(ch, loc)) 
      whitespace += ch; 
    // to avoid infinte loop check char max outside the for loop. 
    if (std::isspace(std::numeric_limits<char>::max(), std::locale(loc))) 
     whitespace += std::numeric_limits<char>::max(); 
    return whitespace; 
} 

Und es mit

std::string whitespace = whitespace_string(std::locale("")); 

Jetzt mit gibt Ihnen einen String mit allen Leerzeichen in der aktuellen Locale. Sie können std::locale("") durch ein anderes Gebietsschema wie std::locale("C") ersetzen, wenn Sie das aktuelle Gebietsschema nicht verwenden möchten.

+0

Könnten wir dieses" constexpr "machen? Ich bin mir nicht sicher, ob ich 'cout's' locale' zur Kompilierzeit bekommen kann? –

+1

@ JonathanMee Ich denke nicht, dass dies "constexpr" gemacht werden kann, da "std :: string" auf der Laufzeitzuweisung beruht. Ich habe jedoch nicht viel Erfahrung mit ihnen. – NathanOliver

+0

Schmale Zeichen sind so letztes Millennium. Und Sie verwenden sie in einem unbekannten Gebietsschema ... –