Bagaimana cara menentukan apakah suatu string adalah angka dengan C ++?

136

Saya mengalami sedikit kesulitan dalam mencoba menulis fungsi yang memeriksa apakah suatu string adalah angka. Untuk permainan yang saya tulis, saya hanya perlu memeriksa apakah baris dari file yang saya baca adalah angka atau tidak (saya akan tahu apakah ini adalah parameter dengan cara ini). Saya menulis fungsi di bawah ini yang saya percaya berfungsi dengan baik (atau saya tidak sengaja diedit untuk menghentikannya atau saya menderita skizofrenia atau Windows adalah skizofrenia):

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

    return false;
}
Brendan Weinstein
sumber
184
Aku benci melihat if (expr) return true; return false;! Cukup tulis return expr;.
ephemient
17
@ephemient Gaya saya adalah melakukan hal yang sama seperti Anda. Tetapi apakah ini benar-benar masalah besar?
Brennan Vincent
2
Prototipe fungsi Anda sepertinya tidak sesuai. Mengapa tidak menggunakan bool isParam (const string & line)
MikimotoH
4
Ya. Saya memiliki kebiasaan buruk mengkode gaya panjang ketika belajar bahasa baru. Saya baru mengenal C ++ dan lebih ragu untuk "pintasan" (atau pintasan yang dirasakan).
Brendan Weinstein
57
@ Brian Vincent: Ya, ini masalah besar. Ini kelas yang sama dari kesalahan seperti if (expr) return expr; else return expr;, if (expr == true), (if expr != false), atau if ((expr == true) == true). Mereka semua memperkenalkan kompleksitas yang tidak menguntungkan penulis, pembaca, atau penyusun kode. Penghapusan kerumitan yang tidak perlu bukanlah jalan pintas; itu kunci untuk menulis perangkat lunak yang lebih baik.
MSalters

Jawaban:

148

Cara paling efisien adalah dengan mengulangi string sampai Anda menemukan karakter non-digit. Jika ada karakter non-digit, Anda dapat menganggap string bukan angka.

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

Atau jika Anda ingin melakukannya dengan cara C ++ 11:

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

Seperti yang ditunjukkan dalam komentar di bawah, ini hanya berfungsi untuk bilangan bulat positif. Jika Anda perlu mendeteksi bilangan bulat atau pecahan negatif, Anda harus menggunakan solusi berbasis pustaka yang lebih kuat. Meskipun, menambahkan dukungan untuk bilangan bulat negatif cukup sepele.

Charles Salvia
sumber
6
Juga tidak menangani angka negatif dan angka non-keseluruhan. Kita tidak tahu apa persyaratannya berdasarkan pertanyaan itu.
Brennan Vincent
76
Anda juga bisa menggunakannya !s.empty() && s.find_first_not_of("0123456789") == std::string::npos;untuk C ++ 03 one-liner.
kbjorklu
8
Juga tidak menangani angka desimal misalnya: 1.23
littlecodefarmer758
3
@Remy Lebeau, ya benar. Ini sebenarnya tidak mengubah string menjadi int. Ini hanya mengidentifikasi apakah suatu string terdiri dari digit angka. Tidak masalah berapa lama talinya.
Charles Salvia
5
Jangan lupa untuk menyertakan <string> <algorithm>dan <cctype>membuat contoh C ++ 11 berfungsi.
kR105
88

Mengapa menemukan kembali roda? Pustaka standar C (tersedia dalam C ++ juga) memiliki fungsi yang melakukan ini:

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

Jika Anda ingin menangani pecahan atau notasi ilmiah, gunakan strtodsaja (Anda akan mendapatkan doublehasilnya).

Jika Anda ingin memperbolehkan konstanta heksadesimal dan oktal dalam gaya C / C ++ ( "0xABC"), maka buatlah parameter terakhir 0sebagai gantinya.

