Wie überprüfe ich, ob ein C ++ std :: string mit einem bestimmten String beginnt, und konvertiere einen Teilstring in einen int?

241

Wie implementiere ich Folgendes (Python-Pseudocode) in C ++?

if argv[1].startswith('--foo='):
    foo_value = int(argv[1][len('--foo='):])

(Wenn beispielsweise argv[1]ist --foo=98, dann foo_valueist 98.)

Update: Ich zögere, mich mit Boost zu befassen, da ich nur eine sehr kleine Änderung an einem einfachen kleinen Befehlszeilentool vornehmen möchte (ich möchte lieber nicht lernen, wie man Boost für Minderjährige verknüpft und verwendet Veränderung).

Daryl Spitzer
quelle
Das ist auch interessant.
Manlio

Antworten:

446

Verwenden Sie eine Überladung rfindmit dem posParameter:

std::string s = "tititoto";
if (s.rfind("titi", 0) == 0) {
  // s starts with prefix
}

Wer braucht noch etwas? Pure STL!

Viele haben dies falsch verstanden, um "rückwärts durch die gesamte Zeichenfolge nach dem Präfix suchen" zu bedeuten. Dies würde zu einem falschen Ergebnis führen (z. B. würde string("tititito").rfind("titi")2 im Vergleich zu == 0false zurückgeben) und wäre ineffizient (Blick auf die gesamte Zeichenfolge anstatt nur auf den Anfang). Dies ist jedoch nicht der Fall, da der posParameter als übergeben wird 0, wodurch die Suche auf eine Übereinstimmung nur an dieser Position oder früher beschränkt wird . Beispielsweise:

std::string test = "0123123";
size_t match1 = test.rfind("123");    // returns 4 (rightmost match)
size_t match2 = test.rfind("123", 2); // returns 1 (skipped over later match)
size_t match3 = test.rfind("123", 0); // returns std::string::npos (i.e. not found)
Ludovic Aubert
quelle
32
Diese Antwort sollte die am besten gewählte sein, nicht die Boost-Antwort: D Warum sollten Sie eine andere Bibliothek verwenden, wenn Sie bereits STL haben?
Iuliu Atudosiei
@ sweisgerber.dev, ich bin verwirrt über deine erste Behauptung. Der Rückgabewert von findist nur dann Null, wenn er titiam Anfang der Zeichenfolge steht. Wenn es woanders gefunden wird, erhalten Sie einen Rückgabewert ungleich Null, und wenn es nicht gefunden wird, erhalten Sie einen Wert, nposder ebenfalls ungleich Null ist. Angenommen, ich habe Recht, würde ich diese Antwort vorziehen, da ich keine nicht standardmäßigen Dinge einbringen muss (ja, ich weiß, dass Boost überall ist, ich würde nur einfache C ++ - Bibliotheken für einfache Dinge wie diese bevorzugen).
Paxdiablo
@paxdiablo: Sie haben Recht, es prüft zwar, ob es mit beginnt titi, aber der Konvertierungsteil fehlt.
sweisgerber.dev
2
Haben wir Beweise dafür, dass dies in den meisten Compilern optimiert ist? Ich finde es nicht anderswo, zu erwähnen, dass die Optimierung "find" oder "rfind" auf der Grundlage des Rückgabewerts, gegen den geprüft wird, gängige Praxis ist.
Superziyi
2
@alcoforado "rfind startet am Ende des Strings ..." Nein, das gilt nur für die Überladung rfind(), die keinen posParameter akzeptiert . Wenn Sie die Überladung verwenden, die einen posParameter benötigt, wird nicht die gesamte Zeichenfolge durchsucht, sondern nur diese Position und früher. (Genau wie regulär find()mit posParameter nur an dieser Position oder später aussieht.) Wenn Sie also bestehen pos == 0, wie in dieser Antwort gezeigt, wird es buchstäblich nur für Übereinstimmungen an dieser einen Position berücksichtigt. Das wurde bereits in der Antwort und in den Kommentaren erklärt.
Arthur Tacca
188

Du würdest es so machen:

std::string prefix("--foo=");
if (!arg.compare(0, prefix.size(), prefix))
    foo_value = atoi(arg.substr(prefix.size()).c_str());

Es ist auch eine gute Idee, nach einer Bibliothek wie Boost.ProgramOptions zu suchen, die dies für Sie erledigt.

