সি (C) প্রোগ্রামিংয়ের স্ট্রিংগুলো মূলত যা হওয়ার স্বপ্ন দেখত, সি++ (C++)-এর স্ট্রিংগুলো ঠিক তা-ই — এখানে আর ক্যারেক্টার গোনার (counting characters) বা কোনো নাল টার্মিনেটরের (null terminators) ঝামেলা নেই
আগের নিয়মটি বেশ যন্ত্রণাদায়ক (Painful) ছিল
সি (C) প্রোগ্রামিংয়ে, একটি "স্ট্রিং (string)" বলতে মূলত ক্যারেক্টারের এমন একটি অ্যারেকে (array) বোঝাত, যা একটি অদ্ভুত '\0' বা নাল টার্মিনেটর (null terminator) দিয়ে শেষ হতো। আপনি কি দুটি স্ট্রিংকে যুক্ত করতে বা কনক্যাটেনেট (concatenate) করতে চান? তবে আপনাকে অবশ্যই তাদের দৈর্ঘ্য বা লেন্থ (lengths) জানতে হতো, পর্যাপ্ত মেমোরি বরাদ্দ (allocate) করতে হতো এবং strcat()-কে কল (call) করতে হতো — আর সব সময় দোয়া করতে হতো (hoping) যেন নির্দিষ্ট বাফারের চেয়ে তা বেশি না হয়ে যায় (overrun the buffer)। এখানে করা একটি ছোট ভুলেই সিকিউরিটি ভালনারাবিলিটি বা পুরো সিস্টেমের নিরাপত্তাই (security vulnerability) ঝুঁকিতে পড়তে পারত।
std::string মূলত সবকিছুই বদলে দিয়েছে। এটি নিজের মেমোরি (memory) নিজেই পরিচালনা (manages) করতে পারে, এর নিজস্ব দৈর্ঘ্য বা লেন্থ (length) সম্পর্কে এটি নিজেই অবগত থাকে এবং এটি আপনাকে a + b-এর মতো সহজ নিয়মে কনক্যাটেনেট (concatenate) করার সুবিধা দেয়। একেবারে শুরু থেকে স্ট্রিংগুলোর মূলত এমনই হওয়া উচিত ছিল।
স্ট্রিং তৈরি করা (Creating Strings)
একটি স্ট্রিং তৈরি করার অনেকগুলো উপায় রয়েছে এবং এর সবগুলোই আপনার কাছে বেশ স্বাভাবিক বা ন্যাচারাল (natural) মনে হবে:
স্ট্রিং (Strings) তৈরি (Creating) এবং কনক্যাটেনেট (Concatenating) করা
#include <iostream>
#include <string>
using namespace std;
int main(){
// স্ট্রিং (strings) তৈরির বিভিন্ন উপায়
string greeting ="Hello";
string name("World");
string repeated(5,'*');// "*****"
string copy = greeting;// এটি একটি রিয়েল কপি (real copy) তৈরি করে
// + দিয়ে কনক্যাটেনেশন (Concatenation)
string message = greeting +", "+ name +"!";
cout << message << endl;
// += দিয়ে অ্যাপেন্ড (Append) করা
string sentence ="C++";
sentence +=" is";
sentence +=" powerful";
cout << sentence << endl;
// সাইজ (Size) এবং লেন্থ (length) (এরা হুবহু একই বা identical)
cout <<"Length: "<< message.length()<< endl;// লেন্থ বা Length:
cout <<"Size: "<< message.size()<< endl;// সাইজ বা Size:
cout <<"Empty? "<< boolalpha << message.empty()<< endl;// ফাঁকা কি না বা Empty?
return0;
}
Output
Hello, World!
C++ is powerful
Length: 13
Size: 13
Empty? false
সার্চ করা এবং মডিফাই করা (Searching & Manipulating)
এখানকার স্ট্রিংগুলো (Strings) মূলত বিভিন্ন টেক্সট খোঁজার (finding) এবং মডিফাই (modifying) করার জন্য বিভিন্ন মেথডে ভরপুর থাকে। এর মধ্যে প্রধান মেথডগুলো হলো find(), substr(), এবং replace()। এখানকার find()-টিকে আপনি কিছুটা কোনো একটি সার্চ বারের (search bar) মতো চিন্তা করতে পারেন — এটি মূলত এর প্রথম ম্যাচটির (first match) অবস্থান (position) বা পজিশনটি রিটার্ন করে, অথবা যদি কোনো কিছুই না পাওয়া যায় তবে এটি string::npos রিটার্ন করে থাকে।
সার্চ করা (Searching), সাবস্ট্রিং (Substring) ও রিপ্লেস (Replace)
#include <iostream>
#include <string>
using namespace std;
int main(){
string text ="The quick brown fox jumps over the lazy dog";
// find() মূলত এর পজিশন বা position রিটার্ন করে, অথবা খুঁজে না পাওয়া গেলে এটি string::npos রিটার্ন করে
size_t pos = text.find("fox");
if(pos != string::npos){
cout <<"Found 'fox' at index "<< pos << endl;// 'fox' পাওয়া গেছে ইনডেক্স বা index
}
// substr(শুরু বা start, দৈর্ঘ্য বা length)
string word = text.substr(16,3);// "fox"
cout <<"Extracted: "<< word << endl;// এক্সট্রাক্টেড (Extracted) বা আলাদা করা অংশ:
// replace(শুরু বা start, দৈর্ঘ্য বা length, নতুন স্ট্রিং বা new_string)
text.replace(pos,3,"cat");
cout <<"Replaced: "<< text << endl;// রিপ্লেসড (Replaced) বা প্রতিস্থাপিত অংশ:
// একটি ক্যারেক্টার (character) সার্চ বা find করা
size_t spacePos = text.find(' ');
cout <<"First space at: "<< spacePos << endl;// প্রথম স্পেসটি (space) রয়েছে এখানে:
return0;
}
Output
Found 'fox' at index 16
Extracted: fox
Replaced: The quick brown cat jumps over the lazy dog
First space at: 3
ক্যারেক্টারগুলোর (Characters) ওপর ইটারেট (Iterating) করা
// এখানকার ক্যারেক্টারগুলোকে ইন-প্লেসেই মডিফাই (Modify) করা
string shout ="whisper";
for(char& c : shout){// এখানকার & লক্ষ্য করুন (Note) — আমরা এটি ইন-প্লেসেই মডিফাই (modify) করছি
c =toupper(c);
}
cout << shout << endl;
// এখানকার আলাদা আলাদা ক্যারেক্টারগুলোকে (characters) অ্যাক্সেস (Access) করা
cout <<"First char: "<< word[0]<< endl;// প্রথম ক্যারেক্টার বা First char:
cout <<"Last char: "<< word.back()<< endl;// শেষ ক্যারেক্টার বা Last char:
return0;
}
Output
Uppercase letters: 2
WHISPER
First char: H
Last char: !
স্ট্রিংগুলোর তুলনা বা কম্পেয়ার করা (Comparing Strings)
#include <iostream>
#include <string>
using namespace std;
int main(){
string a ="apple";
string b ="banana";
string c ="apple";
// == মূলত এর কন্টেন্টের সমতা বা equality চেক (checks) করে (যা জাভা বা Java থেকে ভিন্ন!)
cout << boolalpha;
cout <<"a == c: "<<(a == c)<< endl;// true
cout <<"a == b: "<<(a == b)<< endl;// false
// < এবং > মূলত আভিধানিকভাবে বা লেক্সিকোগ্রাফিক্যালি (lexicographically) তুলনা করে থাকে
cout <<"a < b: "<<(a < b)<< endl;// true বা সত্যি (a মূলত b-এর আগে আসে)
cout <<"b < a: "<<(b < a)<< endl;// false
// compare() মূলত সমান (equal) হলে 0, ছোট (less) হলে নেগেটিভ (negative), এবং বড় (greater) হলে পজিটিভ (positive) সাইন রিটার্ন করে
cout <<"compare: "<< a.compare(b)<< endl;// কম্পেয়ার বা compare:
return0;
}
Output
a == c: true
a == b: false
a < b: true
b < a: false
compare: -1
c_str() — সি (C) কোডের সাথে কথা বলা
কখনও কখনও আপনাকে কোনো একটি সি (C) লাইব্রেরি ফাংশনে — যা মূলত একটি const char* প্রত্যাশা (expects) করে — একটি std::string পাস (pass) করার প্রয়োজন হতে পারে। আর ঠিক এই কাজের জন্যই মূলত c_str()-টি ব্যবহার করা হয় — এটি আপনাকে এর ভেতরের ডেটাগুলোর জন্য মূলত একটি নাল-টার্মিনেটেড সি-স্ট্রিং পয়েন্টার (null-terminated C-string pointer) প্রদান করে থাকে。
std::string_view হলো মূলত একটি স্ট্রিংয়ের জন্য বেশ হালকা (lightweight), নন-ওউনিং (non-owning) বা মালিকানাহীন একটি ভিউ (view)। এটি কোনো মেমোরি অ্যালোকেট (allocate memory) করে না কিংবা কোনো ক্যারেক্টার কপিও (copy characters) করে না — এটি শুধু এর বিদ্যমান বা অ্যাক্টিভ কোনো স্ট্রিংয়ের ডেটার (existing string's data) দিকে পয়েন্ট (points) করে থাকে। আর ঠিক এই ব্যাপারটিই এটিকে এমন সব ফাংশন প্যারামিটারের (function parameters) জন্য একে পারফেক্ট (perfect) করে তোলে, যখন আপনার কেবল একটি স্ট্রিংকে পড়ার (read) প্রয়োজন হয়。
স্ট্রিং ভিউ বা string_view — কপি (Copying) করা ছাড়াই রিড (Read) করা
#include <iostream>
#include <string>
#include <string_view>
using namespace std;
// কোনো প্রকার কপি (copying) করা ছাড়াই এটি std::string এবং C-strings — উভয়টিকেই মূলত অ্যাক্সেপ্ট (Accepts) করে
voidprintInfo(string_view sv){
cout <<"Text: "<< sv << endl;// টেক্সট বা Text:
cout <<"Length: "<< sv.length()<< endl;// লেন্থ বা Length:
cout <<"First 5: "<< sv.substr(0,5)<< endl;// প্রথম ৫টি বা First 5:
}
int main(){
string str ="Hello from std::string";
const char* cstr ="Hello from C-string";
printInfo(str);// কোনো কপি (copy) হচ্ছে না!
cout <<"---"<< endl;
printInfo(cstr);// কোনো কপি (copy) হচ্ছে না!
return0;
}
Output
Text: Hello from std::string
Length: 22
First 5: Hello
---
Text: Hello from C-string
Length: 19
First 5: Hello
Note: যেকোনো রিড-ওনলি (read-only) বা শুধুমাত্র পঠনযোগ্য স্ট্রিং প্যারামিটারের ক্ষেত্রে std::string_view ব্যবহার করুন — এটি মূলত যেকোনো অনুলিপি তৈরি করা বা কপি (copying) হওয়া এড়িয়ে চলে এবং এটি std::string ও সি-স্ট্রিং (C-strings) উভয়ের সাথেই দারুণভাবে কাজ করে। শুধু একটি ব্যাপার খেয়াল রাখবেন (careful): একটি string_view কখনোই ওই মূল ডেটার মালিক (own) হতে পারে না, তাই যদি এর আসল বা মূল স্ট্রিংটি (original string) মুছে বা নষ্ট (destroyed) হয়ে যাওয়ার সম্ভাবনা থাকে তবে এটিকে সংরক্ষণ বা স্টোর (store) করতে যাবেন না।
র স্ট্রিং লিটারালগুলো (Raw String Literals) — আর কোনো এস্কেপ (Escape) ম্যাডনেস বা পাগলামি নয়