Fungsi Anda kemudian dapat ditulis sebagai

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
Ben Voigt
sumber
4
Fungsi ini membuang ruang putih di depan. Jadi Anda harus memeriksa dulu char untuk isdigit.
chmike
1
@ chmike: Berdasarkan pemahaman saya tentang pertanyaan, membuang spasi putih utama adalah perilaku yang benar ( atoiseperti yang digunakan dalam pertanyaan, apakah ini juga).
Ben Voigt
1
Pertanyaannya tidak secara spesifik menentukannya, tetapi pemahaman saya tentang persyaratan "memeriksa apakah suatu string adalah angka" berarti bahwa seluruh string adalah angka, sehingga tidak ada spasi. Saya merasa perlu menunjukkan bahwa jawaban Anda berbeda dengan yang lain dalam hal ini. Jawaban Anda mungkin baik-baik saja jika tidak ada masalah jika string memiliki spasi di depan nomor tersebut.
chmike
1
@ BenVoigt Anda mengatakan bahwa pakan ditetapkan nullptrjika strtolberhasil, bukan? Bukan itu yang saya lihat :(
Jonathan Mee
2
@ JonathanMee: Tidak, pakan menunjuk ke NUL yang mengakhiri string. Jadi p != 0dan *p == 0.
Ben Voigt
33

Dengan kompiler C ++ 11, untuk bilangan bulat non-negatif saya akan menggunakan sesuatu seperti ini (perhatikan ::bukan std::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}

http://ideone.com/OjVJWh

szx
sumber
1
Ini jawaban terbaik.
Martin Broadhurst
Jika ada utf8 karakter dalam string, Anda akan mendapatkan error run time.
Lion King
29

Anda dapat melakukannya dengan cara C ++ dengan boost :: lexical_cast. Jika Anda benar-benar bersikeras untuk tidak menggunakan dorongan, Anda bisa memeriksa apa yang dilakukannya dan melakukannya. Sederhana saja.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
Edward Strange
sumber
21
Menggunakan try{} catch{}ide yang bagus? Haruskah kita menghindarinya sebanyak mungkin?
Nawaz
32
-1 untuk menyalahgunakan mencoba menangkap ... blogs.msdn.com/b/ericlippert/archive/2008/09/10/...
NoSenseEtAl
14
coba {} catch {} sesuai di sini. Namun, menangkap (...) hanyalah praktik buruk. Dalam hal ini, gunakan boost :: bad_lexical_cast untuk handler pengecualian Anda.
NuSkooler
5
Saya merasa seperti ini sedang mencoba membaca dari suatu file. Tidak peduli berapa banyak pengecekan yang Anda lakukan pada file Anda tidak akan tahu apakah mungkin untuk membacanya sampai Anda melakukannya. Entah itu akan berhasil atau tidak. Dalam hal ini Anda akan perlu menangkap pengecualian. Jadi dalam hal ini saya pikir ini adalah cara yang sangat baik untuk melakukannya.
Casey
4
@ EarlGray - Saya pasti akan tertarik mendengar apa yang akan dilakukan oleh Windows. Standar ini cukup jelas tentang bagaimana seharusnya kode ini berlaku.
Edward Strange
16

Saya hanya ingin melemparkan ide ini yang menggunakan iterasi tetapi beberapa kode lain melakukan iterasi:

#include <string.h>

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

Ini tidak kuat seperti seharusnya ketika memeriksa titik desimal atau tanda minus karena memungkinkan ada lebih dari satu dan di setiap lokasi. Hal yang baik adalah bahwa itu adalah satu baris kode dan tidak memerlukan perpustakaan pihak ketiga.

Ambil '.' dan '-' jika hanya bilangan bulat positif yang diizinkan.

David Rektor
sumber
kesalahan: 'strspn' tidak dideklarasikan dalam lingkup ini saya pikir ini karena saya kehilangan "#include" tetapi apa
Qwertie
4
Jika Anda akan menggunakan std::string, gunakan find_first_not_offungsi anggotanya.
Ben Voigt
5
Ini akan gagal jika Anda memasukkan string "12.3-4.55-", yang jelas bukan angka yang valid
Buzzrick
Buzzrick, jawaban yang diajukan sudah menyatakan bahwa ini akan gagal dengan non-angka yang Anda sebutkan.
David Rektor
jika Anda batasi hanya untuk "0123456789" maka rumusnya sempurna untuk menguji bilangan bulat
tak
16

Saya menyarankan pendekatan regex. Pertandingan-regex penuh (misalnya, menggunakan boost :: regex ) dengan

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

akan menunjukkan apakah string adalah angka atau bukan. Ini termasuk angka positif dan negatif, bilangan bulat serta desimal.

Variasi lainnya:

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

(hanya positif)

-?[0-9]+

(hanya bilangan bulat)

[0-9]+

(hanya bilangan bulat positif)

Mephane
sumber
Ahem, saya mencoba menggunakan std::regexdengan gcc 4.7, gcc 4.8 - mereka berdua membuang std::regex_errortanda-tanda [di regexp, bahkan untuk "[abc]" yang tidak bersalah (apakah saya melakukan itu salah?). Dentang-3.4 tidak menyadari <regex>sama sekali. Ngomong-ngomong, ini sepertinya jawaban paling jago, +1.
Dmytro Sirenko
3
@EarlGray: Regex hanya tersedia dengan benar dari GCC 4.9
Lightness Races in Orbit
13

Berikut cara lain untuk melakukannya menggunakan <regex>perpustakaan:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}
mpataki14
sumber
Ah, begitu juga. Saya telah memperbarui dengan solusi yang lebih baik. Terima kasih.
mpataki14
Bukankah seharusnya "[(- | +) |] [0-9] +" (plus sebagai ganti bintang), jika tidak regex Anda dapat cocok dengan "-" atau "+" sebagai angka yang valid.
David Mulder
Bagus. Saya tidak yakin apa yang dilakukan (, | dan) di kelas karakter pertama - karakter-karakter tersebut kehilangan makna khusus mereka di dalam kelas karakter sejauh yang saya ketahui. Bagaimana dengan "^ [- +]? [0-9] + $"?
U007D
Mungkin tidak efisien. Setiap kali ini dipanggil, ia memanggil std :: regex constructor yang mengkompilasi regex.
user31264
12

Dengan solusi ini Anda dapat memeriksa semuanya, mulai dari negatif ke angka positif dan bahkan angka mengambang. Ketika Anda mengubah tipe numke integer Anda akan mendapatkan kesalahan jika string berisi titik.

#include<iostream>
#include<sstream>
using namespace std;


int main()
{
      string s;

      cin >> s;

      stringstream ss;
      ss << s;

      float num = 0;

      ss >> num;

      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}

Buktikan: Program C ++

tzwickl
sumber
10

Saya telah menemukan kode berikut ini sebagai yang paling kuat (c ++ 11). Ini menangkap bilangan bulat dan mengapung.

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}
dk123
sumber
Tampaknya garis using namespace std;itu tidak perlu.
Xam
5

