2012-03-17 17 views
18

Bir C dizesinin geçerli bir tamsayı olup olmadığını kontrol etmem gerekiyor. C dizesinin geçerli bir int olup olmadığını belirleyin C

Ben bu dizede geçersizliğini belirtmeden, basitçe 8 döndürülen çizgilerin her ikisi de dize "8 -9 10" gönderme hem

int num=atoi(str); 

ve

int res=sscanf(str, "%d", &num); 

Ama denedik.

Herkes alternatif önerebilir mi?

+0

'atoi' hata denetimi yapmıyor; str '' int' değerinin bir temsilini içermiyorsa davranışı tanımsızdır. (Tipik uygulamalar '0' döndürür.)' Sscanf' daha iyidir, ancak dizideki değer 'int' olarak gösterilemiyorsa davranışı tanımsızdır. Ayrıca, başlığınız geçerli bir int kontrol etmek istediğinizi belirtiyor, ancak sorunuzun bedeninde "geçerli tamsayı" yazıyor; onlar aynı şey değiller. int * birkaç * tam sayı * türünden biridir. –

cevap

29

strtol() 'a bir göz atın, işaretçiyi döndürerek dizenin geçersiz bölümlerini anlatabilir.

Ve coşkulu örnek kodlara dikkat edin .. kapsamlı hata işleme için man sayfasına bakın.

+0

strtol() işaretçiyi dizgedeki bir sonraki "nesneye" ayarlar. Hiçbir şey doğrulamaz. –

+1

@ g24l Bu işaretçi NULL işaretine işaret ederse, tüm dizenin geçerli olduğunu bilirsiniz. Değilse, değil. Tadaa! – blueshift

+0

Boş bir sonlandırılmış dize. –

8

Belki strtol veya benzeri libc işlevleri kullanarak, ancak bu sorun o kadar da zor değil hakkında akıl yürütme değil yakılmış olsun edeceğiz:

#include <stdbool.h> // if using C99... for C++ leave this out. 
#include <ctype.h> 

bool is_valid_int(const char *str) 
{ 
    // Handle negative numbers. 
    // 
    if (*str == '-') 
     ++str; 

    // Handle empty string or just "-". 
    // 
    if (!*str) 
     return false; 

    // Check for non-digit chars in the rest of the stirng. 
    // 
    while (*str) 
    { 
     if (!isdigit(*str)) 
     return false; 
     else 
     ++str; 
    } 

    return true; 
} 

[Not: Ben başka türlü yerine else arasında isdigit(*str++) yapmış olabileceğini daha kısa tutmak ama benim hatırlama standartları o isdigit makro olması mümkün söylemek olmasıdır.]

bir sınırlama dizesinde sayısı bir tamsayı uymaz ise bu return false olmamasıdır sanırım. Bu sizin için önemli olabilir veya olmayabilir.

+1

"o kadar zor değil", ama geri gelip değiştirmeliydin;) – blueshift

+1

@blueshift Point, ama bir web formuna kod yazarken 5 dakika içinde 1 düzenleme benim için o kadar da kötü değil. :-) – asveikau

+0

Bu durumda, kendi kendine yuvarlanmaya ya da strtol() doğru hata işlemeyi denemek için daha fazla hata eğilimli olup olmadığını bilmiyorum. Belki hala strtol öneririz. – blueshift

2

int okumak ve yapmak olacaktır sağlam Bunu yapmanın basit bir yolu emin dize temsili örnek atoi ve itoa birleştirmek için, giriş dizesi özdeş mi:

int is_int(char const* p) 
{ 
    return strcmp(itoa(atoi(p)), p) == 0; 
} 
+0

Güzel bir fikir :). Bununla birlikte, bu, çalışmasını sağlamak için ön ve arkadaki boşlukları kırpmayı gerektirir. – sara

+3

Bu çözümün ANSI uyumlu olmadığını unutmayın. –

0

dize içerip içermediğini kontrol için geçerli bir sayıyı düzenli bir ifade kullanabilirsiniz. tamsayılar için Örneğin kullanın:

[- +] [0-9] +

ve kayan nokta sayıları için genel bir durum:?

[+ -] [0-9] + [ .] [0-9] * ([eE] [+ -] [0-9] +?)? C++ 11 durumunda normal ifade işlevleri kütüphanede, örn. "std :: regex_match (.....)" tam eşleşmeyi verir. konuyu yukarı kazma

#include <regex> 
..... 
std::string strnumber("-1.234e+01"); 
float number; 
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?")) 
number=std::stof(strnumber); 
else 
std::cout<<"error, string is not a valid number"; 
0

Maalesef bu iş parçacığı bir google arama yaparak ilk maçı olması nedeniyle bütünlük uğruna ve ...

mümkündür: Kod aşağıdaki gibi görünmelidir gibi bir şey kullanmak: man sayfasına göre standart C gibi görünüyor

ret = sscanf(string, "%d%n", &number, &idx); 
if (ret == 0 || string[idx] != '\0') 
    /* handle the error */ 

%n direktifi, işlenmiş karakter sayısını sayar.

[Düzenle] sscanf, taşmaları algılamanın bir yolunu oluşturmuyor gibi görünmektedir, bu nedenle strtoX işlevleri ailesi tercih edilmelidir IMHO.

İlgili konular