2017-05-10 3 views
4

Also ich möchte Zahlen aus einer TXT-Datei als Ganzzahlen lesen.C++ ifstream read only Nummer eines Wortes

datei.txt:

hello 123-abc 
world 456-def 

aktuellen Code:

int number; 
ifstream file("file.txt"); 
while (!file.eof()) 
{ 
    file >> number; //123, 456 
} 

Nun ist diese offensichtlich nicht funktioniert und ive versucht, dies für eine „while“ zu lösen, aber ich kann einfach nicht dieses Problem umgehen, .

+0

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

+1

while (! file.eof()) tut nicht, was Sie denken, dass es tut – pm100

Antwort

1

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.

0

Sie müssen überprüfen, ob die Datei geöffnet ist, dann die aktuelle Zeile erhalten, analysiert dann die aktuelle Zeile die erste Zahl zu erhalten:

std::string currentLine = ""; 
std::string numbers = ""; 
ifstream file("file.txt"); 
if(file.is_open()) 
{ 
    while(std::getline(file, currentLine)) 
    { 
     int index = currentLine.find_first_of(' '); // look for the first space 
     numbers = currentLine.substr(index + 1, xyz); 
    } 
} 

xyz ist die Länge der Zahlen (3 in diesem Fall, wenn immer konstant) oder Sie können nach dem nächsten Leerzeichen suchen, indem Sie einen Teilstring von (index, currentLine.back() - index);

Ich bin sicher, dass Sie den Rest herausfinden können, viel Glück.

+0

Woher wissen Sie, dass die Zahl immer ein Leerzeichen davor haben wird? – paddy

+0

Ich nehme nicht an, dass es ein Standard in diesem Beispiel ist, da er zwei identische Zeilen zeigt, aber das Konzept ist dasselbe, solange in der Datei ein Leerzeichen vor und hinter der Nummer steht. Holen Sie sich einen Teilstring, sehen Sie, ob er in einen int umgewandelt werden kann, wenn nicht, dann versuchen Sie den nächsten Teilstr und so weiter. –

0

Zeile für Zeile lesen und alle Zeichen löschen, die keine Ziffern sind. Beenden Sie mit einem std::stoi bevor Sie zu Ihrem std::vector drücken.

std::ifstream file{"file.txt"}; 
std::vector<int> numbers; 

for (std::string s; std::getline(file, s);) { 
    s.erase(std::remove_if(std::begin(s), std::end(s), 
     [] (char c) { return !::isdigit(c); }), std::end(s)); 
    numbers.push_back(std::stoi(s)); 
} 

Alternativ std::regex_replace verwenden nicht-stellige Zeichen zu entfernen:

auto tmp = std::regex_replace(s, std::regex{R"raw([^\d]+(\d+).+)raw"}, "$1"); 
numbers.push_back(std::stoi(tmp)); 

Live example