Oder suchen Sie andersherum das erste Nichtziffernzeichen.
Gelten die gleichen Funktionen für string und für char* ?
Oder suchen Sie andersherum das erste Nichtziffernzeichen.
Gelten die gleichen Funktionen für string und für char* ?
Natürlich gibt es viele Möglichkeiten, eine Zeichenfolge nur auf numerische Zeichen zu testen. Zwei mögliche Methoden sind:
bool is_digits(const std::string &str)
{
return str.find_first_not_of("0123456789") == std::string::npos;
}
oder
bool is_digits(const std::string &str)
{
return std::all_of(str.begin(), str.end(), ::isdigit); // C++11
}
Warum ist hier ein doppelter Doppelpunkt in isdigit ? Es kompiliert nicht ohne es, std::isdigit
geht auch nicht.
– Dfr
9. November 2013 um 7:39 Uhr
@Dfr: Es gibt mehr als einen isdigit
Funktionen (ab <cctype>
und <locale>
Kopfzeilen). Siehe diese verwandte Antwort.
– Hochofen
9. November 2013 um 7:50 Uhr
Der C ++ 11-Weg rockt ehrlich gesagt 🙂
– dk123
5. Mai 2014 um 12:54 Uhr
@Jichao: Du hast Recht, aber das wäre eine andere Frage.
– Hochofen
12. Juni 2014 um 21:05 Uhr
@AmitUpadhyay: Ich habe Referenzen verwendet, um das Kopieren der Weitergabe zu vermeiden std::string
Parameter (Kopieren wäre möglicherweise teuer). Sie sind auch const
um sicherzustellen, dass ich die Variablen des Aufrufers nicht ändere. Die Verwendung von konstanten Referenzen auf diese Weise ist in der C++-Programmierung weit verbreitet.
– Hochofen
18. Januar 2017 um 14:35 Uhr
Dietmar Kühl
Mehrere Personen haben bereits die Verwendung erwähnt isdigit()
. Beachten Sie jedoch, dass dies nicht ganz trivial ist, weil char
kann signiert werden, was dazu führen würde, dass ein negativer Wert übergeben wird isdigit()
. Diese Funktion kann jedoch nur positive Werte annehmen. Das heißt, Sie möchten etwas Ähnliches:
if (s.end() == std::find_if(s.begin(), s.end(),
[](unsigned char c)->bool { return !isdigit(c); })) {
std::cout << "string '" << s << "' contains only digits\n";
}
Es scheint die Begründung für die Umstellung zu sein unsigned char
ist nicht offensichtlich. Hier sind also die relevanten Zitate aus den jeweiligen Standards:
Gemäß ISO/IEC 9899:2011 (bzw. ISO/IEC 9899:1999) 7.4 Absatz 1 gilt für die Argumente der Funktionen ab <ctype.h>
:
… In allen Fällen ist das Argument ein
int
deren Wert als darstellbar sein sollunsigned char
oder soll gleich dem Wert des Makros seinEOF
. Wenn das Argument einen anderen Wert hat, ist das Verhalten undefiniert.
Leider gibt der C++-Standard dies nicht vor char
ist ein vorzeichenloser Typ. Stattdessen spezifiziert sie in ISO/IEC 14882:2011 3.9.1 [basic.fundamental] Absatz 1:
… Es ist implementierungsabhängig, ob a
char
Objekt kann negative Werte enthalten. …
Natürlich kann ein negativer Wert nicht als dargestellt werden unsigned char
. Das heißt, wenn char
verwendet einen signierten Typ für eine Implementierung (es gibt tatsächlich mehrere, die dies tun, z. B. wird es unter MacOS mit gcc oder clang signiert), besteht die Gefahr, dass der Aufruf einer der <ctype.h>
Funktion würde undefiniertes Verhalten verursachen.
Nun, warum funktioniert die Umstellung auf unsigned char
macht die richtigen Dinge?
Gemäß 4.7 [conv.integral] Absatz 2:
Wenn der Zieltyp vorzeichenlos ist, ist der resultierende Wert die kleinste vorzeichenlose Ganzzahl, die kongruent zur Quell-Ganzzahl ist (Modulo 2n wobei n die Anzahl der Bits ist, die zur Darstellung des vorzeichenlosen Typs verwendet werden). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
Das heißt, die Umwandlung von a [potentially] unterzeichnet char
zu unsigned char
ist wohldefiniert und führt dazu, dass das Ergebnis im zulässigen Bereich für die liegt <ctype.h>
Funktionen.
Ich bin mir nicht sicher, ob ich Sie verstehe: Sagen Sie das Konvertieren char
zu unsigned char
die möglicherweise Überläufe oder UB erzeugen, ist eine bessere Idee, als sich darauf zu verlassen isdigit()
Überprüfung auf c
sein von ['0'..'9']
die speziell nimmt int
als Eingang? Jegliche Zitate oder Begründungen könnten hilfreich sein, wenn möglich.
– Sebastian Mach
13. Februar 2013 um 16:56 Uhr
Die Umstellung von char
zu unsigned char
wird nicht überlaufen oder so. Es behält die ursprünglichen Bits bei, ergibt aber einen Wert im definierten Bereich von isdigit()
selbst wenn char
vorzeichenbehaftet ist und das Zeichen im negativen Bereich liegt. Das relevante Zitat befindet sich in C’s 7.4 Absatz 1.
– Dietmar Kühl
13. Februar 2013 um 20:29 Uhr
isdigit(int)
sagt Ihnen, ob ein Zeichen eine Ziffer ist. Wenn Sie von ASCII und Basis 10 ausgehen, können Sie auch Folgendes verwenden:
int first_non_digit_offset= strspn(string, "0123456789")
Im gleichen Sinne wie Mischas Antwort, aber richtiger: sscanf(buf, "%*u%*c")==1
.
scanf
gibt 0 zurück, wenn die %d
die Ziffernextraktion schlägt fehl, und 2, wenn nach den von erfassten Ziffern etwas steht %c
. Und da *
verhindert, dass der Wert gespeichert wird, Sie können nicht einmal einen Überlauf bekommen.
paxdiablo
Die cctype
Header-Datei hat eine gute Anzahl von Zeichenklassifizierungsfunktionen, die Sie für jedes Zeichen in der Zeichenfolge verwenden können. Für numerische Prüfungen wäre das isdigit
.
Das folgende Programm zeigt, wie jedes Zeichen eines C- oder C++-Strings überprüft wird (der Prozess ist ziemlich identisch in Bezug auf die Überprüfung der tatsächlichen Zeichen, der einzige wirkliche Unterschied besteht darin, wie man die Länge erhält):
#include <iostream>
#include <cstring>
#include <cctype>
int main (void) {
const char *xyzzy = "42x";
std::cout << xyzzy << '\n';
for (int i = 0; i < std::strlen (xyzzy); i++) {
if (! std::isdigit (xyzzy[i])) {
std::cout << xyzzy[i] << " is not numeric.\n";
}
}
std::string plugh ("3141y59");
std::cout << plugh << '\n';
for (int i = 0; i < plugh.length(); i++) {
if (! std::isdigit (plugh[i])) {
std::cout << plugh[i] << " is not numeric.\n";
}
}
return 0;
}
Shakiba Moshiri
#include <regex>
std::string string( "I only have 3 dollars!" );
std::cout << std::regex_search( string, std::regex( "\\d+" ) ); // true
und
std::string string( "I only have three dollars!" );
std::cout << std::regex_search( string, std::regex( "\\d+" ) ); // false
sh.e.salh
Von dem cplusplus.com Sie können die isdigit-Funktion wie folgt verwenden:
// isdigit example (C++)
#include <iostream> // std::cout
#include <string> // std::string
#include <locale> // std::locale, std::isdigit
#include <sstream> // std::stringstream
int main ()
{
std::locale loc;
std::string str="1776ad";
if (isdigit(str[0],loc))
{
int year;
std::stringstream(str) >> year;
std::cout << "The year that followed " << year << " was " << (year+1) << ".\n";
}
return 0;
}
Hinweis: Es gibt 2 Arten von isdigits, die andere Version ist lokal unabhängig und ASCII-basiert.