Wie kann man mit C++ feststellen, ob eine Zeichenfolge eine Zahl ist?

Lesezeit: 6 Minuten

Wie kann man mit C feststellen ob eine Zeichenfolge eine
Brendan Weinstein

Ich hatte ziemliche Probleme beim Versuch, eine Funktion zu schreiben, die überprüft, ob eine Zeichenfolge eine Zahl ist. Für ein Spiel, das ich schreibe, muss ich nur prüfen, ob eine Zeile aus der Datei, die ich lese, eine Zahl ist oder nicht (auf diese Weise werde ich wissen, ob es sich um einen Parameter handelt). Ich habe die folgende Funktion geschrieben, von der ich glaube, dass sie reibungslos funktioniert (oder ich habe sie versehentlich bearbeitet, um sie zu stoppen, oder ich bin schizophren oder Windows ist schizophren):

bool isParam (string line)
{
    if (isdigit(atoi(line.c_str())))
        return true;

    return false;
}

  • ich hassen Sehen if (expr) return true; return false;! Einfach schreiben return expr;.

    – vergänglich

    11. Januar 2011 um 6:08 Uhr


  • @ephemient Mein Stil ist es, dasselbe zu tun wie du. Aber ist es wirklich eine große Sache?

    – Brennan Vincent

    11. Januar 2011 um 6:12 Uhr

  • Ja. Ich habe die schlechte Angewohnheit, beim Erlernen einer neuen Sprache im Langstil zu codieren. Ich bin neu in C ++ und zögere mehr mit “Verknüpfungen” (oder wahrgenommenen Verknüpfungen).

    – Brendan Weinstein

    11. Januar 2011 um 6:59 Uhr

  • @Brennan Vincent: Ja, das ist eine große Sache. Es ist die gleiche Klasse von Fehlern wie if (expr) return expr; else return expr; , if (expr == true) , (if expr != false)oder if ((expr == true) == true). Sie alle führen zu Komplexität, die dem Autor, Leser oder Compiler des Codes nicht zugute kommt. Die Eliminierung unnötiger Komplexität ist keine Abkürzung; es ist der Schlüssel zum Schreiben besserer Software.

    – MSalter

    11. Januar 2011 um 8:24 Uhr

  • @MSalters Persönlich denke ich nicht, dass die OP-Version unbedingt so schlecht ist. Ich verwende dieses Konstrukt, wenn ich vermute, dass zwischen der if-Anweisung und der return-Anweisung mehr Code vorhanden sein könnte. Erst wenn ich sicher weiß, dass es nichts anderes geben wird, reduziere ich es, um expr zurückzugeben.

    – TStancek

    18. März 2019 um 11:29 Uhr

Wie kann man mit C feststellen ob eine Zeichenfolge eine
Ben Voigt

Warum das Rad neu erfinden? Die C-Standardbibliothek (auch in C++ verfügbar) hat eine Funktion, die genau das tut:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}

Wenn Sie mit Brüchen oder wissenschaftlicher Notation umgehen möchten, gehen Sie mit strtod stattdessen (Sie erhalten eine double Ergebnis).

Wenn Sie hexadezimale und oktale Konstanten im C/C++-Stil zulassen möchten ("0xABC"), dann machen Sie den letzten Parameter 0 stattdessen.

Ihre Funktion kann dann geschrieben werden als

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}

  • Diese Funktion verwirft den Leerraum davor. Sie müssen daher das erste Zeichen für isdigit überprüfen.

    – Chike

    24. Juni 2013 um 8:51 Uhr

  • @chmike: Nach meinem Verständnis der Frage ist das Verwerfen führender Leerzeichen das richtige Verhalten (atoi wie in der Frage verwendet, tut dies auch).

    – Ben Voigt

    24. Juni 2013 um 12:21 Uhr

  • Die Frage hat es nicht explizit angegeben, aber mein Verständnis der Anforderung “überprüft, ob eine Zeichenfolge eine Zahl ist” bedeutet, dass die gesamte Zeichenfolge die Zahl ist, also keine Leerzeichen. Ich hatte das Bedürfnis, darauf hinzuweisen, dass sich Ihre Antwort in dieser Hinsicht von den anderen unterscheidet. Ihre Antwort kann in Ordnung sein, wenn es in Ordnung ist, dass die Zeichenfolge Leerzeichen vor der Zahl enthält.

    – Chike

    1. Juli 2013 um 10:53 Uhr

  • @BenVoigt Das sagst du p wird eingestellt nullptr wenn strtol ist erfolgreich, oder? Das sehe ich nicht 🙁

    – Jonathan Mei

    13. November 2014 um 21:21 Uhr

  • @JonathanMee: Nein, p wird auf die NUL zeigen, die die Zeichenfolge beendet. Damit p != 0 und *p == 0.

    – Ben Voigt

    13. November 2014 um 21:23 Uhr

  • Wenn die Zeichenfolge utf8-Zeichen enthält, erhalten Sie einen Laufzeitfehler.

    – König der Löwen

    23. Februar 2018 um 12:58 Uhr

