Çift baskı için doğru format belirleyici


482

doublePrintf için doğru format belirleyici nedir ? Öyle mi %f, değil %lfmi? İnanıyorum %fama emin değilim.

Kod örneği

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}

19
Bir C89 kitaplığı ile sıkışıp kalırsanız "%lf"tanımsızdır; C99 ve C11 kütüphanelerinde olduğu gibi tanımlanır "%f".
pmg

1
Varyantınız hiç olmadığı kadar doğru. %lfiçin doğru biçim belirleyicisidir double. Ama C99'da böyle oldu. Ondan önce kullanmak zorundaydı %f.
AnT

Yanıtlar:


626

"%f"bir çift için (veya en az bir) doğru biçimdir. Orada olan bir hiçbir biçim floatbir pas girişiminde çünkü eğer, floatiçin printf, bu terfi olacak doubleönce printfonu alır 1 . "%lf"geçerli standart kapsamında da kabul edilebilir - dönüşüm dönüştürücüsü (diğerleri arasında) lizliyorsa, bunun hiçbir etkisi olmadığı fbelirtilir.

Bu, bir yer olduğunu unutmayın printfbiçim dizeleri ölçüde farklılık scanf(ve fscanf, vs.) biçim dizeleri. Çıkışı, bir geçiyoruz değer terfi edilecek floatiçin doublevariadic parametre olarak geçirilen zaman. Girişi için bir geçiyoruz işaretçi size anlatmak zorunda teşvik edilmemektedir, scanfbir okumak isteyip floatya da doubleöylesine için, scanf, %fbir okumak istediğiniz aracı floatve %lfbir okumak istediğiniz anlamına gelir doublebunun ne için, (ve değer, a long double, %Lfya printfda için kullanın scanf).


1. C99, §6.5.2.2 / 6: "Aranan işlevi gösteren ifadede bir prototip içermeyen bir tür varsa, her bağımsız değişkende tamsayı yükseltmeleri gerçekleştirilir ve float türünde olan bağımsız değişkenler ikiye yükseltilir. Bunlara varsayılan bağımsız değişken promosyonları denir. " C ++ 'da ifadeler biraz farklıdır (örneğin, "prototip" kelimesini kullanmaz), ancak etki aynıdır: tüm varyasyon parametreleri, işlev tarafından alınmadan önce varsayılan promosyonlara tabi tutulur.


8
g++%lf-Wall -Werror -pedanticerror: ISO C++ does not support the ‘%lf’ gnu_printf format
Şununla

2
@kynan: Öyleyse (en azından g ++ 'nın geçerli bir sürümünü varsayarak), bu g ++' da bir hata. C89 / 90 ve C ++ 98/03 için izin vermek lbir uzantıydı. C99 / 11 ve C ++ 11 standartları uygulamanın izin vermesini gerektirir.
Jerry Coffin

1
İlginçtir ki, scanf yapar Talep doubles ile temsil %lf: o beklenen yakınıyor float *ve bulunan double *sadece birlikte %f.
Eric Dand

1
@JerryCoffin g ++ hala varsayılan olarak g ++ 98 moduna geçer
MM

5
@EricDand en Çünkü scanfböylece, okur neyi saklamak için nereye işaretçileri alır ihtiyaçları ise uzay olmanın ne kadar büyük bilmek de sivri-, printfdeğerlerini kendileri ve "varsayılan argüman promosyonları" alır hem bulurlar demek doublebu yüzden, s lolduğu aslında isteğe bağlıdır.
TripeHound

63

C99 standardı ( N1256 taslağı) göz önüne alındığında, kurallar işlev türüne bağlıdır: fprintf (printf, sprintf, ...) veya scanf.

Çıkarılan ilgili parçalar:

Önsöz

Bu ikinci baskı, ISO / IEC 9899 / COR1: 1994, ISO / IEC 9899 / AMD1: 1995 ve ISO / IEC 9899 / COR2: 1996 tarafından değiştirilen ve düzeltilen ilk baskı olan ISO / IEC 9899: 1990'ı iptal eder ve değiştirir. Önceki baskıdaki önemli değişiklikler şunları içerir:

  • %lf dönüşüm belirticisine izin verildi printf

7.19.6.1 fprintfİşlev

7 Uzunluk değiştiriciler ve anlamları:

l (ell) (...) öğesinin a, A, e, E, f, F, g veya G dönüşüm belirteci üzerinde bir etkisi olmadığını belirtir.

L Aşağıdaki a, A, e, E, f, F, g veya G dönüşüm belirticisinin uzun bir çift bağımsız değişken için geçerli olduğunu belirtir.

İçin belirtilen aynı kurallar fprintfbaşvurusunda printf, sprintfve benzeri fonksiyonlar.

7.19.6.2 fscanfİşlev

11 Uzunluk değiştiriciler ve anlamları:

l (ell) Aşağıdaki a, A, e, E, f, F, g veya G dönüşüm belirticisinin, iki katı tip işaretçisine sahip bir bağımsız değişken için geçerli olduğunu belirtir;

L Aşağıdaki a, A, e, E, f, F, g veya G dönüşüm belirticisinin, uzun ve çift işaretçiye sahip bir bağımsız değişken için geçerli olduğunu belirtir.

12 Dönüştürme belirteçleri ve anlamları: a, e, f, g İsteğe bağlı olarak imzalı bir kayan nokta sayısı ile eşleşir, (...)

14 A, E, F, G ve X dönüşüm belirteçleri de geçerlidir ve sırasıyla a, e, f, g ve x ile aynı şekilde davranır.

fprintfAşağıdaki belirteçler ve karşılık gelen türler için uzun öykü kısa belirtilmiştir:

  • %f -> çift
  • %Lf -> uzun çift.

ve fscanfbunun için:

  • %f -> şamandıra
  • %lf -> çift
  • %Lf -> uzun çift.

25

Olabilir %f, %gya %esen numara biçimlendirilmiş olmak istiyorum nasıl bağlı. Daha fazla ayrıntı için buraya bakın. lDeğiştirici gereklidir scanfile doubledeğil de printf.


1
-1: l(küçük harf) değiştiricisi tamsayı türleri içindir ( cplusplus.com/reference/clibrary/cstdio/printf ) ve Lkayan nokta türleri içindir. Ayrıca, Ldeğiştirici long doublebir düz değil, bir bekler double.
user470379

10
user470379: Cevabımla çelişki nerede? Bunun için lgerekli olmadığını söylemedim . printfdouble
vitaut

16

Biçim , tam olarak kullandığınız gibi %lfmükemmel bir printfbiçimdir double. Kodunuzda yanlış bir şey yok.

Biçim %lfiçinde printfbiçimi belirteçleri arasında yüzeysel "tutarsızlık" oluşturdu C dilinde, eski (pre-C99) sürümlerinde desteklenmeyen edildi doubleiçinde printfve scanf. Bu yüzeysel tutarsızlık C99'da giderildi.

Kullanılacak gerekli değildir %lfile doublede printf. İsterseniz de kullanabilirsiniz %f( %lfve %feşdeğerse printf). Fakat modern C'deki gibi kullanmayı tercih etmek çok mantıklı %folan float, %lfbirlikte doubleve %Lfbirlikte long doublesürekli olarak hem de, printfve scanf.


İle scanf(), "%f", "%lf"bir maç float *, double *değil, float, doublegeçen çizgi ile ima etti.
chux - Monica'yı geri döndü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.