والتي C I/O مكتبة ينبغي أن تستخدم في C++ الكود ؟ [مغلقة]

StackOverflow https://stackoverflow.com/questions/119098

  •  02-07-2019
  •  | 
  •  

سؤال

في C++ code, أنا أميل إلى استخدام C++ مكتبة iostream بدلا من C مكتبة stdio.

لقد لاحظت بعض المبرمجين يبدو التمسك stdio ، مصرا على أنه أكثر المحمولة.

هذا هو الحال فعلا ؟ ما هو أفضل للاستخدام ؟

هل كانت مفيدة؟

المحلول

للإجابة على السؤال الأصلي:
أي شيء يمكن القيام به باستخدام stdio يمكن أن يتم ذلك باستخدام مكتبة iostream.

Disadvantages of iostreams: verbose
Advantages    of iostreams: easy to extend for new non POD types.

خطوة إلى الأمام C++ جعلت أكثر C كان نوع الأمان.

  • iostreams صمم ليكون صراحة نوع آمنة.وبالتالي الإحالة إلى كائن صراحة التحقق من نوع (at مترجم الوقت) الكائن الذي يتم تعيينه أيضا (توليد وقت التحويل البرمجي خطأ إذا لزم الأمر).وبالتالي منع الذاكرة وقت التشغيل على تشغيل أو كتابة عدد عشري قيمة شار كائن وما إلى ذلك.

  • scanf()/printf() والأسرة من ناحية أخرى تعتمد على المبرمج على شكل سلسلة الصحيح ولم يكن هناك أي نوع التدقيق (أعتقد أن دول مجلس التعاون الخليجي امتداد يساعد).ونتيجة لذلك كان مصدر العديد من الأخطاء (كما المبرمجين أقل الكمال في التحليل من المجمعين [لن أقول المجمعين هي مثالية فقط أفضل من البشر]).

فقط لتوضيح تعليقات من كولن جنسن.

  • على iostream المكتبات كانت مستقرة منذ إصدار آخر القياسية (أنسى السنة الفعلية ولكن منذ حوالي 10 سنوات).

لتوضيح تصريحات مايكل جانسون.

  • لغات أخرى يذكر أن استخدام نمط تنسيق صريحة ضمانات لمنع الآثار الجانبية الخطيرة C stdio المكتبة التي يمكن (في C ولكن ليس ذكر اللغات) يسبب تشغيل وقت الحادث.

N. B. أوافق على أن مكتبة iostream قليلا مطول الجانب.ولكن أنا على استعداد لطرح مع verboseness لضمان التشغيل السلامة.ولكن يمكننا التخفيف من الإسهاب باستخدام تعزيز تنسيق المكتبة.

#include <iostream>
#include <iomanip>
#include <boost/format.hpp>

struct X
{  // this structure reverse engineered from
   // example provided by 'Mikael Jansson' in order to make this a running example

    char*       name;
    double      mean;
    int         sample_count;
};
int main()
{
    X   stats[] = {{"Plop",5.6,2}};

    // nonsense output, just to exemplify

    // stdio version
    fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
            stats, stats->name, stats->mean, stats->sample_count);

    // iostream
    std::cerr << "at " << (void*)stats << "/" << stats->name
              << ": mean value " << std::fixed << std::setprecision(3) << stats->mean
              << " of " << std::setw(4) << std::setfill(' ') << stats->sample_count
              << " samples\n";

    // iostream with boost::format
    std::cerr << boost::format("at %p/%s: mean value %.3f of %4d samples\n")
                % stats % stats->name % stats->mean % stats->sample_count;
}

نصائح أخرى

انها مجرد مطول جدا.

يتأمل iostream بناء على ما يلي: (وبالمثل بالنسبة scanf):

// nonsense output, just to examplify
fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
    stats, stats->name, stats->mean, stats->sample_count);

من شأنه أن يتطلب شيئا مثل:

std::cerr << "at " << static_cast<void*>(stats) << "/" << stats->name
          << ": mean value " << std::precision(3) << stats->mean
          << " of " << std::width(4) << std::fill(' ') << stats->sample_count
          << " samples " << std::endl;