Sie können dies auf C++-Weise mit boost::lexical_cast tun. Wenn Sie wirklich darauf bestehen, Boost nicht zu verwenden, können Sie einfach untersuchen, was es tut, und das tun. Es ist ziemlich einfach.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }

  • Verwenden try{} catch{} eine gute Idee? Sollten wir es nicht so weit wie möglich vermeiden?

    – Nawaz

    11. Januar 2011 um 6:17 Uhr

  • -1 wegen Missbrauchs von try catch… blogs.msdn.com/b/ericlippert/archive/2008/09/10/…

    – NoSenseetAl

    28. November 2012 um 9:59 Uhr

  • try{} catch{} ist hier angebracht. Allerdings ist catch(…) nur eine schlechte Übung. Verwenden Sie in diesem Fall boost::bad_lexical_cast für Ihren Exception-Handler.

    – NuSkooler

    7. Februar 2013 um 17:59 Uhr

  • Ich habe das Gefühl, dass dies versucht, aus einer Datei zu lesen. Egal, wie viel Sie die Datei überprüfen, Sie werden nicht wissen, ob es möglich ist, daraus zu lesen, bis Sie es tun. Entweder es geht oder nicht. In diesem Fall müssen Sie eine Ausnahme abfangen. In diesem Fall denke ich, dass dies eine völlig gute Methode ist.

    – Casey

    10. Mai 2013 um 0:06 Uhr

  • @EarlGray – Ich wäre sicherlich daran interessiert zu hören, welche betriebssystemabhängigen Aktionen Windows ausführen würde. Der Standard ist ziemlich klar darüber, wie sich dieser Code verhalten soll.

    – Edward Seltsam

    2. August 2013 um 0:46 Uhr

Ich wollte nur diese Idee einbringen, die Iteration verwendet, aber ein anderer Code führt diese Iteration durch:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}

Es ist nicht so robust, wie es sein sollte, wenn nach einem Dezimalpunkt oder Minuszeichen gesucht wird, da mehr als eines von jedem und an jeder Stelle vorhanden sein kann. Das Gute ist, dass es sich um eine einzige Codezeile handelt und keine Bibliothek eines Drittanbieters erforderlich ist.

Entfernen Sie das ‘.’ und ‘-‘ wenn nur positive ganze Zahlen erlaubt sind.

  • Verwenden try{} catch{} eine gute Idee? Sollten wir es nicht so weit wie möglich vermeiden?

    – Nawaz

    11. Januar 2011 um 6:17 Uhr

  • -1 wegen Missbrauchs von try catch … blogs.msdn.com/b/ericlippert/archive/2008/09/10/…

    – NoSenseetAl

    28. November 2012 um 9:59 Uhr

  • try{} catch{} ist hier angebracht. Allerdings ist catch(…) nur eine schlechte Übung. Verwenden Sie in diesem Fall boost::bad_lexical_cast für Ihren Exception-Handler.

    – NuSkooler

    7. Februar 2013 um 17:59 Uhr

  • Ich habe das Gefühl, dass dies versucht, aus einer Datei zu lesen. Egal, wie viel Sie die Datei überprüfen, Sie werden nicht wissen, ob es möglich ist, daraus zu lesen, bis Sie es tun. Entweder es geht oder nicht. In diesem Fall müssen Sie eine Ausnahme abfangen. In diesem Fall denke ich, dass dies eine völlig gute Methode ist.

    – Casey

    10. Mai 2013 um 0:06 Uhr

  • @EarlGray – Ich wäre sicherlich daran interessiert zu hören, welche betriebssystemabhängigen Aktionen Windows ausführen würde. Der Standard ist ziemlich klar darüber, wie sich dieser Code verhalten soll.

    – Edward Seltsam

    2. August 2013 um 0:46 Uhr

1647058810 736 Wie kann man mit C feststellen ob eine Zeichenfolge eine
StaceyGirl

Ich würde einen Regex-Ansatz vorschlagen. Eine vollständige Regex-Übereinstimmung (z. B. using boost::regex) mit

-?[0-9]+([\.][0-9]+)?

würde zeigen, ob die Zeichenfolge eine Zahl ist oder nicht. Dazu gehören positive und negative Zahlen, Ganzzahlen sowie Dezimalzahlen.

Andere Variationen:

[0-9]+([\.][0-9]+)?

(nur positiv)

-?[0-9]+

(nur ganzzahlig)

[0-9]+

(nur positive ganze Zahl)

  • Ähm, ich habe versucht zu benutzen std::regex mit gcc 4.7, gcc 4.8 – beide werfen std::regex_error auf irgendein Zeichen von [ in regexp, even for an innocent “[abc]” (mache ich das falsch?). clang-3.4 ist sich dessen nicht bewusst <regex> überhaupt. Wie auch immer, dies scheint die vernünftigste Antwort zu sein, +1.

    – Dmytro Sirenko

    31. Juli 2013 um 17:41 Uhr


  • @EarlGray: Regex ist nur ab GCC 4.9 richtig verfügbar

    – Leichtigkeitsrennen im Orbit

    1. Februar 2014 um 21:28 Uhr


992660cookie-checkWie kann man mit C++ feststellen, ob eine Zeichenfolge eine Zahl ist?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy