เป็นไปได้ใน 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
ใช่คุณสามารถทำได้ แต่คุณต้องค้นหาตำแหน่งของสตริงแรกที่มีสมาชิก find () ของสตริงแล้วแทนที่ด้วยมันแทนที่ () สมาชิก
string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
s.replace( pos, 5, "somename" ); // 5 = length( $name )
}
หากคุณวางแผนที่จะใช้ห้องสมุดมาตรฐานคุณควรได้รับหนังสือ The C ++ Standard Libraryซึ่งครอบคลุมเนื้อหาทั้งหมดนี้เป็นอย่างดี
ฉันใช้สิ่งนี้โดยทั่วไป:
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 inline - ไม่จำเป็นต้องทำการมอบหมาย = กลับมา
ตัวอย่างการใช้งาน:
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);
}
}