Bir dizenin C ++ ile bir sayı olup olmadığı nasıl belirlenir?


136

Bir dizenin sayı olup olmadığını kontrol eden bir işlev yazmaya çalışırken oldukça sorun yaşadım. Yazdığım bir oyun için, okuduğum dosyadaki bir satırın bir sayı olup olmadığını kontrol etmem gerekiyor (bu şekilde bir parametre olup olmadığını öğreneceğim). Sorunsuz çalıştığına inandığım aşağıdaki işlevi yazdım (veya yanlışlıkla durdurmak için düzenledim veya şizofrenim veya Windows şizofrendir):

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

    return false;
}

184
Ben nefret görme if (expr) return true; return false;! Sadece yazın return expr;.
ephemient

17
@ephemient Benim tarzım seninle aynı şeyi yapmak. Ama gerçekten önemli mi?
Brennan Vincent

2
İşlev prototipiniz uygun görünmüyor. Bool isParam (const string & line) neden kullanılmıyor?
MikimotoH

4
Evet. Yeni bir dil öğrenirken uzun tarzı kodlama konusunda kötü bir alışkanlığım var. C ++ 'da yeniyim ve "kısayollar" (veya algılanan kısayollar) konusunda daha tereddütlüyüm.
Brendan Weinstein

57
@Brennan Vincent: Evet, çok önemli. Bu hatalar olarak aynı sınıf var if (expr) return expr; else return expr;, if (expr == true), (if expr != false), veya if ((expr == true) == true). Hepsi kodun yazarına, okuyucusuna veya derleyicisine fayda sağlamayan karmaşıklık sunar. Gereksiz karmaşıklığın ortadan kaldırılması bir kısayol değildir; daha iyi yazılım yazmanın anahtarıdır.
MSalters

Yanıtlar:


148

En etkili yol, rakam olmayan bir karakter bulana kadar dizeyi yinelemek olacaktır. Herhangi bir rakam olmayan karakter varsa, dizeyi bir sayı olarak kabul edebilirsiniz.

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();
}

Veya bunu C ++ 11 yolu ile yapmak istiyorsanız:

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();
}

Aşağıdaki yorumlarda belirtildiği gibi, bu yalnızca pozitif tamsayılar için işe yarar. Negatif tam sayıları veya kesirleri tespit etmeniz gerekiyorsa, daha sağlam bir kitaplık tabanlı çözüm kullanmalısınız. Bununla birlikte, negatif tam sayılar için destek eklemek oldukça önemsizdir.


6
Negatif sayıları ve tam olmayan sayıları da işlemez. Soruya bağlı olarak gereksinimlerin neler olduğunu bilemiyoruz.
Brennan Vincent

76
!s.empty() && s.find_first_not_of("0123456789") == std::string::npos;Bir C ++ 03 tek satırlık için de kullanabilirsiniz .
kbjorklu

8
Ayrıca ondalık sayıları da işlemez, örneğin: 1.23
littlecodefarmer758

3
@Remy Lebeau, evet öyle. Aslında dizeyi bir int. Bu sadece bir dizenin sayısal rakamlardan oluşup oluşmadığını belirler. İpin ne kadar uzun olduğu önemli değil.
Charles Salvia

5
C ++ 11 örneğini dahil etmeyi <string> <algorithm>ve <cctype>çalışmasını sağlamayı unutmayın .
kR105

88

Neden tekerleği yeniden icat etmelisiniz? C standart kitaplığı (C ++ ile de mevcuttur) tam olarak bunu yapan bir işleve sahiptir:

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

Kesirleri veya bilimsel gösterimi işlemek istiyorsanız, strtodbunun yerine ile devam edin (bir doublesonuç alırsınız ).

C / C ++ stilinde ( "0xABC") onaltılık ve sekizlik sabitlere izin vermek istiyorsanız , 0bunun yerine son parametreyi yapın .

İşleviniz şu şekilde yazılabilir:

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

4
Bu işlev öndeki beyaz alanı atar. Bu nedenle isdigit için ilk karakteri kontrol etmelisiniz.
chmike

1
@chmike: Soruyu anladığıma göre, öndeki boşlukları atmak doğru davranıştır ( atoisoruda kullanıldığı gibi bunu da yapar).
Ben Voigt

