আমি যদি একটি লাইনের সাথে একটি স্ট্যান্ড :: স্ট্রিং তৈরি করতে চাই তবে:
std::string my_string("a\0b");
যেখানে আমি ফলস্বরূপ স্ট্রিংয়ে তিনটি অক্ষর রাখতে চাই (ক, নাল, খ), আমি কেবল একটি পেয়েছি। সঠিক বাক্য গঠন কী?
আমি যদি একটি লাইনের সাথে একটি স্ট্যান্ড :: স্ট্রিং তৈরি করতে চাই তবে:
std::string my_string("a\0b");
যেখানে আমি ফলস্বরূপ স্ট্রিংয়ে তিনটি অক্ষর রাখতে চাই (ক, নাল, খ), আমি কেবল একটি পেয়েছি। সঠিক বাক্য গঠন কী?
উত্তর:
আমরা আক্ষরিক তৈরি করতে সক্ষম হয়েছি std::string
#include <iostream>
#include <string>
int main()
{
using namespace std::string_literals;
std::string s = "pl-\0-op"s; // <- Notice the "s" at the end
// This is a std::string literal not
// a C-String literal.
std::cout << s << "\n";
}
সমস্যাটি এমন std::stringকনস্ট্রাক্টর যা const char*ধরে নেয় ইনপুটটি সি-স্ট্রিং। সি-স্ট্রিংগুলি \0সমাপ্ত হয় এবং এভাবে \0অক্ষরটি পৌঁছালে পার্সিং বন্ধ হয়ে যায় ।
এর জন্য ক্ষতিপূরণ দেওয়ার জন্য, আপনাকে এমন কন্সট্রাক্টর ব্যবহার করতে হবে যা একটি চর অ্যারে (কোনও সি-স্ট্রিং নয়) থেকে স্ট্রিং তৈরি করে। এটি দুটি পরামিতি নেয় - অ্যারেতে একটি পয়েন্টার এবং একটি দৈর্ঘ্য:
std::string x("pq\0rs"); // Two characters because input assumed to be C-String
std::string x("pq\0rs",5); // 5 Characters as the input is now a char array with 5 characters.
নোট: সি ++ std::stringহয় না \0 -terminated (অন্যান্য পোস্টে প্রস্তাবিত)। তবে, আপনি একটি অভ্যন্তরীণ বাফারে একটি পয়েন্টারটি বের করতে পারেন যাতে পদ্ধতিটির সাথে সি-স্ট্রিং রয়েছে c_str()।
এ ব্যবহার সম্পর্কে নীচে ডগ টি এর উত্তরও দেখুন vector<char>।
এছাড়াও চেক আউট রিয়াদ একটি সি ++ 14 সমাধান জন্য।
আপনি যদি ম্যানিপুলেশনটি করে থাকেন তবে আপনি সি-স্টাইলের স্ট্রিং দিয়ে (অক্ষরের অ্যারে) ব্যবহার বিবেচনা করবেন
std::vector<char>
আপনি যেমন সি-স্ট্রিংয়ের মতো আচরণ করেন তেমনভাবে অ্যারের মতো আচরণ করার আপনার আরও স্বাধীনতা রয়েছে। স্ট্রিনে অনুলিপি করতে আপনি অনুলিপি () ব্যবহার করতে পারেন:
std::vector<char> vec(100)
strncpy(&vec[0], "blah blah blah", 100);
std::string vecAsStr( vec.begin(), vec.end());
এবং আপনি সি-স্ট্রিংগুলি একই স্থানে ব্যবহার করতে পারেন একই জায়গায় এটি ব্যবহার করতে পারেন
printf("%s" &vec[0])
vec[10] = '\0';
vec[11] = 'b';
স্বাভাবিকভাবেই, আপনি সি-স্ট্রিংয়ের মতো একই সমস্যায় ভুগছেন। আপনি আপনার নাল টার্মিনালটি ভুলে যেতে পারেন বা বরাদ্দকৃত স্থানটি লিখে দিতে পারেন।
byte *bytes = new byte[dataSize]; std::memcpy(bytes, image.data, dataSize * sizeof(byte)); std::string test(reinterpret_cast<char *>(bytes)); std::cout << "Encoded String length " << test.length() << std::endl;
আপনি কেন এমন কাজ করতে চান তা আমার কোনও ধারণা নেই তবে এটি চেষ্টা করুন:
std::string my_string("a\0b", 3);
vector<unsigned char>বা এর unsigned char *জন্য আবিষ্কার করা হয়েছিল।
std::stringতথ্যটি প্লেইন-পাঠ্য হিসাবে বিবেচনা করা উচিত তা বোঝাতে ব্যবহার করি তবে আমি কিছু হ্যাশিংয়ের কাজ করছি এবং আমি নিশ্চিত করতে চাই যে জড়িত শূন্য চরিত্রগুলির সাথে এখনও সমস্ত কিছু কাজ করে। এটি এম্বেডড নাল চরিত্রের সাথে একটি স্ট্রিং আক্ষরিকের বৈধ ব্যবহারের মতো বলে মনে হচ্ছে।
\0UTF-8 স্ট্রিংয়ের একটি বাইট কেবল NUL হতে পারে। একটি মাল্টি বাইট এনকোডেড অক্ষর কখনই থাকতে পারে না - \0এই বিষয়ে অন্য কোনও ASCII অক্ষর নেই।
ব্যবহারকারী-সংজ্ঞায়িত আক্ষরিকাগুলি সি ++ এ কী নতুন ক্ষমতা যুক্ত করে? একটি মার্জিত উত্তর উপস্থাপন করুন: সংজ্ঞায়িত করুন
std::string operator "" _s(const char* str, size_t n)
{
return std::string(str, n);
}
তাহলে আপনি আপনার স্ট্রিংটি এভাবে তৈরি করতে পারেন:
std::string my_string("a\0b"_s);
বা এমনকি:
auto my_string = "a\0b"_s;
একটি "পুরানো শৈলী" উপায় আছে:
#define S(s) s, sizeof s - 1 // trailing NUL does not belong to the string
তাহলে আপনি সংজ্ঞা দিতে পারেন
std::string my_string(S("a\0b"));
নিম্নলিখিতটি কাজ করবে ...
std::string s;
s.push_back('a');
s.push_back('\0');
s.push_back('b');
আপনি এই সম্পর্কে যত্নবান হতে হবে। যদি আপনি 'বি' কে কোনও সংখ্যাসূচক অক্ষরের সাথে প্রতিস্থাপন করেন তবে আপনি বেশিরভাগ পদ্ধতি ব্যবহার করে নিঃশব্দে ভুল স্ট্রিং তৈরি করবেন। দেখুন: সি ++ স্ট্রিং আক্ষরিক জন্য পালনের চরিত্রের নিয়ম ।
উদাহরণস্বরূপ, আমি এই প্রোগ্রামের মাঝখানে এই নিরীহ চেহারা স্নিপেটটি ফেলে দিয়েছি
// Create '\0' followed by '0' 40 times ;)
std::string str("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", 80);
std::cerr << "Entering loop.\n";
for (char & c : str) {
std::cerr << c;
// 'Q' is way cooler than '\0' or '0'
c = 'Q';
}
std::cerr << "\n";
for (char & c : str) {
std::cerr << c;
}
std::cerr << "\n";
এই প্রোগ্রামটি আমার জন্য কি ফলাফল:
Entering loop.
Entering loop.
vector::_M_emplace_ba
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
এটি আমার দু'বার প্রথম মুদ্রণ বিবরণী ছিল, বেশ কয়েকটি নন-প্রিন্টিং অক্ষর, তার পরে একটি নতুন লাইন, তারপরে অভ্যন্তরীণ মেমরির কিছু, যা আমি কেবল ওভাররোট করে (এবং তারপরে মুদ্রণ করে দেখানো হয় যে এটি ওভাররাইট হয়েছে)। সর্বোপরি সবচেয়ে খারাপ, এমনকি এটি পুরোপুরি এবং ভার্বোজ জিসিসি সতর্কতার সাথে সংকলন করা আমাকে কিছু ভুল হওয়ার ইঙ্গিত দেয় নি, এবং ভালগ্রাইন্ডের মাধ্যমে প্রোগ্রামটি চালানো কোনও মেমরি অ্যাক্সেসের অনুষঙ্গ সম্পর্কে অভিযোগ করেনি। অন্য কথায়, এটি আধুনিক সরঞ্জামগুলি দ্বারা সম্পূর্ণরূপে নিরীক্ষণযোগ্য।
আপনি এই একই সমস্যাটি আরও সহজরূপে পেতে পারেন std::string("0", 100);তবে উপরের উদাহরণটি একটি সামান্য কৌশলযুক্ত এবং কী ভুল তা দেখতে আরও শক্ত er
ভাগ্যক্রমে, সি ++ 11 ইনিশিয়ালার তালিকা সিনট্যাক্স ব্যবহার করে সমস্যার একটি ভাল সমাধান দেয়। এটি আপনাকে অক্ষরের সংখ্যা নির্দিষ্ট করা থেকে বাঁচায় (যা আমি উপরে দেখিয়েছি, আপনি ভুলভাবে করতে পারেন), এবং পালানো সংখ্যার সমন্বয় এড়ানো যায় avo std::string str({'a', '\0', 'b'})যে কোনও স্ট্রিং সামগ্রীর জন্য সুরক্ষিত, সংস্করণগুলির চেয়ে আলাদা যা কোনও অ্যারে charএবং আকার নেয়।
সি ++ 14 এ আপনি এখন আক্ষরিক ব্যবহার করতে পারেন
using namespace std::literals::string_literals;
std::string s = "a\0b"s;
std::cout << s.size(); // 3
auto s{"a\0b"s};
এই প্রশ্নটি যদি কেবল শিক্ষামূলক উদ্দেশ্যে না হয় তবে std :: vector <car> ব্যবহার করা ভাল।
বেনামের উত্তরটি দুর্দান্ত, তবে সি ++ 98 তে একটি অ-ম্যাক্রো সমাধানও রয়েছে:
template <size_t N>
std::string RawString(const char (&ch)[N])
{
return std::string(ch, N-1); // Again, exclude trailing `null`
}
এই ফাংশন সহ, RawString(/* literal */)একই স্ট্রিং উত্পাদন করবে S(/* literal */):
std::string my_string_t(RawString("a\0b"));
std::string my_string_m(S("a\0b"));
std::cout << "Using template: " << my_string_t << std::endl;
std::cout << "Using macro: " << my_string_m << std::endl;
অতিরিক্ত হিসাবে, ম্যাক্রো নিয়ে একটি সমস্যা রয়েছে: এক্সপ্রেশনটি আসলে std::stringলিখিত হিসাবে হয় না এবং তাই ব্যবহার করা যায় না যেমন সাধারণ অ্যাসাইনমেন্ট-ইনিশিয়ালাইজের জন্য:
std::string s = S("a\0b"); // ERROR!
... সুতরাং এটি ব্যবহার করা ভাল:
#define std::string(s, sizeof s - 1)
স্পষ্টতই আপনার প্রকল্পে আপনার কেবল একটি বা অন্য সমাধান ব্যবহার করা উচিত এবং আপনি যা উপযুক্ত মনে করেন তা কল করুন।
আমি জানি এটি দীর্ঘ সময় এই প্রশ্ন জিজ্ঞাসা করা হয়েছে। তবে যার জন্য একই সমস্যা রয়েছে তার জন্য নিম্নলিখিত কোডটিতে আগ্রহী হতে পারে।
CComBSTR(20,"mystring1\0mystring2\0")
স্ট্যান্ড :: স্ট্রিংয়ের প্রায় সমস্ত বাস্তবায়ন বাতিল-সমাপ্ত, সুতরাং আপনার সম্ভবত এটি করা উচিত নয়। নোট করুন যে স্বয়ংক্রিয় নাল টার্মিনেটর (এ, নাল, বি, নাল) এর কারণে "a \ 0b" আসলে চারটি অক্ষর দীর্ঘ long আপনি যদি সত্যিই এটি করতে এবং std :: স্ট্রিংয়ের চুক্তিটি ভাঙতে চান তবে আপনি এটি করতে পারেন:
std::string s("aab");
s.at(1) = '\0';
তবে আপনি যদি করেন তবে আপনার সমস্ত বন্ধুরা আপনাকে উপহাস করবে, আপনি কখনই সত্যিকারের সুখ পাবেন না।