Thomas
quelle
7
Das größte Problem dabei ist die atoi("123xyz")Rückkehr 123, während Pythons int("123xyz")eine Ausnahme auslöst.
Tom
Die Problemumgehung besteht darin, ein sscanf () zu erstellen und das Ergebnis und das Original zu vergleichen, um zu entscheiden, ob fortgefahren oder eine Ausnahme ausgelöst werden soll.
Roopesh Majeti
1
Oder ersetzen Sie einfach atoimit strtoloder strtoll, was lässt uns Fehlerbedingungen in dem Eingabewert erkennen.
Tom
1
Dies ist eine bessere Lösung als die rfind, die von der Optimierung abhängt, um zu funktionieren.
Calmarius
143

Der Vollständigkeit halber werde ich die C-Methode erwähnen:

Wenn stres sich um Ihre ursprüngliche Zeichenfolge handelt, substrist dies die Teilzeichenfolge, die Sie überprüfen möchten

strncmp(str, substr, strlen(substr))

wird zurückkehren, 0wenn mit str beginnt substr. Die Funktionen strncmpund strlenbefinden sich in der C-Header-Datei<string.h>

(ursprünglich von Yaseen Rauf hier gepostet , Markup hinzugefügt)

Verwenden Sie für einen Vergleich ohne Berücksichtigung der Groß- und Kleinschreibung strnicmpanstelle von strncmp.

Dies ist die C-Methode. Für C ++ - Zeichenfolgen können Sie dieselbe Funktion wie folgt verwenden:

strncmp(str.c_str(), substr.c_str(), substr.size())
Felix Dombek
quelle
9
in der Tat scheint jeder nur "use boost" zu gehen und ich bin dankbar für eine stl- oder OS-Bibliotheksversion
Force Gaia
Ja. Es wird jedoch davon ausgegangen, dass die Zeichenfolge keine Nullzeichen enthält. Wenn es nicht der Fall ist - sollte man verwendenmemcmp()
Avishai Y
Warum sollte jemand etwas anderes als diese einfache, schöne Lösung verwenden?
Adam Zahran
88

Wenn Sie Boost bereits verwenden, können Sie dies mit Boost-String-Algorithmen + Boost-Lexikon-Cast tun :

#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>

try {    
    if (boost::starts_with(argv[1], "--foo="))
        foo_value = boost::lexical_cast<int>(argv[1]+6);
} catch (boost::bad_lexical_cast) {
    // bad parameter
}

Diese Art von Ansatz ist, wie viele der anderen hier bereitgestellten Antworten, für sehr einfache Aufgaben in Ordnung, aber auf lange Sicht ist es normalerweise besser, eine Befehlszeilen-Analysebibliothek zu verwenden. Boost hat eine ( Boost.Program_options ), die sinnvoll sein kann, wenn Sie Boost bereits verwenden.

Andernfalls bietet eine Suche nach "c ++ - Befehlszeilenparser" eine Reihe von Optionen.

Ferruccio
quelle
107
Das Einziehen großer Abhängigkeiten für eine Zeichenfolgenpräfixprüfung ist wie das Schießen von Vögeln mit Kanonen.
Tobi
150
"Use Boost" ist immer die falsche Antwort, wenn jemand fragt, wie eine einfache Zeichenfolgenoperation in C ++ ausgeführt werden soll.
Glenn Maynard
90
minus 1 für den Vorschlag Boost
hässlicher Kojote
37
Die Verwendung von Boost ist hier richtig, wenn Sie Boost bereits in Ihrem Projekt verwenden.
Alex Che
17
Der Antwort wird "Wenn Sie Boost verwenden ..." vorangestellt. Dies ist eindeutig die richtige Antwort "... wenn Sie Boost verwenden". Wenn nicht, schauen Sie sich den Vorschlag von @Thomas
NuSkooler
82

Code, den ich selbst benutze:

std::string prefix = "-param=";
std::string argument = argv[1];
if(argument.substr(0, prefix.size()) == prefix) {
    std::string argumentValue = argument.substr(prefix.size());
}
Hüseyin Yağlı
quelle
2
Das prägnanteste und hängt nur von std :: string ab, außer dass das optionale und irreführende Argument.size () am Ende des endgültigen Substrats entfernt wird.
Ben Bryant
@ Ben-Bryant: Danke für das Heads Up. Wusste nicht, dass es optional war.
Hüseyin Yağlı
16
Die Verwendung substrführt zu unnötigem Kopieren. Die str.compare(start, count, substr)in Thomas 'Antwort verwendete Methode ist effizienter. Die Antwort von razvanco13 enthält eine andere Methode, mit der das Kopieren mit vermieden wird std::equal.
Felix Dombek
4
@ HüseyinYağlı Thomas uses atoi which is only for windowsHuh? atoiist seit ... je eine C-Standard-Bibliotheksfunktion. In der Tat atoiist es schlecht - nicht weil es Windows-spezifisch ist - sondern weil es (1) C, nicht C ++ und (2) sogar in C veraltet ist (Sie sollten strtoloder eine der anderen verwandten Funktionen verwenden. Weil atoihat Keine Fehlerbehandlung. Aber auch das ist sowieso nur in C.
Parthian Shot
50

Bisher hat noch niemand die STL- Algorithmus / Mismatch- Funktion verwendet. Wenn dies true zurückgibt, ist das Präfix ein Präfix von 'toCheck':

std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()

Vollständiges Beispiel-Prog:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char** argv) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "Will print true if 'prefix' is a prefix of string" << std::endl;
        return -1;
    }
    std::string prefix(argv[1]);
    std::string toCheck(argv[2]);
    if (prefix.length() > toCheck.length()) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "'prefix' is longer than 'string'" <<  std::endl;
        return 2;
    }
    if (std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()) {
        std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck << '"' << std::endl;
        return 0;
    } else {
        std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"' << toCheck << '"' << std::endl;
        return 1;
    }
}

Bearbeiten:

Wie @James T. Huggett vorschlägt, passt std :: gleich besser zu der Frage: Ist A ein Präfix von B? und ist etwas kürzer Code:

std::equal(prefix.begin(), prefix.end(), toCheck.begin())

Vollständiges Beispiel-Prog:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char **argv) {
  if (argc != 3) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "Will print true if 'prefix' is a prefix of string"
              << std::endl;
    return -1;
  }
  std::string prefix(argv[1]);
  std::string toCheck(argv[2]);
  if (prefix.length() > toCheck.length()) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "'prefix' is longer than 'string'" << std::endl;
    return 2;
  }
  if (std::equal(prefix.begin(), prefix.end(), toCheck.begin())) {
    std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck
              << '"' << std::endl;
    return 0;
  } else {
    std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"'
              << toCheck << '"' << std::endl;
    return 1;
  }
}
matiu
quelle
2
Warum nicht std :: gleich verwenden?
Brice M. Dempsey
Klingt gut für mich. Es wäre auch kürzerer Code. Ich sagte, ich muss die Antwort jetzt bearbeiten: p
matiu
2
Die Verwendung std::equalfür Zeichenfolgen hat den Nachteil, dass das Zeichenfolgenende nicht erkannt wird. Sie müssen daher manuell prüfen, ob das Präfix kürzer als die gesamte Zeichenfolge ist. (Wie im Beispiel-Prog richtig gemacht, aber im Einzeiler oben weggelassen.)
Felix Dombek
Also kein Vorteil gegenüber rfind?
10ндрей Вахрушев
26

Angesichts der Tatsache, dass beide Zeichenfolgen - argv[1]und "--foo"- C-Zeichenfolgen sind, ist die Antwort von @ FelixDombek zweifellos die beste Lösung.

Angesichts der anderen Antworten hielt ich es jedoch für erwähnenswert, dass es std::stringeine einfache, maximal kopierfähige, maximal effiziente Lösung gibt, die bisher noch nicht erwähnt wurde , wenn Ihr Text bereits als verfügbar ist:

const char * foo = "--foo";
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(strlen(foo));

Und wenn foo schon ein String ist:

std::string foo("--foo");
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(foo.length());
Marcelo Cantos
quelle
6
rfind(x, 0) == 0sollte wirklich im Standard definiert werden alsstarts_with
porges
1
Nein, weil rfind()(anstelle von startswith()) sehr ineffizient ist - es wird bis zum Ende der Zeichenfolge gesucht.
Ankostis
4
@ankostis rfind (x) sucht vom Ende bis zum Anfang, bis es tatsächlich x findet. Aber rfind (x, 0) beginnt von Anfang an (Position = 0) bis zum Start zu suchen. es sucht also nur dort, wo es gesucht werden muss; sucht nicht von / bis zum Ende.
Anonymer Feigling
18

