Char'ı C ve C ++ 'da int'e dönüştür


400

Nasıl C ve C ++ 'da charbir dönüştürebilirim int?


1
@Matt: Daha somut olmak iyi bir fikir olurdu. bir genelleme sormak , göreviniz için geçerli olmayan ve hatta doğru olmayan genelleştirilmiş cevapları davet eder . Unutmayın, sormanız gerektiğinde, muhtemelen doğru bir şekilde genelleştirmek için yeterli bilginiz yoktur.
Şerefe ve s. - Alf

@Af P.P. Steinbach: Orijinal soru hangi dilde belirsizdi. Anahtar kelimeler cve c++bence her iki dilin karşı karşıya olduğu cevaplar makul.
Matt Joiner

8
Diğer teknik forumlardaki kapsamlı deneyimimden, sezgilerim OP'nin gerçekten "bir sayının (10'da) metin temsilini nasıl alıp karşılık gelen sayıya dönüştüreceğim" anlamına gelmesidir. Genel olarak, C ve C ++ neofitlerinin genellikle metnin bu dillerde nasıl çalıştığı ve gerçekten ne anlama geldiği konusunda inanılmaz derecede bulanık fikirleri vardır char.
Karl Knechtel

3
@KarlKnechtel: Eğer bu doğruysa (ASCII tüm aralığı kapsamasa da ASCII değerlerini karakterlerden çıkarmayı teşvik ettiği için 50/50 civarında veriyorum), OP'nin netliğe ihtiyacı var - ama bu bir dupe arasında stackoverflow.com/questions/439573/... .
Fred Nurk

3
OP'nin bu soruyu açıklığa kavuşturmak için üç saati vardı ve bunu başaramadı. Olduğu gibi, aslında ne sorulduğunu bilmenin bir yolu yoktur. Kapatmak için oy verdi.
sbi

Yanıtlar:


551

Ne yapmak istediğine bağlı:

değeri bir ascii kodu olarak okumak için,

char a = 'a';
int ia = (int)a; 
/* note that the int cast is not necessary -- int ia = a would suffice */

karakteri dönüştürmek '0' -> 0, '1' -> 1vb yazabilirsiniz

char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */

Açıklama :
a - '0'eşdeğerdir ((int)a) - ((int)'0'), yani karakterlerin ascii değerleri birbirinden çıkarılır. Yana 0hemen önce gelir 1(ve böylece kadar ASCII tablosunda 9), ikisi arasındaki fark karakteri bu sayısını verir atemsil eder.


14
ia = (a - '0')% 48;
Kshitij Banerjee

@KshitijBanerjee Bu iki nedenden dolayı iyi bir fikir değil: '0' öncesi ascii karakterler için negatif bir sayı verir (örneğin &-> -10 gibi ) ve 10'dan büyük sayılar verir (örneğin x-> 26)
SheetJS

2
int ia = a - '0' - ihtiyacınız olan şey bu
funk

5
@ kevin001 Karakteri int'e dönüştürmek istiyorsanız ve bir karakter olmayan '1'bir ascii numarası sağlarsa , 0-9 arasında saymak için yeniden hizalamak 1için ofseti kaldırmanız gerekir '0'. Ardışık 1-9 sayıları ascii tamsayı numarasına bitişiktir.
krisdestruction

Oyuncular gerekli değil / isteniyor
Craig Estey

97

ASCII kodunda sayılar (rakamlar) 48'den başlar . Tek yapmanız gereken:

int x = (int)character - 48;

19
@ chad: Sadece daha okunabilir değil, aynı zamanda daha taşınabilir. C ve C ++ bir ASCII temsilini garanti etmez, ancak kullanılan temsilin ne olursa olsun, 10 ondalık basamağın temsillerinin bitişik ve sayısal sırada olduğunu garanti ederler.
Ben Voigt

Değiştirecek tek şey 48, biraz "büyülü" gibi görünüyor açmak için'0'
ArielGro

59

C ve C ++ her zaman en azından türleri destekler int. Ayrıca karakter değişmezleri intC ve charC ++ 'dadır.

Bir chartürü yalnızca bir öğesine atayarak dönüştürebilirsiniz int.

char c = 'a'; // narrowing on C
int a = c;

3
Bu amaç için çok az takdir edilen tekliyi de kullanabilirsiniz operator+().
Cubbi

24
-1 Sorunun tek anlamlı yorumu için cevap yanlış. Bu (kod int a = c;), C standart kitaplık işlevlerinin ele alamadığı negatif değerleri tutacaktır. C standart kütüphane fonksiyonları, chardeğerleri işlemenin anlamı için standardı belirler int.
Şerefe ve s. - Alf

