Es gibt eine Reihe von Möglichkeiten, wie Sie dies tun können. Die Methode, die Sie ausprobiert haben, funktioniert nicht, da sich an der Leseposition im Stream kein Zahlenähnliches befindet. Daher wird die Eingabe fehlschlagen und das Fehlerbit des Streams wird gesetzt. Sie werden für immer Schleife, weil Sie nur für eof testen. Read this für weitere Informationen.
Ein einfacher Weg, um eine Zeile zu einem Zeitpunkt zu lesen, und die erste Nummer suchen, indem das zweite Argument std::strtol
ausnutzt:
#include <iostream>
#include <string>
#include <experimental/optional>
std::experimental::optional<int> find_int_strtol(const std::string & s)
{
for(const char *p = s.c_str(); *p != '\0'; p++)
{
char *next;
int value = std::strtol(p, &next, 10);
if(next != p) {
return value;
}
}
return {};
}
int main()
{
for(std::string line; std::getline(std::cin, line);)
{
auto n = find_int_strtol(line);
if(n)
{
std::cout << "Got " << n.value() << " in " << line << std::endl;
}
}
return 0;
}
dies ein wenig klobig ist und es wird auch Negative erfassen, die du willst vielleicht nicht. Aber es ist ein einfacher Ansatz. Der Zeiger next
unterscheidet sich von , wenn Zeichen extrahiert wurden. Andernfalls schlägt die Funktion fehl. Dann inkrementieren Sie um 1 und suchen Sie erneut. Es sieht aus wie eine polynomische Suche, aber es ist linear.
Ich habe std::optional
von C++ 17 verwendet, aber ich war auf einem C++ 14 Compiler testen. Es ist für die Bequemlichkeit. Sie könnten die Funktion ohne sie schreiben.
Beispiel Live is here.
Eine flexiblere Möglichkeit, solche Probleme zu lösen, ist die Verwendung eines regulären Ausdrucks. In diesem Fall genügt eine einfache numerische Regex-Suche. Im Folgenden finden Sie nur positive Ganzzahlen, aber Sie können diese Art von Mustern verwenden, um auch komplexe Daten zu finden. Vergessen Sie beinhalten nicht die Header <regex>
:
std::experimental::optional<int> find_int_regex(const std::string & s)
{
static const std::regex r("(\\d+)");
std::smatch match;
if(std::regex_search(s.begin(), s.end(), match, r))
{
return std::stoi(match[1]);
}
return {};
}
Live-Beispiel is here.
So wollen Sie etwas ignorieren, die keine Zahl sein könnte? Versuchen Sie, in eine Zeichenfolge zu lesen. Verwenden Sie dann einen regulären Ausdruck, um die Zeichenfolge abzugleichen, und wählen Sie die Nummer aus einer der übereinstimmenden Gruppen des regulären Ausdrucks. Verwirrt noch? :-) Die Regex ist zugegebenermaßen einfacher als andere Arten des Lesens wegen der fortlaufenden Reihe von Zeichen wie '123', obwohl' stoi' im Allgemeinen so viele Ganzzahlen von der Vorderseite der Zeichenkette abzieht, wie sie können. YMMV – AndyG
while (! file.eof()) tut nicht, was Sie denken, dass es tut – pm100