Berikut adalah solusi untuk memeriksa bilangan bulat positif:

bool isPositiveInteger(const std::string& s)
{
    return !s.empty() && 
           (std::count_if(s.begin(), s.end(), std::isdigit) == s.size());
}
Jaime Soto
sumber
5

Coba ini:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
Tomasz
sumber
1
Ini hanya menguji bilangan bulat tak bertanda
tidak ada yang istimewa
4

Brendan ini

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

hampir ok.

dengan asumsi string yang dimulai dengan 0 adalah angka, tambahkan saja tanda centang untuk kasus ini

bool isNumber(const string &line) 
{
 if (line[0] == '0') return true;
 return (atoi(line.c_str()));
}

ofc "123hello" akan kembali benar seperti yang dicatat Tony D.

Noam Geffen
sumber
3

Yang paling sederhana yang dapat saya pikirkan di c ++

bool isNumber(string s) {
    if(s.size()==0) return false;
    for(int i=0;i<s.size();i++) {
        if((s[i]>='0' && s[i]<='9')==false) {
            return false;
        }
    }
    return true;
}

Contoh kode kerja: https://ideone.com/nRX51Y

Abhijit Annaldas
sumber
3

Solusi saya menggunakan C ++ 11 regex ( #include <regex>), dapat digunakan untuk pemeriksaan yang lebih tepat, seperti unsigned int, doubledll:

static const std::regex INT_TYPE("[+-]?[0-9]+");
static const std::regex UNSIGNED_INT_TYPE("[+]?[0-9]+");
static const std::regex DOUBLE_TYPE("[+-]?[0-9]+[.]?[0-9]+");
static const std::regex UNSIGNED_DOUBLE_TYPE("[+]?[0-9]+[.]?[0-9]+");

bool isIntegerType(const std::string& str_)
{
  return std::regex_match(str_, INT_TYPE);
}

bool isUnsignedIntegerType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_INT_TYPE);
}

bool isDoubleType(const std::string& str_)
{
  return std::regex_match(str_, DOUBLE_TYPE);
}

bool isUnsignedDoubleType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_DOUBLE_TYPE);
}

Anda dapat menemukan kode ini di http://ideone.com/lyDtfi , ini dapat dengan mudah dimodifikasi untuk memenuhi persyaratan.