Mit C ++ 17 können Sie std::basic_string_view& mit C ++ 20 std::basic_string::starts_withoder verwenden std::basic_string_view::starts_with.

Der Vorteil std::string_viewim Vergleich zu std::string- in Bezug auf die Speicherverwaltung - besteht darin, dass es nur einen Zeiger auf eine "Zeichenfolge" (zusammenhängende Folge von char-ähnlichen Objekten) enthält und deren Größe kennt. Beispiel ohne Verschieben / Kopieren der Quellzeichenfolgen, um den ganzzahligen Wert zu erhalten:

#include <exception>
#include <iostream>
#include <string>
#include <string_view>

int main()
{
    constexpr auto argument = "--foo=42"; // Emulating command argument.
    constexpr auto prefix = "--foo=";
    auto inputValue = 0;

    constexpr auto argumentView = std::string_view(argument);
    if (argumentView.starts_with(prefix))
    {
        constexpr auto prefixSize = std::string_view(prefix).size();
        try
        {
            // The underlying data of argumentView is nul-terminated, therefore we can use data().
            inputValue = std::stoi(argumentView.substr(prefixSize).data());
        }
        catch (std::exception & e)
        {
            std::cerr << e.what();
        }
    }
    std::cout << inputValue; // 42
}
Roi Danton
quelle
1
@ RolandIllig Nein, std::atoiist völlig in Ordnung. Bei schlechten Eingaben (die in diesem Code behandelt werden) werden Ausnahmen ausgelöst. Hattest du noch etwas anderes im Sinn?
Roi Danton
Sprechen Sie über die atoivon <cstdlib>? In der Dokumentation heißt es "es werden niemals Ausnahmen ausgelöst".
Roland Illig
@ RolandIllig Ich beziehe mich auf Ihren ersten Kommentar. Es scheint, Sie sprechen fälschlicherweise über atoistatt std::atoi. Der erste ist unsicher zu verwenden, während der zweite in Ordnung ist. Ich verwende letzteres im Code hier.
Roi Danton
Bitte beweisen Sie mir, dass dies std::atoitatsächlich eine Ausnahme darstellt, indem Sie eine geeignete Referenz angeben. Bis du es tust, glaube ich dir nicht, da es sehr verwirrend wäre, beides zu haben ::atoiund std::atoiganz anders zu handeln.
Roland Illig
4
@ RolandIllig Danke, dass du hartnäckig bist! Sie haben Recht, es war ein Versehen, std::atoidas anstelle von verwendet wurde std::stoi. Ich habe das behoben.
Roi Danton
12
text.substr(0, start.length()) == start
Macsinus
quelle
3
@ GregorDoroschenko beantwortet den Teil "Überprüfen, ob die Zeichenfolge mit einem anderen beginnt".
Etarion
1
Effizient und elegant mit std :: string. Daraus habe ich am meisten gelernt.
Michael B
1
Extrapunkte für einen if (one-liner)
Einzeiler, der
@ Roland Illig Warum glaubst du, dass das Verhalten in diesem Fall undefiniert ist? Der Ausdruck gibt false zurück, da substr eine Zeichenfolge mit der gleichen Länge wie Text gemäß en.cppreference.com/w/cpp/string/basic_string/substr
Macsinus
11

Mit STL könnte dies so aussehen:

std::string prefix = "--foo=";
std::string arg = argv[1];
if (prefix.size()<=arg.size() && std::equal(prefix.begin(), prefix.end(), arg.begin())) {
  std::istringstream iss(arg.substr(prefix.size()));
  iss >> foo_value;
}
razvanco13
quelle
2
Das sollte sein if (prefix.size()<=arg.size() && std::equal(...)).
Jared Grubb
10

Dieses sscanfBeispiel ist meiner Meinung nach eleganter als die meisten Boost-Lösungen, da die Gefahr besteht, dass es für die Verwendung von C-Konstrukten in Flammen steht. Und Sie müssen sich keine Gedanken über die Verknüpfung machen, wenn Sie irgendwo mit einem Python-Interpreter arbeiten!

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    for (int i = 1; i != argc; ++i) {
        int number = 0;
        int size = 0;
        sscanf(argv[i], "--foo=%d%n", &number, &size);
        if (size == strlen(argv[i])) {
            printf("number: %d\n", number);
        }
        else {
            printf("not-a-number\n");
        }
    }
    return 0;
}

