2011-02-07 9 views
8

Najwyraźniej jest to przewidziane do pracy przy pokazywaniu, czy łańcuch jest liczbowy, na przykład "12.5" == tak, "abc" == nie. Jednak nie mam żadnego dostępu do danych wejściowych.Czy mogę stwierdzić, czy std :: string reprezentuje liczbę za pomocą stringstream?

std::stringstream ss("2"); 
double d; ss >> d; 
if(ss.good()) {std::cout<<"number"<<std::endl;} 
else {std::cout<<"other"<<std::endl;} 
+2

Czy "12,5 abc" zakwalifikować jako "ciąg jest liczbową"? Jeśli "nie", żadna z dotychczasowych odpowiedzi nie ma zastosowania. – etarion

Odpowiedz

4

Powinieneś użyć istringstream, aby wiedział, że próbuje przeanalizować dane wejściowe. Ponadto, po prostu sprawdź wynik ekstrakcji bezpośrednio, zamiast później użyć good.

#include <sstream> 
#include <iostream> 

int main() 
{ 
    std::istringstream ss("2"); 
    double d = 0.0; 
    if(ss >> d) {std::cout<<"number"<<std::endl;} 
    else {std::cout<<"other"<<std::endl;} 
} 
+0

Jak w ogóle "ma się problem z analizą danych wejściowych"? Być może dobre dla przejrzystości kodu, ale nie widzę żadnego technicznego powodu. –

+1

Nie sprawdzasz dodatkowych treści. "2 abc" nie jest na przykład liczbą - jest ciągiem z osadzonymi białymi znakami.IIRC, rozwiązaniem jest sprawdzenie {{ss.peek() == EOF}} (wszystko zostało zużyte) lub może patrząc na {{ss.gcount()}}. – Tom

7

Nie używaj dobrze()! Sprawdź, czy strumień jest failed or not:

if (ss) 

Dobry powie Ci, czy któryś z eofbit, badbit lub failbit są ustawione, a nie() opowiada o badbit i failbit. Prawie nigdy nie dbasz o eofbit, chyba że już znasz wiesz, że strumień się nie powiódł, więc prawie nigdy nie chcesz używać dobra.

Należy pamiętać, że badanie strumienia bezpośrednio jak opisano powyżej, jest dokładnie równoważny:

if (!ss.fail()) 

Odwrotnie, p odpowiada ss.fail().


Łącząc ekstrakcji w wyrażeniu warunkowym:

if (ss >> d) {/*...*/} 

Czy dokładnie równoważne:

ss >> d; 
if (ss) {/*...*/} 

Jednakże, prawdopodobnie chcesz, aby sprawdzić, czy kompletny łańcuch może być przekształcone w podwójne, co jest nieco bardziej zaangażowane. Użyj algorytmu boost :: lexical_cast, który obsługuje już wszystkie przypadki.

-1
int str2int (const string &str) { 
    stringstream ss(str); 
    int num; 
    if((ss >> num).fail()) 
    { 
     //ERROR: not a number 
    } 
    return num; 
} 
5

Jeśli chcesz sprawdzić, czy string zawiera tylko numer i nic innego (z wyjątkiem spacji), użyj tego:

#include <sstream> 

bool is_numeric (const std::string& str) { 
    std::istringstream ss(str); 
    double dbl; 
    ss >> dbl;  // try to read the number 
    ss >> std::ws; // eat whitespace after number 

    if (!ss.fail() && ss.eof()) { 
     return true; // is-a-number 
    } else { 
     return false; // not-a-number 
    } 
} 

ss >> std::ws jest ważne dla akceptacji numery z końcowe spacje takiego jako "24 ".

Kontrola ss.eof() jest ważna dla odrzucania ciągów takich jak "24 abc". Zapewnia to, że dotarliśmy do końca ciągu po przeczytaniu liczby (i białych znaków).

uprząż Test:

#include <iostream> 
#include <iomanip> 

int main() 
{ 
    std::string tests[8] = { 
      "", "XYZ", "a26", "3.3a", "42 a", "764", " 132.0", "930 " 
    }; 
    std::string is_a[2] = { "not a number", "is a number" }; 
    for (size_t i = 0; i < sizeof(tests)/sizeof(std::string); ++i) { 
     std::cout << std::setw(8) << "'" + tests[i] + "'" << ": "; 
     std::cout << is_a [is_numeric (tests[i])] << std::endl; 
    } 
} 

wyjściowa:

 '': not a number 
    'XYZ': not a number 
    'a26': not a number 
    '3.3a': not a number 
    '42 a': not a number 
    '764': is a number 
' 132.0': is a number 
    '930 ': is a number 
Powiązane problemy