Menu

C'de Metinden Int'e: atoi, strtol ve Sayıları Metne Çevirmek

C'de metin ile sayı arasında dönüşüm: atoi neden hata bildiremez, strtol ve strtod'u endptr ve errno ile doğru kullanmak, snprintf ile sayıları metne çevirmek ve '0' ile tek basamak numaraları.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Metin kullanıcılardan, dosyalardan ve komut satırından karakter olarak gelir. "42" üç bayttır - '4', '2', '\0' - ve siz dönüştürene dek içindeki hiçbir şey 42 sayısı değildir. C iki kuşak dönüşüm fonksiyonu sunar: hata bildiremeyen kısa ve eski olanlar ve bildirebilen uzun olanlar. Bu sayfa ikisini de gösteriyor ve gerçek programların neden ikinci kümeyi kullandığını açıklıyor.

Eski Aile: atoi, atol, atof

Adları gibi okunurlar: ASCII'den int'e, long'a, double'a. Bir argüman, bir sonuç.

Baştaki boşluklar atlanır, isteğe bağlı bir işaret okunur, rakamlar tüketilir ve sonrasındaki her şey yok sayılır. Bu, girdi yanlış olana dek elverişlidir:

Üçü de 0 yazdırır. Dönüş kodu yok, bayrak yok, "bu işe yaradı mı?" diye sormanın yolu yok - ve int'i taşıran bir değer, bildirilen bir hata değil tanımsız davranıştır. Oyuncak bir programdaki sabit yazılmış bir değer için bu katlanılabilir. Bir insanın ya da dosyanın sağlayabileceği her şey için sessiz bir hata üreticisidir.

Doğru Araç: strtol

strtol (string to long), olan biteni bildirmek için iki kanalı olan aynı dönüşümdür.

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

endptr, fonksiyonun tüketmediği ilk karaktere ayarlanır. base sayı tabanıdır - 10 kullanın ya da sabitin kendi önekinin karar vermesi için 0 (on altılık için 0x, sekizlik için baştaki 0).

endptr'ı okumak, atoi'nin yanıtlayamadığı soruları yanıtlar:

  • end == input, hiçbir şey dönüştürülmedi demektir - metin bir sayıyla başlamadı.
  • *end != '\0', sonda içerik vardı demektir. Bunun bir hata olup olmadığı sizin kararınız: "42 elma" ayrıştırılırken sorunsuzdur, tüm satırın bir sayı olması gerekiyorken bir sorundur.

Taşma ayrıca errno üzerinden bildirilir. Tam, doğru deyim bir kez yazılıp yeniden kullanılmaya değer:

Üç ayrıntı bunu doğru kılar. Çağrıdan önceki errno = 0 önemlidir, çünkü kütüphane errno'yu yalnızca ayarlar; asla temizlemez, dolayısıyla daha önceki bir çağrıdan kalan bayat bir değer bu çağrının başarısızlığı diye okunurdu. strtol, int'ten geniş olabilen long döndürür, dolayısıyla INT_MIN/INT_MAX'a karşı aralık denetimi ERANGE'ten ayrıdır. Ve başarıyı bir durum olarak döndürüp değeri bir gösterici üzerinden vermek, C fonksiyonlarının "ya bir değer ya bir başarısızlık" bildirme yoludur - dönüş değeri her iki işi birden yapamaz.

strtoul işaretsiz karşılığıdır ve strtoll/strtoull, long long için çalışır.

Diğer Tabanlar

Taban 16 on altılık okur; taban 0 öneki inceler ve kendisi karar verir.

Taban 0, belirli bir durumda tuzaktır: "012" gibi sıfırla doldurulmuş ondalık bir sayı sekizlik okunur ve 10 çıkar. Girdiniz ondalıksa açıkça 10 deyin.

Kayan Nokta: strtod

strtod, double için aynı biçimdir ve atof'un atoi ile aynı kusuru vardır.

strtod ayrıca bilimsel gösterimi ("1.5e3"), on altılık float'ları ve "inf" ile "nan" kelimelerini kabul eder. Yerel ayar ondalık ayıracını etkiler; bu, başka yerde yazılmış dosyaları ayrıştıranları şaşırtır - varsayılan "C" yerel ayarında ayıraç her zaman noktadır.

Sayıdan Metne: snprintf

Diğer yöne giderken standart cevap snprintf'tir. En fazla verdiğiniz kadar yazar, her zaman sonlandırır ve tam sonucun ihtiyaç duyacağı uzunluğu döndürür.

Dönüş değeri kırpılma denetimidir. Tampon boyutuna eşit ya da ondan büyükse metin sığmamıştır:

Uzanılmaması gereken iki şey: itoa standart C'nin parçası değildir, dolayısıyla onu kullanan kod her yerde derlenmez; ve sprintf, boyut sınırı olmayan snprintf'tir ki bu, tamponunuzun sonunun ötesine şikâyet etmeden yazacağı anlamına gelir.

Tek Karakterler ve '0'

'0' ile '9' arasındaki rakam karakterlerinin ardışık olması garantidir, dolayısıyla düz çıkarma bir rakam karakteri ile değeri arasında dönüşüm yapar.

Yalnızca rakamlar böyle davranır - harflerin ardışık olması zorunlu değildir, dolayısıyla c - 'a' alfabe aritmetiği için taşınabilir değildir. Çıkarmaya güvenmeden önce onu isdigit ile koruyun:

unsigned char dönüşümü metinlerdeki ile aynı sebeple zorunludur: <ctype.h> fonksiyonları negatif argümanlar için tanımsızdır ve düz char işaretli olabilir.

Hangi Fonksiyonu Kullanmalı

  • Bir kullanıcıdan, bir dosyadan ya da argv'den gelen metin → tam denetimle strtol / strtod.
  • Kendi yazdığınız ve denetlediğiniz bir sabit → atoi kabul edilebilir, sıra dışı olmasa da.
  • Bir tampona sayı → snprintf ve dönüş değerini denetleyin.
  • Tek bir rakam karakteri → isdigit'ten sonra '0''ı çıkarın.
  • Asla → gets, sprintf, itoa.

Sıkça Sorulan Sorular

C'de bir metin int'e nasıl çevrilir?

Doğru cevap strtol(text, &end, 10)'dur: değeri döndürür, end'i tüketmediği ilk karaktere ayarlar ve taşmayı errno üzerinden bildirir. atoi(text) daha kısadır ama hem "0" hem "merhaba" için 0 döndürür ve ikisini ayırt etmenin yolu yoktur.

C'de atoi'nin nesi yanlış?

Başarısızlığı bildiremez. atoi("abc"), gerçek bir sıfırdan ayırt edilemeyen 0 döndürür ve taşma, bildirilen bir hata değil tanımsız davranıştır. Metin bir kullanıcıdan, bir dosyadan ya da bir komut satırı argümanından geldiğinde her zaman strtol kullanın.

C'de bir int'i metne nasıl çeviririm?

snprintf(buf, sizeof buf, "%d", n). Standarttır, tampon boyutuyla sınırlıdır ve tam sonucun ihtiyaç duyduğu karakter sayısını döndürür - dolayısıyla sizeof buf'a eşit ya da ondan büyük bir dönüş değeri metnin kırpıldığını söyler. itoa standart C değildir.

C'de '7' karakterini 7 sayısına nasıl çeviririm?

'0''ı çıkarın: int digit = c - '0';. Rakam karakterleri her C karakter kümesinde ardışıktır, dolayısıyla çıkarma 0 ile 9 arasını verir. Önce isdigit((unsigned char)c) ile koruyun, çünkü aritmetik başka her şey için anlamsızdır.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA