c++ - আমি কীভাবে সিটি+তে ইউটিএফ-8 এ স্ট্যান্ডিং:: স্ট্রিংটি সঠিকভাবে ব্যবহার করব?




string c++11 (3)

আমার প্ল্যাটফর্মটি একটি ম্যাক এবং সি ++ 11 (বা উপরে)। আমি একজন সি ++ শিক্ষানবিশ এবং একটি ব্যক্তিগত প্রকল্পে কাজ করছি যা চীনা এবং ইংরেজি প্রক্রিয়া করে। ইউটিএফ -8 এই প্রকল্পের জন্য পছন্দসই এনকোডিং।

আমি স্ট্যাক ওভারফ্লোতে কিছু পোস্ট পড়েছি এবং তাদের মধ্যে অনেকগুলি ইউটিএফ -8 এর সাথে লেনদেন করার সময় std::string ব্যবহার করার পরামর্শ দেয় এবং ইউটিএফ -8 এর জন্য এখনই char8_t নেই বলে char8_t এড়িয়ে চলতে পরামর্শ দেয়।

তবে, তাদের মধ্যে কেউ কীভাবে str[i] , std::string::size() , std::string::find_first_of() বা std::regex std::string::find_first_of() মতো ফাংশনগুলি সঠিকভাবে মোকাবেলা করতে পারে সে সম্পর্কে আলোচনা করে না কারণ এই ফাংশনটি সাধারণত অপ্রত্যাশিত ফলাফল দেয় যখন ইউটিএফ -8 মুখোমুখি হন।

আমার কি std::wstring std::string দিয়ে এগিয়ে যাওয়া উচিত বা std::wstring স্যুইচ করা std::wstring ? যদি আমার std::string সাথে থাকা উচিত তবে উপরের সমস্যাগুলি পরিচালনা করার জন্য সবচেয়ে ভাল অনুশীলন কোনটি?


ইউনিকোড গ্লোসারি

ইউনিকোড একটি বিস্তৃত এবং জটিল বিষয়। আমি সেখানে খুব গভীরভাবে তলিয়ে যেতে চাই না, তবে একটি দ্রুত শব্দকোষ প্রয়োজন:

  1. কোড পয়েন্টস : কোড পয়েন্ট হ'ল ইউনিকোডের প্রাথমিক বিল্ডিং ব্লক, একটি কোড পয়েন্ট হ'ল একটি পূর্ণসংখ্যা যা একটি অর্থ ম্যাপ করা হয়। পূর্ণসংখ্যার অংশটি 32 টি বিটের সাথে খাপ খায় (ভাল, সত্যিই 24 বিট) এবং এর অর্থ হ'ল একটি বর্ণ, ডায়রিটিক, একটি সাদা স্থান, একটি চিহ্ন, একটি হাসিখুশি, অর্ধ পতাকা হতে পারে ... এবং এটি এমনকি " পরের অংশটি ডান থেকে বামে পড়ে "।
  2. গ্রাফিম ক্লাস্টারস : গ্রাফিম ক্লাস্টারগুলি শব্দার্থবিজ্ঞানের সাথে সম্পর্কিত কোড পয়েন্টগুলির গোষ্ঠী, উদাহরণস্বরূপ, ইউনিকোডে একটি পতাকা দুটি কোড পয়েন্ট যুক্ত করে প্রতিনিধিত্ব করে; এই দু'জনের প্রত্যেকেরই বিচ্ছিন্নতার কোনও অর্থ নেই, তবে গ্রাফিম ক্লাস্টারে একত্রে যুক্ত তারা একটি পতাকা উপস্থাপন করে। গ্রাফিম ক্লাস্টারগুলি কিছু স্ক্রিপ্টে ডায়াক্রিটিকের সাথে একটি চিঠি যুক্ত করতে ব্যবহৃত হয়।

এটি ইউনিকোডের বেসিক। কোড পয়েন্ট এবং গ্রাফিম ক্লাস্টারের মধ্যে পার্থক্যটি বেশিরভাগ ক্ষেত্রেই প্রকাশিত হতে পারে কারণ বেশিরভাগ আধুনিক ভাষার জন্য প্রতিটি "চরিত্র" একটি একক কোড পয়েন্টে ম্যাপ করা হয় (সাধারণত ব্যবহৃত অক্ষর + ডায়াক্রিটিক সংমিশ্রনের জন্য উত্সর্গীকৃত উচ্চারণ ফর্ম রয়েছে)। তবুও, আপনি যদি স্মাইলি, পতাকা ইত্যাদিতে উদ্যোগী হন ... তবে আপনাকে এই পার্থক্যের দিকে মনোযোগ দিতে হতে পারে।

ইউটিএফ প্রাইমার