سلسلة التنسيق هو كائن-أورينتيدنيس يمكن أن تكون تجنبت الخوض لصالح التنسيق DSL جزءا لا يتجزأ في السلاسل.النظر في اللثغة هي format, بايثون printf-تنسيق نمط أو PHP, باش, Perl, Ruby و سلسلة intrapolation.

iostream على أن استخدام القضية هي مضللة في أحسن الأحوال.

على تعزيز تنسيق المكتبة يوفر نوع-آمنة وجوه المنحى البديل printf على غرار سلسلة التنسيق و هو مكمل iostreams التي لا تعاني من المعتاد الإسهاب القضايا بسبب استخدام ذكي من المشغل%.أوصي معتبرا انه على استخدام عادي ج printf إذا كنت لا يروق التنسيق مع iostream مشغل<<.

مرة أخرى في الأيام القديمة السيئة ، C++ لجنة المعايير أبقى اللعب مع اللغة iostreams كان هدف متحرك.إذا كنت تستخدم iostreams كنت تعطى فرصة إعادة كتابة أجزاء من التعليمات البرمجية الخاصة بك في كل عام أو نحو ذلك.بسبب هذا, لا تستخدم دائما stdio التي لم تتغير بشكل كبير منذ عام 1989.

إذا كنت تفعل الأشياء اليوم, وأود أن استخدام iostreams.

أنا تعلمت ج قبل تعلم C++ ، stdio المكتبات يبدو أكثر طبيعية للاستخدام.هناك إيجابيات وسلبيات على iostream مقابلstdio ولكن افتقد printf() عند استخدام iostream.

مبدئيا أود أن استخدام iostreams ، في الممارسة العملية لا تفعل الكثير تنسيق عشرية ، إلخ التي تجعل iostreams أيضا غير قابل للقراءة ، لذلك يمكنني استخدام stdio.دفعة::تنسيق تحسن ولكن ليس تماما تحفيز بما فيه الكفاية بالنسبة لي.في الممارسة العملية ، stdio تقريبا typesafe منذ أكثر الحديث المجمعين لا حجة التحقق على أي حال.

انها منطقة حيث أنا لا تزال غير سعيدة تماما مع أي من الحلول.

الثنائية IO, أنا أميل إلى استخدام stdio هو fread و fwrite.من أجل تنسيق الاشياء أنا عادة استخدام IO تيار على الرغم من ميكائيل قال غير نيفل (غير الافتراضي؟) التنسيق يمكن أن يكون بيتا.

سوف تكون المقارنة بين اثنين مكتبات الرئيسية من C++ مكتبة القياسية.

لا يجب استخدام ج-الأسلوب-الشكل-سلسلة-على أساس سلسلة المعالجة الروتينية في C++.

عدة أسباب وجود mit استخدامها:

  • لا typesafe
  • لا يمكن أن تمر من غير جراب أنواع variadic حجة القوائم (أي لا scanf+co. ، ولا printf+co.) ، أو يمكنك إدخال الظلام معقل من غير معرفة السلوك
  • من السهل الحصول على خطأ:
    • يجب أن يتمكن من الحفاظ على شكل سلسلة و "القيمة الحجة قائمة" في المزامنة
    • يجب أن نضع في المزامنة صحيح

خفية البق قدم في الأماكن النائية

ليس فقط printf في حد ذاتها ليست جيدة.البرنامج يحصل القديم و هو بتعميل الترميز و تعديل الأخطاء قد تكون عرض من الأماكن النائية.افترض أن لديك

.

// foo.h
...
float foo;
...

و في مكان ما ...

// bar/frob/42/icetea.cpp
...
scanf ("%f", &foo);
...

وبعد ثلاث سنوات تجد أن فو يجب أن يكون من النوع المخصص ...

// foo.h
...
FixedPoint foo;
...

ولكن في مكان ما ...

// bar/frob/42/icetea.cpp
...
scanf ("%f", &foo);
...

...ثم القديم الخاص بك printf/scanf لا يزال ترجمة, إلا أنه يمكنك الآن الحصول على عشوائية segfaults و لا تتذكر لماذا.

