Bir karakter basamağını C'deki karşılık gelen tam sayıya dönüştür


103

C'de bir karakteri tam sayıya dönüştürmenin bir yolu var mı?

Örneğin, '5'5'ten 5'e?

Yanıtlar:


150

Diğer yanıtlara göre, bu sorun değil:

char c = '5';
int x = c - '0';

Ayrıca, hata kontrolü için önce isdigit (c) 'nin doğru olup olmadığını kontrol etmek isteyebilirsiniz. Harfler için aynısını tamamen taşınabilir bir şekilde yapamayacağınızı unutmayın, örneğin:

char c = 'b';
int x = c - 'a'; // x is now not necessarily 1

Standart, '0' ile '9' arasındaki rakamlar için karakter değerlerinin bitişik olduğunu garanti eder, ancak alfabenin harfleri gibi diğer karakterler için hiçbir garanti vermez.


3
@Paul Tomblin: Evet, rakamlar için değil, çünkü cevapta söylediğim gibi, standart "0" dan "9" a bitişiktir ancak "a" dan "z" ye gibi diğer karakterler için bu tür garantiler sağlamaz.
Chris Young

karakter c = 'b'; int x = c - 'a'; o zaman x yalnızca ASCII'de 1 olur?
Pan

@Pan ASCII dahil, 'b' 1 'a' dan fazla olan herhangi bir kodlamada. Bu hala ancak yapar, EBCDIC içinde geçerlidir ( 'j' - 'i') == 8.
Chris Young

@ChrisYoung Neden? EBCDIC'de "j", "i" den 1 fazla değil mi?
Pan

2
Atoi'nin kullanılmadığı yerlerde neyi özlüyorum?
Daniel

41

Şu şekilde '0' çıkarın:

int i = c - '0';

Standart C aralığındaki her basamaklı garanti '0'..'9'(bölümünde önceki basamak birden büyük olan 5.2.1/3bir C99 taslak ). Aynı şey C ++ için de geçerlidir.


1
Bu yanıt, bir karakterin / zaten / etkili bir şekilde bir tamsayı olduğundan, her durumda uygulama tanımlı işaretten (yani, imzalı veya işaretsiz olabilir) ve CHAR_BITS uzunluğunda olduğundan bahsetmişseniz daha iyi olacaktır.
Arafangion

Bunun ona gerçekten yardımcı olacağından emin değildim. ama Chris bir .. z'nin zorunlu olarak bitişik olmamasıyla iyi bir noktaya değindi. onun yerine bundan bahsetmeliydim. şimdi yarışı kazandı :)
Johannes Schaub - litb

1
Seninki daha iyi, çünkü cevabını nitelendirdin - Chris pekala kendi işini uydurabilirdi. :)
Arafangion

Övgün için teşekkürler. C'nin durumundan emin olmadığımı kabul ediyorum, bu yüzden yukarı baktım ve 'zaten oradaydım çünkü referansı cevaba yapıştırdım :)
Johannes Schaub - litb

Ve bu, efendim, bu yüzden benden birkaç puanınız var. :)
Arafangion

29

Çılgın bir tesadüf eseri, bir karakter dizisini tam sayıya dönüştürmek istiyorsanız , bunu da yapabilirsiniz!

char *num = "1024";
int val = atoi(num); // atoi = ASCII TO Int

