C ++ هل يمكن أن يحمل Char من النوع الأصلي لشخصية الملف؟
سؤال
العنوان هو جميل التفسير الذاتي.
char c = std::cin.peek(); // sets c equal to character in stream
لقد أدركت فقط أن سحر نوع الأصلي لا يمكن أن يحمل eof.
شكرا، NMR.
المحلول
إجابة قصيرة: لا. استخدام إتجاه بدلا من شار.
إجابة أطول قليلا: لا. إذا كنت تستطيع الحصول على حرف أو القيمة إف من وظيفة، مثل ج غرس و c ++ نظرة خاطفة, بوضوح طبيعي شار المتغير لن يكون كافيا لعقد كل شخصيات صالحة و القيمة إف.
حتى الإجابة لفترة أطول: ذلك يعتمد، لكنها لن تعمل أبدا لأنك قد تأمل.
يحتوي C و C ++ على ثلاثة أنواع أحرف (باستثناء أنواع "واسعة"): شار, شار وقع و غير موقعة. وبعد سهل شار يمكن توقيعها أو غير موقعة، وهذا يختلف بين التحويل البرمجيات.
القيمة إف هو عدد صحيح سلبي، عادة -1، لذلك من الواضح أنه لا يمكنك تخزينه في غير موقعة أو في سهل شار هذا غير مميز. على افتراض أن نظامك يستخدم أحرفا 8 بت (التي تفعل كل شيء تقريبا)، إف سيتم تحويلها إلى (عشري) 255، ولن يعمل البرنامج الخاص بك.
ولكن إذا كان لديك شار يتم توقيع الكتابة، أو إذا كنت تستخدم شار وقع اكتب، ثم نعم، يمكنك تخزين -1 في ذلك، لذلك نعم، يمكن أن تعقد إف. وبعد ولكن ماذا يحدث بعد ذلك عندما تقرأ شخصية برمز 255 من الملف؟ سيتم تفسيره على أنه -1، وهذا هو، إف (على افتراض أن تنفيذك يستخدم -1). لذلك سيتوقف الرمز الخاص بك عن القراءة ليس فقط في نهاية الملف، ولكن أيضا بمجرد أن تجد حرفا 255.
نصائح أخرى
لاحظ أن قيمة الإرجاع لل std::cin.peek()
هو في الواقع من النوع std::basic_ios<char>::int_type
, ، وهذا هو نفسه std::char_traits<char>::int_type
, ، وهو int
وليس أ char
.
أكثر أهمية من ذلك، تعاد القيمة في ذلك int
ليس بالضرورة وضعا بسيطا من char
ل int
ولكن هو نتيجة للاتصال std::char_traits<char>::to_int_type
على الحرف التالي في الدفق أو std::char_traits<char>::eof()
(الذي يعرف أن يكون EOF
) إذا لم يكن هناك شخصية.
عادة، يتم تنفيذ هذا كل شيء بنفس الطريقة تماما fgetc
يلقي الشخصية إلى unsigned char
ثم إلى int
لقيمة العودة حتى تتمكن من التمييز بين جميع قيم الأحرف الصالحة EOF
.
إذا قمت بتخزين قيمة الإرجاع std::cin.peek()
في char
ثم هناك إمكانية قراءة شخصية بقيمة إيجابية (قل ÿ في ملف مشفر ISO-8859-1) مقارنة EOF
.
الشيء المحدد الذي يجب القيام به سيكون.
typedef std::istream::traits_type traits_type;
traits_type::int_type ch;
traits_type::char_type c;
while (!traits_type::eq_int_type((ch = std::cin.peek()), traits_type::eof()))
{
c = traits_type::to_char_type(ch);
// ...
}
ربما سيكون هذا أكثر استخداما:
int ch;
char c;
while ((ch = std::cin.peek()) != EOF)
{
c = std::iostream::traits_type::to_char_type(ch);
// ...
}
لاحظ أنه من المهم تحويل قيمة الأحرف بشكل صحيح. إذا قمت بإجراء مقارنة مثل هذا: if (ch == '\xff') ...
أين ch
هو int
على النحو الوارد أعلاه، قد لا تحصل على النتائج الصحيحة. تحتاج إلى استخدام std::char_traits<char>::to_char_type
على ch
أو std::char_traits<char>::to_int_type
على الطابع الثابت للحصول على نتيجة ثابتة. (عادة ما تكون آمنة مع أعضاء مجموعة الأحرف الأساسية، على الرغم من ذلك.)