الإسهاب iostreams

إذا كنت تعتقد printf() هو أقل مطول ، ثم هناك احتمال أن كنت لا تستخدم iostream هو القوة الكاملة.على سبيل المثال:

  printf ("My Matrix: %f %f %f %f\n"
          "           %f %f %f %f\n"
          "           %f %f %f %f\n"
          "           %f %f %f %f\n",
          mat(0,0), mat(0,1), mat(0,2), mat(0,3), 
          mat(1,0), mat(1,1), mat(1,2), mat(1,3), 
          mat(2,0), mat(2,1), mat(2,2), mat(2,3), 
          mat(3,0), mat(3,1), mat(3,2), mat(3,3));

قارن ذلك إلى استخدام iostreams الحق:

cout << mat << '\n';

لديك لتحديد الصحيح الزائد على المشغل<< التي لديها ما يقرب من هيكل printf الاشياء, ولكن الفرق الكبير هو أن لديك الآن شيء يمكن إعادة استخدامها و typesafe;بالطبع يمكنك أيضا جعل شيئا إعادة استخدامها printf-يحب, ولكن ثم لديك printf مرة أخرى (ماذا لو كنت محل مصفوفة أعضاء الجديد FixedPoint?), وبصرف النظر عن غيرها من غير التفاهات مثليجب تمرير ملف* مقابض حولها.

ج-نمط تنسيق السلاسل ليست أفضل I18N من iostreams

لاحظ أن شكل سلاسل وغالبا ما يعتقد كونه الإنقاذ مع التدويل ، ولكنها ليست على الإطلاق أفضل من iostream في هذا الصدد:

printf ("Guten Morgen, Sie sind %f Meter groß und haben %d Kinder", 
        someFloat, someInt);

printf ("Good morning, you have %d children and your height is %f meters",
        someFloat, someInt); // Note: Position changed.

// ^^ not the best example, but different languages have generally different
//    order of "variables"

I. e., النمط القديم ج شكل سلاسل عدم الموضعية المعلومات بقدر iostreams القيام به.

قد ترغب في النظر في دفعة::تنسيق, الذي يقدم الدعم مشيرا الموقف في شكل سلسلة صراحة.من أمثلة القسم:

cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style.

بعض printf-تطبيقات توفر الموضعية الحجج ، لكنها غير القياسية.

يجب أن أبدا استخدام ج-نمط تنسيق السلاسل ؟

وبصرف النظر عن الأداء (كما أشار يناير Hudec), أنا لا أرى سببا.ولكن نأخذ في الاعتبار:

"نحن يجب أن ننسى صغيرة الكفاءة تقل عن 97% من الوقت:من السابق لأوانه الأمثل هو أصل كل الشرور.إلا أننا يجب أن لا نفوت الفرص المتاحة لنا في هذه المرحلة الحرجة 3%.مبرمج جيد لا أن نركن إلى الرضا من قبل مثل هذا المنطق سيكون من الحكمة أن ننظر بعناية في المدونة ؛ ولكن فقط بعد أن تم تحديد" - كانوث

و

"اختناقات تحدث في أماكن مثيرة للدهشة ، لذلك لا تحاول تخمين الثانية وضعت في سرعة الإختراق حتى أثبتت حيث ان عنق الزجاجة هو." - بايك

نعم printf-تطبيقات عادة ما تكون أسرع من iostreams عادة ما تكون أسرع من دفعة::شكل (صغيرة و محددة المعيار كتبت ، ولكن يجب أن تعتمد إلى حد كبير على الوضع على وجه الخصوص:إذا printf=100% ، ثم iostream=160%, وزيادة::تنسيق=220%)

ولكن لا عمياء حذف التفكير فيه:كم من الوقت هل حقا تنفق على النص-معالجة ؟ كم من الوقت الخاص بك تشغيل البرنامج قبل الخروج ؟ هو ذات الصلة إلى العودة إلى ج-نمط شكل سلاسل فضفاضة نوع السلامة نقصان refactorbility, زيادة احتمال دقيق جدا الأخطاء التي قد تخفي نفسها لسنوات و قد تكشف عن نفسها الحق إلى المفضلة لديك العملاء الوجه ؟