তারপরে, ইউনিকোড কোড পয়েন্টগুলির একটি সিরিয় এনকোড করতে হবে; সাধারণ এনকোডিংগুলি হ'ল ইউটিএফ -8, ইউটিএফ -16 এবং ইউটিএফ -32, মোটামুটি 5 টি সাধারণ এনকোডিংয়ের জন্য লিটল-এন্ডিয়ান এবং বিগ-এন্ডিয়ান উভয় ফর্মের মধ্যে দুটি পরে বিদ্যমান।

ইউটিএফ-এক্সে, এক্স কোড ইউনিটের বিটগুলির আকার, প্রতিটি কোড পয়েন্ট তার দৈর্ঘ্যের উপর নির্ভর করে এক বা একাধিক কোড ইউনিট হিসাবে প্রতিনিধিত্ব করা হয়:

  • ইউটিএফ -8: 1 থেকে 4 কোড ইউনিট,
  • UTF-16: 1 বা 2 কোড ইউনিট,
  • ইউটিএফ -32: 1 কোড ইউনিট।

std::wstring std::string এবং std::wstring

  1. std::wstring ব্যবহার করবেন না যদি আপনি বহনযোগ্যতার বিষয়ে চিন্তা করেন ( std::wstring কেবলমাত্র 16 বিট); পরিবর্তে std::u32string ব্যবহার করুন (ওরফে std::basic_string<char32_t> )।
  2. ইন-মেমরি প্রতিনিধিত্ব ( std::wstring std::string বা std::wstring ) অন ডিস্ক উপস্থাপনা (ইউটিএফ -8, ইউটিএফ -16 বা ইউটিএফ std::wstring ) থেকে স্বতন্ত্র, সুতরাং সীমানায় রূপান্তর করার জন্য নিজেকে প্রস্তুত করুন (পড়া এবং লেখা)।
  3. যদিও একটি 32-বিটস wchar_t নিশ্চিত করে যে কোনও কোড ইউনিট একটি সম্পূর্ণ কোড পয়েন্ট উপস্থাপন করে, তবুও এটি একটি সম্পূর্ণ গ্রাফি ক্লাস্টারকে উপস্থাপন করে না।

আপনি যদি কেবল স্ট্রিংগুলি পড়ছেন বা রচনা করছেন তবে আপনার কাছে std::wstring std::string বা std::wstring std::string খুব কম সমস্যা থাকতে হবে না।

সমস্যাগুলি শুরু হয়ে গেলে আপনি কাটা এবং ডাইসিং শুরু করেন, তারপরে আপনাকে (1) কোড পয়েন্টের সীমানা (ইউটিএফ -8 বা ইউটিএফ -16 এ) এবং (2) গ্রাফিম ক্লাস্টারস সীমানায় মনোযোগ দিতে হবে। প্রাক্তনটিকে আপনার নিজের পক্ষে সহজেই পরিচালনা করা যায়, পরবর্তীটির জন্য একটি ইউনিকোড সচেতন লাইব্রেরি ব্যবহার করা দরকার।

std::u32string std::string বা std::u32string std::string std::u32string ?

পারফরম্যান্স যদি উদ্বেগের বিষয় থাকে তবে সম্ভবত এটি ছোট মেমরির পদক্ষেপের কারণে std::string আরও ভাল অভিনয় করবে; যদিও চাইনিজদের ভারী ব্যবহারের ফলে ডিলটি বদলে যেতে পারে। সর্বদা হিসাবে, প্রোফাইল।

গ্রাফেম ক্লাস্টার যদি সমস্যা না হয় তবে std::u32string জিনিসগুলি সরল করার সুবিধা রয়েছে: 1 কোড ইউনিট -> 1 কোড পয়েন্টের অর্থ আপনি দুর্ঘটনাক্রমে কোড পয়েন্টগুলি বিভক্ত করতে পারবেন না, এবং std::basic_string সমস্ত ফাংশন এর বাইরে কাজ করবে না std::basic_string বাক্স।

আপনি যদি std::string বা char* / char const* নিয়ে সফ্টওয়্যারটির সাথে ইন্টারফেস করেন তবে ব্যাক-ওভার রূপান্তরগুলি এড়াতে std::string । অন্যথায় এটি ব্যথা হবে।

std::string ইউটিএফ -8।

ইউটিএফ -8 আসলে std::string বেশ ভাল কাজ করে।

বেশিরভাগ ক্রিয়াকলাপ বাক্সের বাইরে চলে যায় কারণ ইউটিএফ -8 এনকোডিংটি স্ব-সিঙ্ক্রোনাইজিং এবং এএসসিআইআইয়ের সাথে পিছনে সামঞ্জস্যপূর্ণ।

কোড পয়েন্টগুলি যেভাবে এনকোড করা হয়েছে, সেই কারণে কোড পয়েন্ট সন্ধান করা দুর্ঘটনাক্রমে অন্য কোড পয়েন্টের মাঝের সাথে মেলে না:

  • str.find('\n') কাজ করে,
  • str.find("...") বাইট 1 দ্বারা বাইট মেলানোর জন্য কাজ করে ,
  • str.find_first_of("\r\n") যদি ASCII অক্ষরগুলির সন্ধান করে তবে কাজ করে।

