محدد التنسيق الصحيح للمضاعفة في printf
-
27-09-2019 - |
سؤال
ما هو التحديد التنسيق الصحيح ل double
في printf؟ فعلا %f
أو هو %lf
؟ أعتقد أنه %f
, ، لكنني لست متأكدًا.
عينة الكود
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
المحلول
"%f"
هو التنسيق الصحيح (أو واحد على الأقل) لمضاعفة. هناك هو لا يوجد تنسيق ل float
, ، لأنه إذا حاولت تمرير أ float
إلى printf
, ، سيتم ترقيته إلى double
قبل printf
يستقبلها1. "%lf"
مقبول أيضًا بموجب المعيار الحالي - l
تم تحديده على أنه ليس له أي تأثير إذا تليها f
محدد التحويل (من بين أمور أخرى).
لاحظ أن هذا مكان واحد printf
سلاسل التنسيق تختلف اختلافا كبيرا scanf
(و fscanf
, ، وما إلى ذلك) تنسيق السلاسل. للإخراج ، أنت تمر القيمة, ، والتي سيتم ترقيتها من float
إلى double
عند تمريرها كمعلمة متنوعة. للدخول أنت تمر أ مؤشر, ، الذي لم يتم الترويج له ، لذلك عليك أن تخبر scanf
سواء كنت تريد قراءة أ float
أو أ double
, ، وذلك ل scanf
, %f
يعني أنك تريد قراءة أ float
و %lf
يعني أنك تريد قراءة أ double
(ولما يستحق الأمر ، long double
, ، انت تستخدم %Lf
احد الامرين printf
أو scanf
).
1. C99 ، الفقرة 6.5.2.2/6: "إذا كان التعبير الذي يشير إلى الوظيفة المدعوة له نوع لا يتضمن نموذجًا أوليًا ، يتم تنفيذ العروض الترويجية الصحيحة على كل وسيطة ، ويتم تعزيز الوسيطات التي تحتوي على تعويم النوع إلى مضاعفة. وتسمى هذه الترقيات الوسيطة الافتراضية. " في C ++ ، تختلف الصياغة إلى حد ما (على سبيل المثال ، لا تستخدم كلمة "النموذج الأولي") ولكن التأثير هو نفسه: جميع المعلمات المتنوعة تخضع للترقيات الافتراضية قبل استلامها بواسطة الوظيفة.
نصائح أخرى
Given the C99 standard (namely, the N1256 draft), the rules depend on the function kind: fprintf (printf, sprintf, ...) or scanf.
Here are relevant parts extracted:
Foreword
This second edition cancels and replaces the first edition, ISO/IEC 9899:1990, as amended and corrected by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995, and ISO/IEC 9899/COR2:1996. Major changes from the previous edition include:
%lf
conversion specifier allowed inprintf
7.19.6.1 The
fprintf
function7 The length modifiers and their meanings are:
l (ell) Specifies that (...) has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument.
The same rules specified for fprintf
apply for printf
, sprintf
and similar functions.
7.19.6.2 The
fscanf
function11 The length modifiers and their meanings are:
l (ell) Specifies that (...) that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to double;
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to long double.
12 The conversion specifiers and their meanings are: a,e,f,g Matches an optionally signed floating-point number, (...)
14 The conversion specifiers A, E, F, G, and X are also valid and behave the same as, respectively, a, e, f, g, and x.
The long story short, for fprintf
the following specifiers and corresponding types are specified:
%f
-> double%Lf
-> long double.
and for fscanf
it is:
%f
-> float%lf
-> double%Lf
-> long double.
يمكن أن يكون %f
, %g
أو %e
اعتمادًا على كيفية تنسيق الرقم. نرى هنا لمزيد من التفاصيل. ال l
مطلوب المعدل في scanf
مع double
, ، ولكن ليس في printf
.
الصحيح printf
تنسيق ل double
هو %lf
, ، بالضبط كما استخدمته. لا حرج في الكود الخاص بك.
شكل %lf
في printf
لم يكن مدعومًا في الإصدارات القديمة (قبل C99) من لغة C ، والتي أنشأت "عدم الاتساق" السطحية بين مواصفات التنسيق لصالح double
في printf
و scanf
. تم إصلاح هذا التناقض السطحي في C99.
لذلك في C Modern ، من المنطقي التفضيل لاستخدامه %f
مع float
, %lf
مع double
و %Lf
مع long double
باستمرار في كليهما printf
و scanf
.
%Lf
(لاحظ العاصمة L
) هل تنسيق محدد إلى عن على زوجي طويل.
من أجل سهل doubles
, ، أيضاً %e
, %E
, %f
, %g
أو %G
سوف تفعل.
لمضاعفة يمكنك ببساطة استخدام %lf
أو يمكنك استخدام أي من المتابعة حسب تفضيلاتك
%e
أو %E
للقيم في التنسيق الأسي
%g
أو %G
للحصول على تدوين طبيعي أو أسي ، أيهما أكثر ملاءمة لحجمها.
اقرأ المزيد في هنا قائمة بجميع محددات التنسيق في ج