aniliitb10
sumber
Saya akan meminta downvoters untuk membantu saya memahami masalah ini, saya akan meningkatkan jawaban saya. Terima kasih.
aniliitb10
2

Solusi berdasarkan komentar oleh kbjorklu adalah:

bool isNumber(const std::string& s)
{
   return !s.empty() && s.find_first_not_of("-.0123456789") == std::string::npos;
}

Seperti halnya jawaban David Rector, tidak kuat untuk merangkai dengan beberapa titik atau tanda minus, tetapi Anda dapat menghapus karakter-karakter itu hanya untuk memeriksa bilangan bulat.


Namun, saya sebagian untuk solusi, berdasarkan solusi Ben Voigt , menggunakan strtodcstdlib untuk melihat nilai desimal, notasi ilmiah / teknik, notasi heksidecimal (C ++ 11), atau bahkan INF / INFINITY / NAN (C ++ 11) adalah:

bool isNumberC(const std::string& s)
{
    char* p;
    strtod(s.c_str(), &p);
    return *p == 0;
}
chappjc
sumber
2

Kami dapat menggunakan kelas stringstream .

    bool isNumeric(string str)
    {
       stringstream stream;                   
       double number;

       stream<<str;
       stream>>number;

       return stream.eof();
    }
ruam
sumber
2

Menggunakan <regex>. Kode ini telah diuji!

bool isNumber(const std::string &token)
{
    return std::regex_match(token, std::regex("(\\+|-)?[0-9]*(\\.?([0-9]+))$"));
}
Nery Jr
sumber
1

Setelah membaca dokumentasi sedikit lebih lama, saya menemukan jawaban yang mendukung kebutuhan saya, tetapi mungkin tidak akan membantu orang lain. Ini dia (tanpa pengembalian yang mengganggu benar dan mengembalikan pernyataan palsu :-))

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}
Brendan Weinstein
sumber
4
Jika nomornya kebetulan 0, Anda akan mendapatkan false-negative.
Charles Salvia
3
Ini akan mengembalikan nomor utama apa pun, dan tidak memperingatkan Anda tentang jejak sampah (mis. "123hello" ==> 123). @ Charles: Brendan menyebutkan dia hanya perlu mengenali int positif dalam komentar pada jawaban lain.
Tony Delroy
1

Saya pikir ungkapan reguler ini harus menangani hampir semua kasus

"^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"

sehingga Anda dapat mencoba fungsi berikut yang dapat bekerja dengan keduanya (Unicode dan ANSI)

bool IsNumber(CString Cs){
Cs.Trim();

#ifdef _UNICODE
std::wstring sr = (LPCWSTR)Cs.GetBuffer(Cs.GetLength());
return std::regex_match(sr, std::wregex(_T("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?")));

#else
    std::string s = (LPCSTR)Cs.GetBuffer();
return std::regex_match(s, std::regex("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"));
#endif
}
Motaz
sumber
1
include <string>

Untuk Memvalidasi Ganda:

bool validateDouble(const std::string & input) {
int decimals = std::count(input.begin(), input.end(), '.'); // The number of decimals in the string
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == decimals + negativeSigns) // Consists of only decimals and negatives or is empty
    return false;
else if (1 < decimals || 1 < negativeSigns) // More than 1 decimal or negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-.0123456789") != input.size()) // The string contains a character that isn't in "-.0123456789"
    return false;
return true;

}

Untuk Memvalidasi Ints (Dengan Negatif)

bool validateInt(const std::string & input) {
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == negativeSigns) // Consists of only negatives or is empty
    return false;
else if (1 < negativeSigns) // More than 1 negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-0123456789") != input.size()) // The string contains a character that isn't in "-0123456789"
    return false;
return true;

}

Untuk Memvalidasi Para Unsigned Ints

bool validateUnsignedInt(const std::string & input) {
return (input.size() != 0 && strspn(input.c_str(), "0123456789") == input.size()); // The string is not empty and contains characters only in "0123456789"

}

Erik Nordin
sumber
1
bool isNumeric(string s){
    if ( !s.empty() && s[0] != '-' )
        s = "0" + s; //prepend 0

    string garbage;

    stringstream ss(s); 
    ss >> *(auto_ptr<double>(new double)) >> garbage;
/*
//the line above extracts the number into an anonymous variable. it could also be done like this:
double x;
ss >> x >> garbage;
*/
    //if there is no garbage return true or else return false
    return garbage.empty(); 
}

cara kerjanya: stringstream >> overload dapat mengonversi string ke berbagai tipe aritmatika yang dilakukannya dengan membaca karakter secara berurutan dari stringstream (ss dalam kasus ini) hingga kehabisan karakter ATAU karakter berikutnya tidak memenuhi kriteria untuk disimpan ke dalam tipe variabel tujuan.

Contoh 1:

stringstream ss("11");
double my_number;
ss >> my_number; //my number = 11

contoh2:

stringstream ss("011");
double my_number;
ss >> my_number; //my number = 11

example3:

stringstream ss("11ABCD");
double my_number;
ss >> my_number; //my number = 11 (even though there are letters after the 11)

penjelasan variabel "sampah":

mengapa tidak mengecek apakah ekstraksi ke dalam double saya memiliki nilai yang valid dan kemudian mengembalikan true jika benar?

perhatikan example3 di atas masih akan berhasil membaca angka 11 ke dalam variabel my_number bahkan jika string input adalah "11ABCD" (yang bukan angka).

untuk menangani kasus ini kita dapat melakukan ekstraksi lain ke dalam variabel string (yang saya namakan sampah) yang dapat membaca apa pun yang mungkin telah tersisa di buffer string setelah ekstraksi awal ke dalam variabel tipe ganda. Jika ada sesuatu yang tersisa itu akan dibaca menjadi "sampah" yang berarti string penuh yang dilewati bukanlah angka (itu hanya dimulai dengan satu). dalam hal ini kami ingin mengembalikan false;

penjelasan "0" yang disebutkan sebelumnya:

mencoba mengekstraksi karakter tunggal menjadi ganda akan gagal (mengembalikan 0 ke dalam ganda kami) tetapi masih akan memindahkan posisi buffer string ke setelah karakter. Dalam hal ini pembacaan sampah kami akan kosong yang akan menyebabkan fungsi salah mengembalikan benar. untuk menyiasatinya, saya menambahkan 0 ke string sehingga jika misalnya string yang dilewatkan adalah "a" maka akan diubah menjadi "0a" sehingga 0 akan diekstraksi menjadi dobel dan "a" diekstraksi menjadi sampah.

mengawali a 0 tidak akan memengaruhi nilai angka sehingga angka tersebut masih akan diekstraksi dengan benar ke dalam variabel ganda kami.

KorreyD
sumber
1
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
Ajean
1

untuk memeriksa apakah string adalah bilangan bulat atau floating point atau lebih Anda bisa menggunakan:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}
Muhammad Khalifa
sumber
1
ini akan mengembalikan 10 untuk string yang berisi nilai "10_is_not_a_number".
KorreyD
1

Namun jawaban lain, yang menggunakan stold(meskipun Anda juga bisa menggunakan stof/ stodjika Anda tidak memerlukan presisi).

bool isNumeric(const std::string& string)
{
    std::size_t pos;
    long double value = 0.0;

    try
    {
        value = std::stold(string, &pos);
    }
    catch(std::invalid_argument&)
    {
        return false;
    }
    catch(std::out_of_range&)
    {
        return false;
    }

    return pos == string.size() && !std::isnan(value);
}
Tim Angus
sumber
1

Coba ini:

bool checkDigit(string str)
{  
   int n=str.length();

   for(int i=0;    i   < n ;   i++)
   {
     if(str[i]<'0' || str[i]>'9')
       return false;
   }

   return true;
}
rrlinus
sumber
1

Anda dapat menguji apakah string dapat dikonversi ke integer dengan menggunakan boost :: lexical_cast . Jika melempar pengecualian bad_lexical_cast maka string tidak dapat dikonversi, jika tidak maka bisa.

Lihat contoh program pengujian seperti di bawah ini:

#include <boost/lexical_cast.hpp>
#include <iostream>

int main(int, char** argv)
{
        try
        {
                int x = boost::lexical_cast<int>(argv[1]);
                std::cout << x << " YES\n";
        }
        catch (boost::bad_lexical_cast const &)
        {
                std:: cout << "NO\n";
        }
        return 0;
}

Eksekusi sampel:

# ./a.out 12
12 YES
# ./a.out 12/3
NO
Łukasz Ślusarczyk
sumber
0

Beberapa bulan yang lalu, saya menerapkan cara untuk menentukan apakah ada string bilangan bulat, heksadesimal atau ganda.