একইভাবে, regex বেশিরভাগ বাক্সের বাইরে কাজ করে। অক্ষরগুলির ক্রম হিসাবে ( "haha" ) কেবলমাত্র বাইটের অনুক্রম ( "哈" ), প্রাথমিক অনুসন্ধান নিদর্শনগুলি বাক্সের বাইরে কাজ করা উচিত।

রেজেক্স স্বাদ এবং প্রয়োগের উপর নির্ভর করে এটি ইউনিকোডের অক্ষরগুলির সাথে মেলে বা নাও পারে, যেমন চরিত্র শ্রেণীর (যেমন [:alphanum:] ) থেকে সাবধান থাকুন।

একইভাবে, ASCII বিহীন "অক্ষর", "哈?" প্রয়োগের বিষয়ে সতর্ক থাকুন "哈?" কেবলমাত্র শেষ বাইটটিকে alচ্ছিক বিবেচনা করতে পারে; এই জাতীয় ক্ষেত্রে বাইটগুলির পুনরাবৃত্ত ক্রমটি পরিষ্কারভাবে চিত্রিত করতে প্রথম বন্ধনী ব্যবহার করুন: "(哈)?"

1 সন্ধানের মূল ধারণাগুলি হ'ল সাধারনকরণ এবং কোলেশন; এটি সমস্ত তুলনামূলক ক্রিয়াকলাপগুলিকে প্রভাবিত করে। std::string কোনও ভাষা বা ব্যবহারের সাথে নির্দিষ্ট তুলনার বিধি বিবেচনা না করে সর্বদা বাইট বাই বাইটের সাথে তুলনা করে (এবং এইভাবে সাজান) will আপনার যদি সম্পূর্ণ স্বাভাবিককরণ / কল্যানেশন পরিচালনা করতে হয় তবে আপনার আইসিইউর মতো একটি সম্পূর্ণ ইউনিকোড লাইব্রেরি প্রয়োজন।


সি ++ ২০ এবং std::u8string আপগ্রেড করার কথা বিবেচনা করুন এটি ইউটিএফ -8 ধরে রাখার জন্য আমাদের 2019 সালের সেরা জিনিস। স্বতন্ত্র কোড পয়েন্ট বা গ্রাফিম ক্লাস্টারগুলিতে অ্যাক্সেসের জন্য কোনও স্ট্যান্ডার্ড গ্রন্থাগার সুবিধা নেই তবে কমপক্ষে আপনার টাইপটি কমপক্ষে সত্য সত্য ইউটিএফ -8 বলার পক্ষে যথেষ্ট শক্তিশালী।


std::wstring std::string এবং std::wstring উভয়ই std::wstring উপস্থাপন করতে ইউটিএফ এনকোডিং ব্যবহার করতে হবে। বিশেষত ম্যাকোএসে, std::string ইউটিএফ -8 (8-বিট কোড ইউনিট), এবং std::wstring ইউটিএফ -32 (32-বিট কোড ইউনিট); নোট করুন যে wchar_t এর আকার প্ল্যাটফর্ম নির্ভর।

উভয়ের জন্যই size কোড পয়েন্ট বা গ্রাফি ক্লাস্টারের সংখ্যার পরিবর্তে কোড ইউনিটের সংখ্যা ট্র্যাক করে। (একটি কোড পয়েন্ট হ'ল ইউনিকোড সত্তা নামক একটি, যার এক বা একাধিক গ্রাফি ক্লাস্টার গঠন করে Gra গ্রাফিক ক্লাস্টারগুলি দৃশ্যমান অক্ষর যা ব্যবহারকারীরা অক্ষর বা ইমোজিসের মত ইন্টারেক্ট করে থাকেন interact)

যদিও আমি চাইনিজদের ইউনিকোড উপস্থাপনার সাথে পরিচিত নই, তবে এটি খুব সম্ভব যে আপনি যখন ইউটিএফ -32 ব্যবহার করবেন তখন কোড ইউনিটের সংখ্যা প্রায়শই গ্রাফিক ক্লাস্টারের সংখ্যার খুব কাছাকাছি থাকে। স্পষ্টতই, তবে এটি 4x পর্যন্ত আরও মেমরি ব্যবহার করে ব্যয় করতে আসে।

সুনির্দিষ্ট সমাধানটি হ'ল আপনি যে ইউনিকোড বৈশিষ্ট্যগুলি পরে যাচ্ছেন তা গণনা করতে আইসিইউয়ের মতো একটি ইউনিকোড লাইব্রেরি ব্যবহার করা।

অবশেষে, মানব ভাষাগুলিতে ইউটিএফ স্ট্রিংগুলি যা সংমিশ্রিত অক্ষরগুলি ব্যবহার করে না তারা সাধারণত regex / regex সাথে বেশ ভাল করে। আমি চাইনিজ সম্পর্কে নিশ্চিত নই, তবে ইংরেজি সেগুলির মধ্যে একটি।





c++11