لماذا الأمراض المنقولة جنسيا :: ينتهي المقارنة قضية سلسلة فشل؟

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

  •  03-07-2019
  •  | 
  •  

سؤال

وقضيت حوالي 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!

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