enum{
        STRING_IS_INVALID_NUMBER=0,
        STRING_IS_HEXA,
        STRING_IS_INT,
        STRING_IS_DOUBLE
};

bool isDigit(char c){
    return (('0' <= c) && (c<='9'));
}

bool isHexaDigit(char c){
    return ((('0' <= c) && (c<='9')) || ((tolower(c)<='a')&&(tolower(c)<='f')));
}


char *ADVANCE_DIGITS(char *aux_p){

    while(CString::isDigit(*aux_p)) aux_p++;
    return aux_p;
}

char *ADVANCE_HEXADIGITS(char *aux_p){

    while(CString::isHexaDigit(*aux_p)) aux_p++;
    return aux_p;
}


int isNumber(const string & test_str_number){
    bool isHexa=false;
    char *str = (char *)test_str_number.c_str();

    switch(*str){
    case '-': str++; // is negative number ...
               break;
    case '0': 
              if(tolower(*str+1)=='x')  {
                  isHexa = true;
                  str+=2;
              }
              break;
    default:
            break;
    };

    char *start_str = str; // saves start position...
    if(isHexa) { // candidate to hexa ...
        str = ADVANCE_HEXADIGITS(str);
        if(str == start_str)
            return STRING_IS_INVALID_NUMBER;

        if(*str == ' ' || *str == 0) 
            return STRING_IS_HEXA;

    }else{ // test if integer or float
        str = ADVANCE_DIGITS(str);
        if(*str=='.') { // is candidate to double
            str++;
            str = ADVANCE_DIGITS(str);
            if(*str == ' ' || *str == 0)
                return STRING_IS_DOUBLE;

            return STRING_IS_INVALID_NUMBER;
        }

        if(*str == ' ' || *str == 0)
            return STRING_IS_INT;

    }

    return STRING_IS_INVALID_NUMBER;


}

Kemudian dalam program Anda, Anda dapat dengan mudah mengkonversi angka dalam fungsi tipenya jika Anda melakukan hal berikut,

string val; // the string to check if number...

switch(isNumber(val)){
   case STRING_IS_HEXA: 
   // use strtol(val.c_str(), NULL, 16); to convert it into conventional hexadecimal
   break;
   case STRING_IS_INT: 
   // use (int)strtol(val.c_str(), NULL, 10); to convert it into conventional integer
   break;
   case STRING_IS_DOUBLE:
   // use atof(val.c_str()); to convert it into conventional float/double
   break;
}

Anda dapat menyadari bahwa fungsi tersebut akan mengembalikan 0 jika nomor tersebut tidak terdeteksi. Angka 0 dapat dianggap false (seperti boolean).

Jordi Espada
sumber
0

Saya mengusulkan konvensi sederhana:

Jika konversi ke ASCII adalah> 0 atau dimulai dengan 0 maka itu adalah angka. Itu tidak sempurna tetapi cepat.

Sesuatu seperti ini:

string token0;

if (atoi(token0.c_str())>0 || isdigit(token0.c_str()[0]) ) { //this is a value
    // do what you need to do...
}
Gokhan Unel
sumber
0

Fungsi ini menangani semua kemungkinan kasus:

bool AppUtilities::checkStringIsNumber(std::string s){
    //Eliminate obvious irritants that could spoil the party
    //Handle special cases here, e.g. return true for "+", "-", "" if they are acceptable as numbers to you
    if (s == "" || s == "." || s == "+" || s == "-" || s == "+." || s == "-.") return false;

    //Remove leading / trailing spaces **IF** they are acceptable to you
    while (s.size() > 0 && s[0] == ' ') s = s.substr(1, s.size() - 1);
    while (s.size() > 0 && s[s.size() - 1] == ' ') s = s.substr(0, s.size() - 1);


    //Remove any leading + or - sign
    if (s[0] == '+' || s[0] == '-')
        s = s.substr(1, s.size() - 1);

    //Remove decimal points
    long prevLength = s.size();

    size_t start_pos = 0;
    while((start_pos = s.find(".", start_pos)) != std::string::npos) 
        s.replace(start_pos, 1, "");

    //If the string had more than 2 decimal points, return false.
    if (prevLength > s.size() + 1) return false;

    //Check that you are left with numbers only!!
    //Courtesy selected answer by Charles Salvia above
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();

    //Tada....
}
Vaibhav Gupta
sumber
0

Bisakah Anda menggunakan kode pengembalian sscanf untuk menentukan apakah itu int?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}
David D
sumber