لماذا الأمراض المنقولة جنسيا :: ينتهي المقارنة قضية سلسلة فشل؟
سؤال
وقضيت حوالي 4 ساعات أمس في محاولة لإصلاح هذه المشكلة في قانون بلدي. I تبسيط المشكلة إلى المثال التالي.
والفكرة هي لتخزين سلسلة في stringstream تنتهي مع الأمراض المنقولة جنسيا :: الغايات، ثم استرجاعها في وقت لاحق وذلك لمقارنة السلسلة الأصلية.
#include <sstream> #include <iostream> #include <string> int main( int argc, char** argv ) { const std::string HELLO( "hello" ); std::stringstream testStream; testStream << HELLO << std::ends; std::string hi = testStream.str(); if( HELLO == hi ) { std::cout << HELLO << "==" << hi << std::endl; } return 0; }
وربما يمكنك تخمين، رمز أعلاه عندما أعدم لن تتم طباعة أي شيء.
وعلى الرغم من، إذا طباعتها، أو نظرت في المصحح (VS2005)، مرحبا ومرحبا تبدو متطابقة، مدة العرض الخاصة بهم () في الواقع يختلف بمقدار 1. وهذا ما أنا على التخمين يسبب "==" المشغل ل فشل.
وسؤالي هو لماذا. أنا لا أفهم لماذا STD :: ينتهي يضاف الطابع غير مرئية إلى سلسلة مرحبا، مما يجعل أطوال مرحبا ومرحبا مختلفة على الرغم من أنها تحتوي على محتوى مماثل. وعلاوة على ذلك، هذه الشخصية غير مرئية لا يحصل قلص مع دفعة تقليم. ومع ذلك، إذا كنت تستخدم strcmp مقارنة .c_str () من السلسلتين، المقارنة يعمل بشكل صحيح.
والسبب كنت الأمراض المنقولة جنسيا :: ينتهي في المقام الأول لأنني كنت قد القضايا في الماضي مع stringstream الاحتفاظ البيانات القمامة في نهاية الدفق. حلت الأمراض المنقولة جنسيا :: ينتهي ذلك بالنسبة لي.
المحلول
وstd::ends
إدراج حرف فارغة في مجرى. سوف تحصل على محتوى المقرر بناء على std::string
الاحتفاظ بتلك حرف خالية وإنشاء سلسلة مع أن حرف خالية في المواقف منها.
وهكذا في الواقع الأمراض المنقولة جنسيا :: سلسلة يمكن أن تحتوي على أحرف فارغة المضمنة. محتويات الأمراض المنقولة جنسيا :: السلسلة التالية <م> هي م> مختلفة:
ABC
ABC\0
وصفر ثنائي ليست بيضاء. لكنه أيضا ليس طباعة، لذلك سوف لا نرى ذلك (إلا إذا تعرض المحطة الطرفية خصيصا).
ومقارنة باستخدام strcmp
وتفسير محتوى std::string
كسلسلة C عند تمرير .c_str()
. فإنه سيقول
وهم، الأحرف قبل \0
أولا (إنهاء حرف خالية) هي <م> ABC م>، لذلك أنا أعتبر السلسلة <م> ABC م>
وهكذا، فإنه لن ترى أي فرق بين الاثنين أعلاه. وربما كنت وجود هذه المشكلة:
std::stringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "b"); // will fail!
وستفشل ASSERT، لأن تسلسل يستخدم stringstream لا يزال القديم الذي يحتوي على "مرحبا". ما فعلتموه هو مجرد الكتابة فوق الحرف الأول. كنت أريد أن أفعل هذا:
std::stringstream s;
s << "hello";
s.str(""); // reset the sequence
s << "b";
assert(s.str() == "b"); // will succeed!
واقرأ أيضا هذه الإجابة: كيفية إعادة استخدام ostringstream
نصائح أخرى
وstd::ends
هو مجرد حرف فارغة. تقليديا، يتم إنهاء السلاسل في C و C ++ مع فارغة (أسكي 0) حرف، ولكن اتضح أن std::string
لا تتطلب حقا هذا الشيء. على أي حال إلى الخطوة من خلال نقطة التعليمات البرمجية بفارق نقطة ونرى عدد قليل من الأشياء المثيرة للاهتمام مستمرة:
int main( int argc, char** argv )
{
وو"hello"
الحرفي سلسلة غير التقليدية الصفر سلسلة إنهاء ثابت. نحن نسخ ذلك كله في std::string
مرحبا.
const std::string HELLO( "hello" );
std::stringstream testStream;
ونحن الآن وضع string
مرحبا (بما في ذلك زائدة 0) في stream
، تليها فارغة الثاني الذي وضعها عن طريق الدعوة إلى std::ends
.
testStream << HELLO << std::ends;
ونحن استخراج من نسخة من الاشياء وضعنا في stream
(سلسلة حرفية "مرحبا"، بالإضافة إلى اثنين من الإنهاء فارغة).
std::string hi = testStream.str();
ونحن ثم قارن بين السلسلتين باستخدام operator ==
على الطبقة std::string
. هذا المشغل (ربما) يقارن طول الكائنات string
- بما في ذلك اي وقت مضى كيف العديد زائدة أحرف فارغة. لاحظ أن الطبقة std::string
لا يتطلب صفيف حرف الأساسية لانهاء مع فارغة زائدة - بعبارة أخرى فإنه يسمح سلسلة لاحتواء أحرف فارغة حتى أول اثنين زائدة أحرف فارغة تعامل كجزء من hi
سلسلة
ومنذ السلسلتين مختلفة في عدد من القيم الخالية زائدة، يفشل المقارنة.
if( HELLO == hi )
{
std::cout << HELLO << "==" << hi << std::endl;
}
return 0;
}
<اقتباس فقرة>
وعلى الرغم من، إذا طباعتها، أو نظرت في المصحح (VS2005)، مرحبا ومرحبا تبدو متطابقة، مدة العرض الخاصة بهم () في الواقع يختلف بمقدار 1. وهذا ما أنا التخمين يسبب "==" المشغل أن تفشل.
اقتباس فقرة>والسبب في ذلك، وطول مختلفة من جانب واحد وراء شخصية فارغة.
<اقتباس فقرة>وسؤالي هو لماذا. انا لست نفهم لماذا الأمراض المنقولة جنسيا :: الغايات هي وأضاف الطابع غير مرئية للسلسلة مرحبا، مما مرحبا ومرحبا مختلفة أطوال على الرغم من أنها لديها محتوى مماثل. وعلاوة على ذلك، وهذا الطابع غير مرئية لا تحصل قلص مع دفعة تقليم. ومع ذلك، إذا استخدام strcmp مقارنة .c_str () ل السلسلتين، ويعمل مقارنة بشكل صحيح.
اقتباس فقرة> وstrcmp
يختلف عن std::string
- هو مكتوب من مرة في الأيام الأولى عندما أنهيت السلاسل مع فارغة - حتى عندما يحصل على أول لاغية زائدة في hi
فإنه يتوقف أبحث
والسبب كنت الأمراض المنقولة جنسيا :: ينتهي في المقام الأول هو أنه كانت لي قضايا في الماضي مع stringstream الإبقاء على البيانات القمامة في نهاية الدفق. حلت الأمراض المنقولة جنسيا :: الغايات التي ل لي.
اقتباس فقرة>في بعض الأحيان انها فكرة جيدة لفهم التمثيل الأساسي.
وأنت تقوم بإضافة حرف NULL إلى مرحبا مع الأمراض المنقولة جنسيا :: الغايات. عند تهيئة مرحبا مع شارع () التي تقوم بإزالة حرف NULL. سلاسل مختلفة. strcmp لا تقارن الأمراض المنقولة جنسيا :: سلاسل، فإنه يقارن شار * (انها وظيفة C).
والأمراض المنقولة جنسيا :: ينتهي يضيف فاصل فارغ (شار) '\ 0'. وكنت استخدامه مع الطبقات strstream إهمال، لإضافة فاصل فارغة.
وأنت لا تحتاج إليها مع stringstream، وفي واقع الأمر مسامير الامور، لأن فاصل باطل ليس "فاصل لاغيا خاص أن تنتهي سلسلة" لstringstream، لstringstream انها مجرد حرف آخر، والطابع الصفري . stringstream فقط يضيفه، والذي يزيد من عدد الأحرف (في قضيتك) إلى سبعة، ويجعل المقارنة مع "مرحبا" تفشل.
وأعتقد أن يكون وسيلة جيدة لمقارنة سلاسل هو استخدام طريقة std::find
. لا تخلط أساليب C وstd::string ones
!