Hier ist eine Beispielausgabe, die zeigt, dass die Lösung führenden / nachfolgenden Müll genauso korrekt behandelt wie den entsprechenden Python-Code und korrekter als alles, atoiwas verwendet wird (wodurch ein nicht numerisches Suffix fälschlicherweise ignoriert wird).

$ ./scan --foo=2 --foo=2d --foo='2 ' ' --foo=2'
number: 2
not-a-number
not-a-number
not-a-number
Tom
quelle
7
Wenn dies der Fall argv[i]ist "--foo=9999999999999999999999999", ist das Verhalten undefiniert (obwohl sich die meisten oder alle Implementierungen ordnungsgemäß verhalten sollten). Ich gehe davon aus 9999999999999999999999999 > INT_MAX.
Keith Thompson
10

Ich verwende eine std::string::comparein Dienstprogramm eingeschlossene Methode wie folgt:

static bool startsWith(const string& s, const string& prefix) {
    return s.size() >= prefix.size() && s.compare(0, prefix.size(), prefix) == 0;
}
Shital Shah
quelle
5

Warum nicht gnu getopts verwenden? Hier ist ein grundlegendes Beispiel (ohne Sicherheitsüberprüfungen):

#include <getopt.h>
#include <stdio.h>

int main(int argc, char** argv)
{
  option long_options[] = {
    {"foo", required_argument, 0, 0},
    {0,0,0,0}
  };

  getopt_long(argc, argv, "f:", long_options, 0);

  printf("%s\n", optarg);
}

Für den folgenden Befehl:

$ ./a.out --foo=33

Sie erhalten

33
Carl Cook
quelle
5

Wenn Sie C ++ 11-Kompatibilität benötigen und Boost nicht verwenden können, finden Sie hier ein Boost-kompatibles Drop-In mit einem Anwendungsbeispiel:

#include <iostream>
#include <string>

static bool starts_with(const std::string str, const std::string prefix)
{
    return ((prefix.size() <= str.size()) && std::equal(prefix.begin(), prefix.end(), str.begin()));
}

int main(int argc, char* argv[])
{
    bool usage = false;
    unsigned int foos = 0; // default number of foos if no parameter was supplied

    if (argc > 1)
    {
        const std::string fParamPrefix = "-f="; // shorthand for foo
        const std::string fooParamPrefix = "--foo=";

        for (unsigned int i = 1; i < argc; ++i)
        {
            const std::string arg = argv[i];

            try
            {
                if ((arg == "-h") || (arg == "--help"))
                {
                    usage = true;
                } else if (starts_with(arg, fParamPrefix)) {
                    foos = std::stoul(arg.substr(fParamPrefix.size()));
                } else if (starts_with(arg, fooParamPrefix)) {
                    foos = std::stoul(arg.substr(fooParamPrefix.size()));
                }
            } catch (std::exception& e) {
                std::cerr << "Invalid parameter: " << argv[i] << std::endl << std::endl;
                usage = true;
            }
        }
    }

    if (usage)
    {
        std::cerr << "Usage: " << argv[0] << " [OPTION]..." << std::endl;
        std::cerr << "Example program for parameter parsing." << std::endl << std::endl;
        std::cerr << "  -f, --foo=N   use N foos (optional)" << std::endl;
        return 1;
    }

    std::cerr << "number of foos given: " << foos << std::endl;
}
vallismortis
quelle
2

Sie können auch verwenden strstr:

if (strstr(str, substr) == substr) {
    // 'str' starts with 'substr'
}

aber ich denke, es ist nur für kurze Strings gut, weil es den gesamten String durchlaufen muss, wenn der String nicht mit 'substr' beginnt.

szx
quelle
2

Ok, warum die komplizierte Verwendung von Bibliotheken und Sachen? C ++ String-Objekte überladen den Operator [], sodass Sie nur Zeichen vergleichen können. Wie ich es gerade getan habe, weil ich alle Dateien in einem Verzeichnis auflisten und unsichtbare Dateien und die .. und ignorieren möchte. Pseudodateien.

while ((ep = readdir(dp)))
{
    string s(ep->d_name);
    if (!(s[0] == '.')) // Omit invisible files and .. or .
        files.push_back(s);
}