valşimdi 1024. Görünüşe göre atoi()iyi ve bu konuda daha önce söylediklerim sadece benim için geçerli (OS X'te (belki (Lisp şakasını buraya ekleyin))). Bunun strtol()yerine, dönüşümü yapmak için daha genel amaçlı bir işlev kullanan , sonraki örnekle kabaca eşleşen bir makro olduğunu duydum :

char *num = "1024";
int val = (int)strtol(num, (char **)NULL, 10); // strtol = STRing TO Long

strtol() şu şekilde çalışır:

long strtol(const char *str, char **endptr, int base);

A'ya dönüşür *strve longona bir taban sayımış gibi basedavranır. **endptrBoş değilse , bulunan ilk rakam olmayan karakteri tutar strtol()(ama bunu kimin umursadığı).


Atoi ile ilgili herhangi bir iş parçacığı sorunu yoktur (statik verisi yoktur) ve kullanımdan kaldırılmamıştır. Aslında işlevsel olarak şuna eşdeğerdir: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran

5
Atoi ile ilgili sorun, 0'ı "burada bir sayı bulamıyor" değeri olarak kullanmasıdır, bu nedenle atoi ("0") ve atoi ("bir") her ikisi de 0 döndürür. Bu sizin için işe yaramazsa kullanmak için strtol () veya sscanf () arayın.
David Thornley

Strtol'ün diğer bir avantajı da, sayıdan sonra gelen aynı dizeden başka şeyler de okumanız gerekmesidir.
dfeuer

@EvanTeran Maalesef Visual Studio'yu çalıştırırsanız bir amortisman uyarısı alırsınız (ve devre dışı bırakılmadan derleme yapamazsınız). VS şimdi tavsiye ediyor itoa_s().
Simon

7

Char '0' veya int 48'i şu şekilde çıkarın:

char c = '5';
int i = c - '0';

Açıklama: Dahili olarak ASCII değeri ile çalışır . ASCII tablosundan, karakter 5'in ondalık değeri 53 ve 0, 48'dir . Yani 53 - 48 = 5

VEYA

char c = '5';
int i = c - 48; // Because decimal value of char '0' is 48

Bu , herhangi bir sayı karakterinden 48 çıkarırsanız , tamsayıyı otomatik olarak dönüştürdüğü anlamına gelir .


6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');

numeralChar - '0'zaten bir tür olduğundan int, oyuncu kadrosuna ihtiyacınız yok. Olmasa bile, oyuncu kadrosuna gerek yok.
Alok Singhal

Huh, evet bu zorlayıcı olur, değil mi? Belki Java algılarımı renklendirdi. Ya da belki tamamen yanılıyorum ve Java'da bile zorlanabilir. :)
Kevin Conner

6

Karakter basamağını karşılık gelen tam sayıya dönüştürmek için. Aşağıda gösterildiği gibi yapın:

char c = '8';                    
int i = c - '0';

Yukarıdaki hesaplamanın arkasındaki mantık, ASCII değerleri ile oynamaktır. Karakter 8'in ASCII değeri 56, karakter 0'ın ASCII değeri 48'dir. 8 tamsayısının ASCII değeri 8'dir.

İki karakter çıkarırsak, ASCII karakterleri arasında çıkarma gerçekleşecektir.

int i = 56 - 48;   
i = 8;

Neden buna olumlu oy veren tek kişi benim? Açıklama çok basit ve bilgilendirici: +1:
Brandon Benefield

0

ASCII'de yalnızca tek bir karakter 0-9 ise, ASCII sıfır karakterinin değerini ASCII değerinden çıkarmak iyi sonuç verecektir.

Daha büyük sayıları dönüştürmek istiyorsanız, aşağıdakiler yapılacaktır:

char *string = "24";

int value;

int assigned = sscanf(string, "%d", &value);

** durumu kontrol etmeyi unutmayın (yukarıdaki durumda işe yaradıysa 1 olmalıdır).

Paul.


0
char chVal = '5';
char chIndex;

if ((chVal >= '0') && (chVal <= '9')) {

    chIndex = chVal - '0';
}
else 
if ((chVal >= 'a') && (chVal <= 'z')) {

    chIndex = chVal - 'a';
}
else 
if ((chVal >= 'A') && (chVal <= 'Z')) {

    chIndex = chVal - 'A';
}
else {
    chIndex = -1; // Error value !!!
}

0

Böyle bir şey yapmam gerektiğinde, istediğim değerlerle bir dizi hazırlarım.

const static int lookup[256] = { -1, ..., 0,1,2,3,4,5,6,7,8,9, .... };

O zaman dönüşüm kolaydır

int digit_to_int( unsigned char c ) { return lookup[ static_cast<int>(c) ]; }

Bu temelde ctype kitaplığının birçok uygulaması tarafından benimsenen yaklaşımdır. Bunu onaltılık rakamlarla da çalışmak için önemsiz bir şekilde uyarlayabilirsiniz.


Bu, tek bir ondalık (veya sekizlik) basamağı dönüştürmek için son derece verimsiz görünüyor. Arama tablonuzun ilgili kısmı L1 önbelleğinde olmazsa, yalnızca bir değer elde etmek için onu çekmek için bir sürü döngü patlatırsınız. Açıkçası, eğer bir yığın rakamı dönüştürüyorsanız bunun iyi bir fikir olduğundan şüphe etme eğilimindeyim, ancak bunu ölçmeniz gerekir. Elbette, Hex için çok daha rekabetçi.
dfeuer

0

Şuna göz at,

char s='A';

int i = (s<='9')?(s-'0'):(s<='F')?((s-'A')+10):((s-'a')+10);

sadece 0,1,2, ...., E, F için.


0

Sadece şu atol()işlevi kullanın :

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    const char *c = "5";
    int d = atol(c);
    printf("%d\n", d);

}

0

Senin basamaklı ise, diyelim ki, '5'ASCII, ikili sayı olarak temsil edilir 0011 0101(53). Her rakam en yüksek dört bite sahiptir 0011ve en düşük 4 bit, bcd'deki rakamı temsil eder. Yani sadece yapıyorsun

char cdig = '5';
int dig = cdig & 0xf; // dig contains the number 5

en düşük 4 biti veya aynı olan rakamı elde etmek için. Asm'de (diğer cevaplarda olduğu gibi) andyerine işlemi kullanır sub.


'5'is 53 ( 00110101)
eyllanesc

@eyllanesc İlk başta 4'tü. Teşekkürler. Düzenledi.
Garmekain

0

Burada, karakterdeki rakamı int'e ve bunun tersi yönde dönüştürmeye izin veren yardımcı işlevler:

int toInt(char c) {
    return c - '0';
}

char toChar(int i) {
    return i + '0';
}

-2

işlev kullanın: diziden tamsayıya atoi, diziden float türüne atof; veya

char c = '5';
int b = c - 48;
printf("%d", b);

Bunu zaten birkaç cevap ele almıştı. Bu, daha önce kapsamadıkları hiçbir şeyi eklemiyor.
ShadowRanger

-3

Bunu bir int'e çevirirsiniz (veya float veya double veya onunla ne yapmak isterseniz) ve onu anoter değişkeninde saklarsınız.

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.