6
@Matt: Aşağı oyu saklıyorum. Mümkünse onu güçlendirirdim! Siz ve başkalarının varsaydığı soru yorumu anlamlı değildir, çünkü bu tamamen önemsizdir ve OP'nin belirli tür kombinasyonları için çok önemsiz olmayan çok önemli bir pratik sorun vardır. Verdiğiniz tavsiyeler acemi için doğrudan tehlikelidir . Büyük olasılıkla C standart kütüphane karakter sınıflandırma fonksiyonlarını kullanan programları için Tanımsız Davranış ile sonuçlanacaktır . Ref. @ Sayam'ın cevabına, o cevabı sildi.
Şerefe ve s. - Alf

3
-1 yanlış olduğu için: isupper (), 1252 highbit karakterden geçilirse tanımsız sonuçlara sahip olur.
Chris Becke

1
"Daima tanıtım yapmak" ile ne demek istiyorsun? Örtük dönüşümler, belirli parametre türleri (örn. Varargs işlevine geçen) sırasında ve bir operatörün işlenenlerini uyumlu türler yapması gerektiğinde değerler yükseltilir. Ama kesinlikle bir değerin tanıtılmadığı zamanlar vardır (eğer bir karakter bir karakter bekleyen bir işleve geçirilirse), aksi takdirde int'den daha küçük bir tipimiz olmazdı.
Adrian McCarthy

31

char sadece 1 baytlık bir tam sayıdır. Char tipinde sihir yok! Bir int'e kısa veya int'e uzun atayabileceğiniz gibi, int'e bir karakter atayabilirsiniz.

Evet, ilkel veri türünün adı "char" olur ve bu yalnızca karakter içermesi gerektiğini ima eder. Ama gerçekte, "char" sadece dili öğrenmeye çalışan herkesi karıştırmak için kötü bir isim seçimidir. Bunun için daha iyi bir isim int8_t'dir ve derleyiciniz en son C standardını takip ediyorsa bu adı kullanabilirsiniz.

Tabii ki bir olsa gerekir dize işleme yaparken, karakter türünü kullandıkları için 1 bayt klasik ASCII tablosu uyan dizini. Sen olabilir Hiç bunu neden istediğini gerçek dünyada pratik neden yoktur rağmen ancak sıra düzenli ints ile dize işleme yapmak. Örneğin, aşağıdaki kod mükemmel şekilde çalışacaktır:

  int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };

  for(i=0; i<6; i++)
  {
    printf("%c", str[i]);
  }

Karakterlerin ve dizelerin bilgisayardaki diğer her şey gibi sadece sayı olduğunu anlamalısınız. Kaynak kodunda 'a' yazdığınızda, 97 tamsayısı olan bir tamsayı sabiti olarak önceden işlenir.

Yani şöyle bir ifade yazarsanız

char ch = '5';
ch = ch - '0';

bu aslında

char ch = (int)53;
ch = ch - (int)48;

bu da C dili tamsayı tanıtımlarından geçiyor

ch = (int)ch - (int)48;

ve sonuç türüne uyması için bir karaktere kısaltıldı

ch = (char)( (int)ch - (int)48 );

Çizgiler arasında böyle bir çok ince şey var, char dolaylı olarak int olarak değerlendiriliyor.


Soru ile etiketlenmediğinden ascii, belirli bir kodlama varsaymamanız gerekir. charEşit olarak ayarlamak int8_tyanlıştır, çünkü eşit olabilir uint8_tya da olabilir uint24_t.
Roland Illig

1
@RolandIllig Hayır, a charher zaman 1 bayttır ve verilen sistemdeki türler int8_t/ uint8_tvarsa (çok olasıdır), a'nın sonucuna uyabileceklerdir char, çünkü o zaman 8 bit olacaktır. Çeşitli eski DSP'ler gibi oldukça egzotik sistemlerde char16 bit uint8_tolacak ve olmayacak. Tamamlanmış DSP'lerle uyumluluk için kod yazmak, tıpkı bir kişinin tamamlayıcısı veya işaret ve büyüklük sistemleri ile uyumluluk için yazmak gibi saçmadır. Bu tür sistemler gerçek dünyada zar zor var olduğundan, büyük zaman kaybı.
Lundin

18

(Bu yanıt, nesnelerin C ++ tarafına yöneliktir, ancak işaret uzantısı sorunu C'de de bulunmaktadır.)

Üç chartürün de ( signed, unsignedve char) kullanılması ilk göründüğünden daha hassastır. 0 ila SCHAR_MAX(8 bit için 127 olan char) değerler kolaydır:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;

Ancak, somevaluebu aralığın dışındayken, yalnızca bu üç türdeki unsigned char"aynı" chardeğerler için tutarlı sonuçlar verir :

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.

İşaret uzantısı nedeniyle veya gibi ctype.h işlevlerini kullanırken bu önemlidir :isuppertoupper

char c = negative_char;  // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n);  // Undefined behavior.

İnt üzerinden dönüşümün örtük olduğuna dikkat edin; bu aynı UB'ye sahiptir:

char c = negative_char;
bool b = isupper(c);

Bunu düzeltmek için ctype.h işlevlerini safe_ctype yoluyla unsigned charsararak kolayca yapılır :

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c);  // No UB.