أنا شخصيا لن تقع مرة أخرى إذا كنت لا يمكن الحصول على أكثر من 20% تسريع.ولكن لأن التطبيقات تنفق تقريبا كل الوقت على المهام الأخرى من سلسلة المعالجة ، لم.بعض موزعي كتبت تنفق تقريبا كل وقتهم في سلسلة المعالجة ، ولكن مجموع وقت صغير جدا أنه لا يستحق الاختبار والتحقق من الجهد.

بعض الألغاز

وأخيرا ، أود مسبقا بعض الألغاز:

إيجاد جميع الأخطاء ، لأن المترجم لن (أنه يمكن أن تشير فقط إذا كان لطيفة):

shared_ptr<float> f(new float);
fscanf (stdout, "%u %s %f", f)

إذا أي شيء آخر, ما الخطأ في هذا ؟

const char *output = "in total, the thing is 50%"
                     "feature  complete";
printf (output);

في حين أن هناك الكثير من الفوائد C++ iostreams API واحد مشكلة كبيرة قد حول i18n.المشكلة هي أن ترتيب المعلمة بدائل يمكن أن تختلف على أساس الثقافة.المثال الكلاسيكي هو شيء من هذا القبيل:

// i18n UNSAFE 
std::cout << "Dear " << name.given << ' ' << name.family << std::endl;

في حين أن يعمل الإنجليزية, الصينية اسم العائلة تأتي أولا.

عندما يتعلق الأمر إلى ترجمة التعليمات البرمجية الخاصة بك على الأسواق الخارجية ، ترجمة قصاصات هو محفوف بالمخاطر لذلك الجديدة l10ns قد تتطلب تغييرات في التعليمات البرمجية وليس فقط سلاسل مختلفة.

دفعة::تنسيق ويبدو أن الجمع بين أفضل من stdio (شكل واحد السلسلة التي يمكن استخدام المعلمات في ترتيب مختلف ثم تظهر) و iostreams (نوع-السلامة التمدد).

يمكنني استخدام iostreams ، أساسا لأن ذلك يجعل من الأسهل كمان مع تيار في وقت لاحق (إذا احتاج الأمر).على سبيل المثال ، يمكنك معرفة أنك ترغب في عرض الإخراج في إطار تتبع -- هذا من السهل نسبيا القيام به مع cout و cerr.يمكنك, بالطبع, كمان مع أنابيب الاشياء على unix, ولكن هذا ليس المحمولة.

أنا لا أحب printf مثل التنسيق ، لذا عادة شكل سلسلة أولا ومن ثم ترسل إلى المخزن المؤقت.مع Qt, أنا غالبا ما تستخدم QString::sprintf (على الرغم من أنها نوصي باستخدام QString::arg بدلا من ذلك).لقد بحثت في دفعة.شكل فضلا, ولكن حقا لا يمكن أن تعتاد على جملة (الكثير من %'s).يجب أن تعطي حقا نظرة ، على الرغم من.

ما يغيب عن iolibraries هو تنسيق المدخلات.

iostreams لا يكون وسيلة لطيفة تكرار scanf() وحتى دفعة لا تمديد الإدخال.

stdio أفضل قراءة الملفات الثنائية (مثل freading كتل في ناقلات<unsigned char=""> واستخدام .تغيير حجم ().... الخ).ترى read_rest وظيفة في الملف.سمو في http://nuwen.net/libnuwen.html على سبيل المثال.

C++ تيارات يمكن خنق على الكثير من وحدات البايت عند قراءة الملفات الثنائية مما تسبب كاذبة eof.

منذ iostreams أصبحت معيارا يجب استخدامها مع العلم أن الكود الخاص بك سوف تعمل بالتأكيد مع الإصدارات الأحدث من برنامج التحويل البرمجي.أعتقد في الوقت الحاضر أكثر من المجمعين تعرف جيدا عن iostreams و يجب أن لا يكون هناك أي مشكلة في استخدام لهم.

ولكن إذا كنت تريد أن العصا مع *printf وظائف يمكن أن يكون هناك أي مشكلة في رأيي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top