1
Soru bunu açıkça belirtmedi, ancak benim "bir dizenin sayı olup olmadığını kontrol eder" gerekliliğiyle ilgili anlayışım, tüm dizenin sayı olduğu, dolayısıyla boşluk olmadığı anlamına gelir. Cevabınızın bu konuda diğerlerinden farklı olduğunu belirtme ihtiyacı hissettim. Dizede sayının önünde boşluklar olması uygunsa cevabınız iyi olabilir.
chmike

1
Diyorsun ki @BenVoigt o payarlanacak nullptreğer strtolsağ sucessful mi? Benim gördüğüm bu değil :(
Jonathan Mee

2
@JonathanMee: Hayır, pdizeyi sonlandıran NUL'u gösterecek. Yani p != 0ve *p == 0.
Ben Voigt

33

C ++ 11 derleyicisiyle, negatif olmayan tamsayılar için şöyle bir şey kullanırdım ( ::bunun yerine not edin std::):

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

http://ideone.com/OjVJWh


1
Bu en iyi cevap.
Martin Broadhurst

Dizede utf8 karakterleri varsa, çalışma zamanı hatası alırsınız.
Lion King

29

Boost :: lexical_cast ile bunu C ++ yolu ile yapabilirsiniz. Takviye kullanmamakta gerçekten ısrar ediyorsanız, ne yaptığını inceleyebilir ve bunu yapabilirsiniz. Oldukça basit.

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

21
Kullanılması try{} catch{}iyi bir fikir? Bundan olabildiğince kaçınmamalı mıyız?
Nawaz


14
burada {} yakala {} denemek uygundur. Ancak, catch (...) sadece kötü bir uygulamadır. Bu durumda, istisna işleyiciniz için boost :: bad_lexical_cast kullanın.
NuSkooler

5
Bunun bir dosyadan okumaya çalıştığını hissediyorum. HAYIR Dosyayı ne kadar kontrol ederseniz edin, onu yapana kadar ondan okuyup okuyamayacağınızı bilemezsiniz. Ya işe yarayacak ya da çalışmayacak. Bu durumda, bir istisna yakalamanız gerekecek. Yani bu durumda bence bunu yapmanın tamamen iyi bir yolu.
Casey

4
@EarlGray - İşletim sistemine bağlı pencerelerin ne yapacağını duymakla kesinlikle ilgilenirim. Standart, bu kodun nasıl davranması gerektiği konusunda oldukça açıktır.
Edward Strange

16

Ben sadece yinelemeyi kullanan bu fikri ortaya atmak istedim, ancak başka bir kod bu yinelemeyi yapıyor:

#include <string.h>

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

Bir ondalık nokta veya eksi işareti kontrol ederken olması gerektiği gibi sağlam değildir, çünkü her bir konumda birden fazla olmasına izin verir. İşin iyi yanı, tek satırlık bir kod olması ve üçüncü taraf bir kitaplık gerektirmemesi.

Dışarı çıkart '.' ve '-' eğer tüm izin verilenler pozitif tam sayılarsa.


hata: 'strspn' bu kapsamda bildirilmedi Sanırım bunun nedeni bir "#include" eksikliğimden kaynaklanıyor ama ne var
Qwertie

4
Eğer kullanımına gidiyoruz std::string, onun kullanmak find_first_not_ofüyesi işlevini.
Ben Voigt 14

5
Açıkçası geçerli bir sayı olmayan "12.3-4.55-" dizesini geçirirseniz bu başarısız olur
Buzzrick

Buzzrick, önerilen cevap zaten bahsettiğin sayı ile başarısız olacağını belirtiyor.
David Rector

bunu yalnızca "0123456789" ile sınırlarsanız, formül, işaretsiz tamsayıyı test etmek için mükemmeldir
özel biri yoktur

16

Bir normal ifade yaklaşımı öneririm. Tam bir normal ifade eşleşmesi (örneğin, boost :: regex kullanarak )

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

dizenin sayı olup olmadığını gösterir. Bu, pozitif ve negatif sayıları, tamsayı ve ondalık sayıları içerir.

Diğer varyasyonlar:

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

(sadece olumlu)

-?[0-9]+

(yalnızca tam sayı)

[0-9]+

(yalnızca pozitif tam sayı)


Ahem, std::regexgcc 4.7, gcc 4.8 ile kullanmayı denedim - ikisi de masum bir "[abc]" için bile std::regex_errorherhangi bir [regexp işareti atıyorlar (bunu yanlış mı yapıyorum?). clang-3.4 hiç farkında değil <regex>. Her neyse, bu en mantıklı cevap gibi görünüyor, +1.
Dmytro Sirenko

3
@EarlGray: Regex yalnızca GCC 4.9'dan uygun şekilde edinilebilir
Orbit'teki Hafiflik Yarışları

13

İşte <regex>kitaplığı kullanarak yapmanın başka bir yolu :

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}

Ah, öyle olur. Daha iyi bir çözümle güncelledim. Teşekkürler.
mpataki14

"[(- | +) |] [0-9] +" (artı yıldız yerine) olmamalıdır, aksi takdirde normal ifadeniz "-" veya "+" ile geçerli bir sayı olarak eşleşebilir.
David Mulder

Güzel. Bu birinci karakter sınıfında (, | ve) 'nin ne yaptığından emin değilim - bu meta karakterler, bildiğim kadarıyla bir karakter sınıfı içinde özel anlamlarını kaybediyorlar. Peki ya "^ [- +]? [0-9] + $"?
U007D

Verimsiz olabilir. Bu her çağrıldığında, normal ifadeyi derleyen std :: regex yapıcısını çağırır.
user31264

12

Bu çözümle, negatiften pozitif sayılara ve hatta kayan sayılara kadar her şeyi kontrol edebilirsiniz. Tipini numtamsayı olarak değiştirdiğinizde, dizge bir nokta içeriyorsa bir hata alırsınız.

#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;
      }             
}