So einfach ist das.

Nils
quelle
4
Eine Lektion in der Geschichte: plus.sandbox.google.com/+RobPikeTheHuman/posts/R58WgWwN9jp
robertwb
2
@robertwb Google+ ist nicht mehr verfügbar
_Static_assert
0
std::string text = "--foo=98";
std::string start = "--foo=";

if (text.find(start) == 0)
{
    int n = stoi(text.substr(start.length()));
    std::cout << n << std::endl;
}
Mois
quelle
3
Es wäre großartig, wenn Sie vermeiden würden, Code ohne Codeerklärung einzufügen. Danke dir.
Wiedergeboren
1
Ineffizienter Code würde die Suche nach dem Anfang der Zeichenfolge fortsetzen.
Ankostis
0

Mit C ++ 11 oder höher können Sie find()und verwendenfind_first_of()

Beispiel mit find, um ein einzelnes Zeichen zu finden:

#include <string>
std::string name = "Aaah";
size_t found_index = name.find('a');
if (found_index != std::string::npos) {
    // Found string containing 'a'
}

Beispiel mit find, um eine vollständige Zeichenfolge zu finden und ab Position 5:

std::string name = "Aaah";
size_t found_index = name.find('h', 3);
if (found_index != std::string::npos) {
    // Found string containing 'h'
}

Beispiel mit dem find_first_of()und nur dem ersten Zeichen, um nur am Anfang zu suchen:

std::string name = ".hidden._di.r";
size_t found_index = name.find_first_of('.');
if (found_index == 0) {
    // Found '.' at first position in string
}

Viel Glück!

Gefahr89
quelle
Warum nicht finden? rfind (str, 0) scannt nicht unnötig eine ganze Zeichenfolge, um eine Auswahl zu treffen, da sie nicht vorrücken kann. Andere sehen.
user2864740
0

Da C ++ 11 std::regex_searchauch verwendet werden kann, um noch komplexere Ausdrücke abzugleichen. Das folgende Beispiel behandelt auch schwebende Zahlen durch std::stofund eine nachfolgende Umwandlung in int.

Die parseIntunten gezeigte Methode kann jedoch eine std::invalid_argumentAusnahme auslösen, wenn das Präfix nicht übereinstimmt. Dies kann je nach Anwendung leicht angepasst werden:

#include <iostream>
#include <regex>

int parseInt(const std::string &str, const std::string &prefix) {
  std::smatch match;
  std::regex_search(str, match, std::regex("^" + prefix + "([+-]?(?=\\.?\\d)\\d*(?:\\.\\d*)?(?:[Ee][+-]?\\d+)?)$"));
  return std::stof(match[1]);
}

int main() {
    std::cout << parseInt("foo=13.3", "foo=") << std::endl;
    std::cout << parseInt("foo=-.9", "foo=") << std::endl;
    std::cout << parseInt("foo=+13.3", "foo=") << std::endl;
    std::cout << parseInt("foo=-0.133", "foo=") << std::endl;
    std::cout << parseInt("foo=+00123456", "foo=") << std::endl;
    std::cout << parseInt("foo=-06.12e+3", "foo=") << std::endl;

//    throw std::invalid_argument
//    std::cout << parseInt("foo=1", "bar=") << std::endl;

    return 0;
}

Die Art der Magie des Regex-Musters wird in der folgenden Antwort ausführlich beschrieben .

BEARBEITEN: Die vorherige Antwort hat die Konvertierung in eine Ganzzahl nicht durchgeführt.

alextoind
quelle
0

Ab C ++ 20 können Sie die starts_withMethode verwenden.

std::string s = "abcd";
if (s.starts_with("abc")) {
    ...
}
Sam Kumar
quelle
-3
if(boost::starts_with(string_to_search, string_to_look_for))
    intval = boost::lexical_cast<int>(string_to_search.substr(string_to_look_for.length()));

Dies ist völlig ungetestet. Das Prinzip ist das gleiche wie beim Python. Benötigt Boost.StringAlgo und Boost.LexicalCast.

Überprüfen Sie, ob die Zeichenfolge mit der anderen Zeichenfolge beginnt, und rufen Sie dann die Teilzeichenfolge ('Slice') der ersten Zeichenfolge ab und konvertieren Sie sie mit lexikalischer Umwandlung.

blwy10
quelle