क्या C ++ में एक स्ट्रिंग के भाग को दूसरे स्ट्रिंग से बदलना संभव है?
मूल रूप से, मैं यह करना चाहूंगा:
QString string("hello $name");
string.replace("$name", "Somename");
लेकिन मैं मानक C ++ पुस्तकालयों का उपयोग करना चाहूंगा।
क्या C ++ में एक स्ट्रिंग के भाग को दूसरे स्ट्रिंग से बदलना संभव है?
मूल रूप से, मैं यह करना चाहूंगा:
QString string("hello $name");
string.replace("$name", "Somename");
लेकिन मैं मानक C ++ पुस्तकालयों का उपयोग करना चाहूंगा।
जवाबों:
एक स्ट्रिंग के भीतर एक विकल्प खोजने के लिए एक फ़ंक्शन है ( find
), और एक स्ट्रिंग में किसी विशेष रेंज को दूसरे स्ट्रिंग ( replace
) के साथ बदलने के लिए एक फ़ंक्शन है , ताकि आप उन प्रभावों को प्राप्त करने के लिए गठबंधन कर सकें जो आप चाहते हैं:
bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if(start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
std::string string("hello $name");
replace(string, "$name", "Somename");
एक टिप्पणी के जवाब में, मुझे लगता है replaceAll
कि शायद कुछ इस तरह दिखाई देगा:
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
from
और to
पारित किया गया const
? अगर from
वहाँ नहीं है तो आपका कार्य क्या है ? -1
उसके लिए मुझसे।
const
हूं और अगर मैंने इस तरह से एक उपयोगिता विधि लिखी है, तो मैं केवल इसे कॉल करूंगा यदि मुझे पता था प्रतिस्थापन मान्य थे
const
करना C ++ के सर्वश्रेष्ठ उपकरणों में से एक की अवहेलना है। फ़ंक्शन मापदंडों के लिए प्रति const
संदर्भ पासिंग डिफ़ॉल्ट मोड होना चाहिए। (FTR, बिना const
, आप अपने फ़ंक्शन के लिए स्ट्रिंग शाब्दिक भी पास नहीं कर सकते, क्योंकि आप अस्थायी लोगों को गैर- const
संदर्भों से बाँध नहीं सकते । इसलिए फ़ंक्शन भी ऐसा नहीं करेगा जो इसे लिखा गया था।)
C ++ 11 के साथ आप इसका उपयोग कर सकते हैं std::regex
:
#include <regex>
...
std::string string("hello $name");
string = std::regex_replace(string, std::regex("\\$name"), "Somename");
भागने के चरित्र से बचने के लिए डबल बैकस्लैश की आवश्यकता होती है।
std::regex_replace
है कि Qt की स्ट्रिंग को स्वीकार नहीं करता।
string
के साथ string.toStdString()
।
String
करने के लिए बदल रहा है std::string
, क्योंकि प्रश्न Qt से संबंधित नहीं है। कृपया ऐसा करने पर विचार करें - मैं ख़ुशी से आपके उत्तर को बाद में बढ़ा दूंगा।
R"(\$name)"
इसके बजाय लिखने की अनुमति देता है "\\$name"
।
std::string
एक replace
तरीका है, यह है कि आप क्या देख रहे हैं?
तुम कोशिश कर सकते हो:
s.replace(s.find("$name"), sizeof("$name") - 1, "Somename");
मैंने अपने आप को आज़माया नहीं है, बस प्रलेखन को पढ़ें find()
और replace()
।
नया स्ट्रिंग वापस करने के लिए इसका उपयोग करें:
std::string ReplaceString(std::string subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}
यदि आपको प्रदर्शन की आवश्यकता है, तो यहां एक अनुकूलित फ़ंक्शन है जो इनपुट स्ट्रिंग को संशोधित करता है, यह स्ट्रिंग की प्रतिलिपि नहीं बनाता है:
void ReplaceStringInPlace(std::string& subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
}
टेस्ट:
std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;
std::cout << "ReplaceString() return value: "
<< ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not modified: "
<< input << std::endl;
ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: "
<< input << std::endl;
आउटपुट:
Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
हां, आप इसे कर सकते हैं, लेकिन आपको पहले स्ट्रिंग की खोज () सदस्य के साथ स्ट्रिंग की स्थिति का पता लगाना होगा, और फिर इसे प्रतिस्थापित () सदस्य के साथ बदलना होगा।
string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
s.replace( pos, 5, "somename" ); // 5 = length( $name )
}
यदि आप मानक पुस्तकालय का उपयोग करने की योजना बना रहे हैं, तो आपको वास्तव में पुस्तक C ++ मानक पुस्तकालय की एक प्रति पकड़ लेनी चाहिए जो इस सभी सामान को अच्छी तरह से कवर करती है ।
मैं आम तौर पर इसका उपयोग करता हूं:
std::string& replace(std::string& s, const std::string& from, const std::string& to)
{
if(!from.empty())
for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
s.replace(pos, from.size(), to);
return s;
}
यह बार-बार std::string::find()
स्ट्रिंग की खोज की अन्य घटनाओं का पता लगाने के लिए कहता है जब तक std::string::find()
कि कुछ भी नहीं मिलता है। क्योंकि मैच std::string::find()
की स्थिति की वापसी में हमें पुनरावृत्तियों को अमान्य करने की समस्या नहीं है।
यह एक विकल्प की तरह लगता है
string.replace(string.find("%s"), string("%s").size(), "Something");
आप इसे एक फ़ंक्शन में लपेट सकते हैं लेकिन यह एक-पंक्ति समाधान स्वीकार्य लगता है। समस्या यह है कि यह केवल पहली घटना को बदल देगा, आप इसके ऊपर लूप करना चाहते हैं, लेकिन यह आपको एक ही टोकन के साथ इस स्ट्रिंग में कई चर डालने की अनुमति देता है ( %s
)
str.replace(str.find("%s"), string("%s").size(), "Something");
यदि सभी स्ट्रिंग्स std :: string हैं, तो आपको वर्णों के कटऑफ के साथ अजीब समस्याएं मिलेंगी यदि उपयोग करना है sizeof()
क्योंकि यह C स्ट्रिंग्स के लिए है, C ++ स्ट्रिंग्स के लिए नहीं। का .size()
वर्ग विधि का उपयोग करने के लिए ठीक है std::string
।
sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);
वह sHaystack इनलाइन को प्रतिस्थापित करता है - उस पर वापस = a असाइनमेंट करने की आवश्यकता नहीं है।
उदाहरण उपयोग:
std::string sHaystack = "This is %XXX% test.";
std::string sNeedle = "%XXX%";
std::string sReplace = "my special";
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
std::cout << sHaystack << std::endl;
wstring myString = L"Hello $$ this is an example. By $$.";
wstring search = L"$$";
wstring replace = L"Tom";
for (int i = myString.find(search); i >= 0; i = myString.find(search))
myString.replace(i, search.size(), replace);
यदि आप इसे जल्दी से करना चाहते हैं तो आप दो स्कैन दृष्टिकोण का उपयोग कर सकते हैं। छद्म कोड:
मुझे यकीन नहीं है कि यह एक इन-प्लेस एल्गो में अनुकूलित किया जा सकता है।
और एक C ++ 11 कोड उदाहरण है, लेकिन मैं केवल एक चार के लिए खोज करता हूं।
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
void ReplaceString(string& subject, char search, const string& replace)
{
size_t initSize = subject.size();
int count = 0;
for (auto c : subject) {
if (c == search) ++count;
}
size_t idx = subject.size()-1 + count * replace.size()-1;
subject.resize(idx + 1, '\0');
string reverseReplace{ replace };
reverse(reverseReplace.begin(), reverseReplace.end());
char *end_ptr = &subject[initSize - 1];
while (end_ptr >= &subject[0])
{
if (*end_ptr == search) {
for (auto c : reverseReplace) {
subject[idx - 1] = c;
--idx;
}
}
else {
subject[idx - 1] = *end_ptr;
--idx;
}
--end_ptr;
}
}
int main()
{
string s{ "Mr John Smith" };
ReplaceString(s, ' ', "%20");
cout << s << "\n";
}
std::string replace(std::string base, const std::string from, const std::string to) {
std::string SecureCopy = base;
for (size_t start_pos = SecureCopy.find(from); start_pos != std::string::npos; start_pos = SecureCopy.find(from,start_pos))
{
SecureCopy.replace(start_pos, from.length(), to);
}
return SecureCopy;
}
मेरा अपना कार्यान्वयन, इस बात को ध्यान में रखते हुए कि स्ट्रिंग को केवल एक बार फिर से आकार देने की आवश्यकता है, फिर प्रतिस्थापित किया जा सकता है।
template <typename T>
std::basic_string<T> replaceAll(const std::basic_string<T>& s, const T* from, const T* to)
{
auto length = std::char_traits<T>::length;
size_t toLen = length(to), fromLen = length(from), delta = toLen - fromLen;
bool pass = false;
std::string ns = s;
size_t newLen = ns.length();
for (bool estimate : { true, false })
{
size_t pos = 0;
for (; (pos = ns.find(from, pos)) != std::string::npos; pos++)
{
if (estimate)
{
newLen += delta;
pos += fromLen;
}
else
{
ns.replace(pos, fromLen, to);
pos += delta;
}
}
if (estimate)
ns.resize(newLen);
}
return ns;
}
उदाहरण इस प्रकार हो सकता है:
std::string dirSuite = replaceAll(replaceAll(relPath.parent_path().u8string(), "\\", "/"), ":", "");
मैं अभी C ++ सीख रहा हूं, लेकिन पहले से पोस्ट किए गए कुछ कोड को संपादित करना, मैं शायद इस तरह से कुछ का उपयोग करूंगा। यह आपको 1 या कई उदाहरणों को बदलने की सुविधा देता है, और आपको शुरुआती बिंदु को निर्दिष्ट करने की सुविधा भी देता है।
using namespace std;
// returns number of replacements made in string
long strReplace(string& str, const string& from, const string& to, size_t start = 0, long count = -1) {
if (from.empty()) return 0;
size_t startpos = str.find(from, start);
long replaceCount = 0;
while (startpos != string::npos){
str.replace(startpos, from.length(), to);
startpos += to.length();
replaceCount++;
if (count > 0 && replaceCount >= count) break;
startpos = str.find(from, startpos);
}
return replaceCount;
}
यह उपयोग करने के लिए और भी बेहतर हो सकता है
void replace(string& input, const string& from, const string& to)
{
while(true)
{
size_t startPosition = input.find(from);
if(startPosition == string::npos)
break;
input.replace(startPosition, from.length(), to);
}
}