Kanıtlayın: C ++ Programı


10

Aşağıdaki kodu en sağlam buldum (c ++ 11). Hem tam sayıları hem de kayan sayıları yakalar.

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}

Görünüşe göre hat using namespace std;gereksiz.
Xam

5

İşte pozitif tam sayıları kontrol etmek için bir çözüm:

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

5

Bunu dene:

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

1
Bu sadece işaretsiz tamsayıları test eder
özel kimse yoktur.

4

Brendan bu

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

neredeyse tamam.

0 ile başlayan herhangi bir dizenin bir sayı olduğunu varsayarsak, bu durum için bir kontrol eklemeniz yeterli

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

ofc "123hello", Tony D'nin belirttiği gibi gerçek olacak.


3

C ++ 'da düşünebildiğim en basit şey

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;
}

Çalışma kodu örneği: https://ideone.com/nRX51Y


3

C ++ 11 regex ( #include <regex>) kullanan çözümüm , daha hassas kontroller için kullanılabilir unsigned int, doublevb.

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);
}

Bu kodu http://ideone.com/lyDtfi adresinde bulabilirsiniz , bu, gereksinimleri karşılayacak şekilde kolayca değiştirilebilir.


Olumsuz oy verenlerden sorunu anlamama yardımcı olmalarını isterim, cevabımı iyileştireceğim. Teşekkürler.
aniliitb10

2

Kbjorklu tarafından yapılan yoruma dayalı bir çözüm şudur:

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

Olduğu gibi David Rektör cevap birden noktalar veya eksi işaretleri ile dizeleri sağlam değil, ama sadece tamsayılar olup olmadığını kontrol etmek Eğer bu karakterleri kaldırabilir.


Bununla birlikte, Ben Voigt'in çözümüne dayanan, strtodondalık değerleri, bilimsel / mühendislik gösterimini, onaltılık gösterimi (C ++ 11) veya hatta INF / INFINITY / NAN'ı (C ++ 11) aramak için cstdlib'de kullanan bir çözüme kısmen düştüm dır-dir:

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

2

Bir stringstream sınıfı kullanabiliriz .

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

       stream<<str;
       stream>>number;

       return stream.eof();
    }

2

Kullanarak <regex>. Bu kod test edildi!

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

1

Belgelere biraz daha danıştıktan sonra, ihtiyaçlarımı destekleyen, ancak muhtemelen başkalarına yardımcı olmayacak bir cevap buldum. İşte burada (can sıkıcı doğru dönüş olmadan ve yanlış ifadeler döndürmeden :-))

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

4
Sayı olursa 0, yanlış negatif alırsınız.
Charles Salvia

3
Bu, baştaki herhangi bir sayıyı döndürecektir ve sizi izleyen anlamsız şeyler konusunda uyarmayacaktır (ör. "123hello" ==> 123). @Charles: Brendan, başka bir cevaba yapılan bir yorumda yalnızca olumlu duyguları tanıması gerektiğini söylüyor.
Tony Delroy

1

Bu normal ifadenin neredeyse tüm durumları ele alması gerektiğini düşünüyorum

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