std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.

Bu çalışır çünkü üç karakter türünden herhangi birini alan herhangi bir işlev diğer iki karakter türünü de alabilir. Herhangi bir türün üstesinden gelebilecek iki işleve yol açar:

int ord(char c) { return (unsigned char)c; }
char chr(int n) {
  assert(0 <= n);  // Or other error-/sanity-checking.
  assert(n <= UCHAR_MAX);
  return (unsigned char)n;
}

// Ord and chr are named to match similar functions in other languages
// and libraries.

ord(c)Bir negatif geçti bile - her zaman negatif olmayan bir değer verir charveya negatif signed char- ve chrherhangi bir değer alır ordüreten ve arka aynı verir char.

Uygulamada, muhtemelen unsigned charbunları kullanmak yerine dökülüyordum , ancak dökümünü kısa bir süre intsarıyorlar char, -to- için hata kontrolü eklemek için uygun bir yer sağlıyorlar ve bunları birkaç kez kullanmanız gerektiğinde daha kısa ve daha açık olacaklar yakın.



7

Bu bir tür dönüştürmek ne demek bağlıdır.

"123456" gibi bir tamsayıyı temsil eden bir dizi karakteriniz varsa, bunu C'de yapmanın iki tipik yolu vardır: atoi () veya strtol () veya genel amaçlı sscanf gibi özel amaçlı bir dönüşüm kullanın () . C ++ (gerçekten yükseltme olarak maskeleyen farklı bir dildir) üçüncü bir dize akışı ekler.

intDeğişkenlerinizden birindeki kesin bit deseninin a olarak ele alınmasını istiyorsanız char, bu daha kolaydır. C'de farklı tamsayı tipleri gerçekte ayrı olan "tiplerden" daha fazla zihinsel durumdur. Sadece chars'nin istendiği yerde kullanmaya başlayın ve iyi olmalısınız. Derleyicinin arada sırada sızlanmayı bırakmak için açık bir dönüşüme ihtiyacınız olabilir, ancak tek yapmanız gereken 256'dan fazla olan bitleri bırakmaktır.


6

nullC'de kesinlikle becerilerim var , ancak basit bir ayrıştırma için:

char* something = "123456";

int number = parseInt(something);

... bu benim için çalıştı:

int parseInt(char* chars)
{
    int sum = 0;
    int len = strlen(chars);
    for (int x = 0; x < len; x++)
    {
        int n = chars[len - (x + 1)] - '0';
        sum = sum + powInt(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}

Bu kod hızla tanımlanmamış davranışı başlatır ve bu nedenle kopyalama ve yapıştırma için uygun değildir. (int taşma)
Roland Illig

4

Muhtemelen bu dönüşümü C standart kitaplığındaki işlevleri kullanmak için istiyorsunuz.

Bu durumda, (C ++ sözdizimi) yapın

typedef unsigned char UChar;

char myCppFunc( char c )
{
    return char( someCFunc( UChar( c ) ) );
}

İfade UChar( c ), unsigned charEOF hariç, C işlevleri tarafından desteklenmeyen negatif değerlerden kurtulmak için dönüşür .

Daha sonra bu ifadenin sonucu intresmi bir argüman için gerçek argüman olarak kullanılır . Otomatik promosyonu nereden alacağınız int. Alternatif olarak bu son adımı açık bir şekilde yazabilirsiniz int( UChar( c ) ), ama şahsen bunu çok ayrıntılı buluyorum.

Şerefe & h.,


0

Ben "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"bir onaltılık değer olarak `` 7C '' ile temsil edilebilir gerçek tamsayı değerine gibi bir char dizi dönüştürme sorunları vardı . Bu yüzden, yardım için gezdikten sonra bunu yarattım ve paylaşmanın harika olacağını düşündüm.

Bu karakter dizesini doğru tamsayılarına ayırır ve benden daha fazla insana yardımcı olabilir;)

unsigned int* char2int(char *a, int len)
{
    int i,u;
    unsigned int *val = malloc(len*sizeof(unsigned long));

    for(i=0,u=0;i<len;i++){
        if(i%2==0){
            if(a[i] <= 57)
                val[u] = (a[i]-50)<<4;
            else
                val[u] = (a[i]-55)<<4;
        }
        else{
            if(a[i] <= 57)
                val[u] += (a[i]-50);
            else
                val[u] += (a[i]-55);
            u++;
        }
    }
    return val;
}

Umarım yardımcı olur!


Bu kodu hiç test ettiniz mi? 50 değeri 48 olmalıdır, 55 değeri yalnızca büyük ASCII harfleri için kullanılırken, örneğinizde küçük harfler bulunur.
Roland Illig

0

Char veya int'e kısa için, sadece değeri atamanız gerekir.

char ch = 16;
int in = ch;

İnt64 ile aynı.

long long lo = ch;

Tüm değerler 16 olacaktır.


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.