böylece hem (Unicode hem de ANSI) ile çalışabilen aşağıdaki işlevi deneyebilirsiniz

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
}

1
include <string>

Çiftleri Doğrulamak İçin:

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;

}

İntleri Doğrulamak İçin (Negatiflerle)

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;

}

İşaretsiz Ints Doğrulamak İçin

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"

}


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(); 
}

nasıl çalışır: dizi akımı >> aşırı yüklemesi dizgeleri çeşitli aritmetik türlere dönüştürebilir, bunu karakter bitene kadar dizge akışından (bu durumda ss) karakterleri sırayla okuyarak yapar VEYA sonraki karakter depolanacak kriterleri karşılamaz hedef değişken türüne.

örnek 1:

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

example2:

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)

"çöp" değişken açıklaması ":

neden sadece çiftime ayıklamanın geçerli bir değere sahip olup olmadığını kontrol etmiyor ve varsa doğruya dönmüyor?

Yukarıdaki uyarı example3, girdi dizesi "11ABCD" (bu bir sayı değil) olsa bile, 11 sayısını my_number değişkenine başarılı bir şekilde okuyacaktır.

Bu durumu ele almak için, double türündeki değişkene ilk ayıklamadan sonra dize tamponunda kalan her şeyi okuyabilen bir dize değişkenine (ben çöp olarak adlandırdığım) başka bir çıkarma yapabiliriz. Geriye kalan herhangi bir şey varsa "çöp" olarak okunacaktır, bu da aktarılan tüm dizenin bir sayı olmadığı anlamına gelir (sadece bir ile başlar). bu durumda yanlış döndürmek isteriz;

başına eklenen "0" açıklaması ":

tek bir karakteri bir ikiliye çıkarmaya çalışmak başarısız olur (çiftimize 0 döndürür) ama yine de dizge tampon konumunu karakterin arkasına taşır. Bu durumda, çöp okumamız boş olacak ve bu da işlevin yanlış bir şekilde doğruya dönmesine neden olacaktır. bunun üstesinden gelmek için dizenin başına 0 ekledim, böylece örneğin iletilen dizi "a" ise "0a" olarak değiştirilir, böylece 0 ikiye çıkarılır ve "a" çöpe çıkarılır.

Bir 0'ın başına eklenmesi sayının değerini etkilemeyecektir, bu nedenle sayı yine de çift değişkenimize doğru bir şekilde çıkarılacaktır.


1
Bu kod soruyu yanıtlayabilirken, bu kodun soruyu neden ve / veya nasıl yanıtladığına ilişkin ek bağlam sağlamak, uzun vadeli değerini artırır.
Ajean

1

bir dizenin tam sayı mı yoksa kayan nokta mı olduğunu kontrol etmek için aşağıdakileri kullanabilirsiniz:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}

1
bu, "10_is_not_a_number" değerini içeren bir dize için 10 döndürür.
KorreyD

1

Yine başka bir cevap, kullanılan stold(yine de stof/ stodhassasiyete ihtiyacınız yoksa / kullanabilirsiniz ).

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);
}


1

Bunu dene:

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;
}

1

Boost :: lexical_cast kullanarak bir dizenin tam sayıya dönüştürülebilir olup olmadığını test edebilirsiniz . Bad_lexical_cast istisnası atarsa, dizge dönüştürülemez, aksi takdirde yapılabilir.

Aşağıdaki böyle bir test programı örneğine bakın:

#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;
}

Örnek yürütme:

# ./a.out 12
12 YES
# ./a.out 12/3
NO

0

Birkaç ay önce, herhangi bir dizenin tamsayı, onaltılık veya çift olup olmadığını belirlemenin bir yolunu uyguladım.

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;


}

Ardından, programınızda, aşağıdakileri yaparsanız, sayıyı fonksiyondaki türüne kolayca dönüştürebilirsiniz.

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;
}

Sayı algılanmazsa işlevin 0 döndüreceğini fark edebilirsiniz. 0, yanlış olarak kabul edilebilir (boolean gibi).


0

Basit bir sözleşme öneriyorum:

ASCII'ye dönüştürme> 0 ise veya 0 ile başlıyorsa, bu bir sayıdır. Mükemmel değil, hızlı.

Bunun gibi bir şey:

string token0;

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

0

Bu işlev tüm olası durumlarla ilgilenir:

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....
}

0

Bir int olup olmadığını belirlemek için sscanf'ın dönüş kodunu kullanabilir misiniz?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.