Apakah mungkin dalam C ++ untuk mengganti bagian dari string dengan string lain?
Pada dasarnya, saya ingin melakukan ini:
QString string("hello $name");
string.replace("$name", "Somename");
Tapi saya ingin menggunakan pustaka C ++ standar.
Apakah mungkin dalam C ++ untuk mengganti bagian dari string dengan string lain?
Pada dasarnya, saya ingin melakukan ini:
QString string("hello $name");
string.replace("$name", "Somename");
Tapi saya ingin menggunakan pustaka C ++ standar.
Jawaban:
Ada fungsi untuk menemukan substring dalam string ( find
), dan fungsi untuk mengganti rentang tertentu dalam string dengan string lain ( replace
), sehingga Anda bisa menggabungkan mereka untuk mendapatkan efek yang Anda inginkan:
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");
Menanggapi komentar, saya pikir replaceAll
mungkin akan terlihat seperti ini:
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
dan to
lulus per const
referensi? Apa fungsi Anda jika from
tidak ada? -1
dari saya untuk itu.
const
dan jika saya menulis metode utilitas seperti ini saya hanya akan menyebutnya jika saya tahu penggantian itu valid
const
mengabaikan salah satu alat terbaik C ++. Lulus per const
referensi harus menjadi mode default untuk parameter fungsi. (FTR, tanpa const
, Anda bahkan tidak bisa meneruskan string literal ke fungsi Anda, karena Anda tidak dapat mengikat sementara ke non- const
referensi. Jadi fungsi tersebut bahkan tidak akan melakukan apa yang ditulis untuk.)
Dengan C ++ 11 Anda dapat menggunakan std::regex
seperti ini:
#include <regex>
...
std::string string("hello $name");
string = std::regex_replace(string, std::regex("\\$name"), "Somename");
Double backslash diperlukan untuk melarikan diri dari karakter pelarian.
std::regex_replace
tidak menerima string Qt.
string
dengan string.toStdString()
.
String
ke std::string
, karena pertanyaannya tidak terkait dengan Qt. Silakan pertimbangkan untuk melakukan itu - Saya dengan senang hati akan meningkatkan jawaban Anda setelahnya.
R"(\$name)"
bukan "\\$name"
.
std::string
mempunyai sebuah replace
metode, apakah itu yang Anda cari?
Kamu bisa mencoba:
s.replace(s.find("$name"), sizeof("$name") - 1, "Somename");
Saya belum mencoba sendiri, cukup baca dokumentasi find()
dan replace()
.
Untuk mengembalikan string baru, gunakan ini:
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;
}
Jika Anda membutuhkan kinerja, berikut ini adalah fungsi yang dioptimalkan yang memodifikasi string input, ini tidak membuat salinan string:
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();
}
}
Tes:
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;
Keluaran:
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
Ya, Anda dapat melakukannya, tetapi Anda harus menemukan posisi string pertama dengan anggota find (), dan kemudian ganti dengan anggota replace ().
string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
s.replace( pos, 5, "somename" ); // 5 = length( $name )
}
Jika Anda berencana menggunakan Perpustakaan Standar, Anda harus benar-benar mendapatkan salinan buku Perpustakaan C ++ Standar yang mencakup semua hal ini dengan sangat baik.
Saya menggunakan ini secara umum:
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;
}
Berulang kali panggilan std::string::find()
untuk mencari kejadian lain dari string yang dicari sampai std::string::find()
tidak menemukan apa pun. Karena std::string::find()
mengembalikan posisi pertandingan, kami tidak memiliki masalah untuk membatalkan iterator.
Ini terdengar seperti opsi
string.replace(string.find("%s"), string("%s").size(), "Something");
Anda bisa membungkus ini dalam suatu fungsi tetapi solusi satu baris ini terdengar dapat diterima. Masalahnya adalah ini akan mengubah kejadian pertama saja, Anda mungkin ingin mengulanginya, tetapi juga memungkinkan Anda untuk memasukkan beberapa variabel ke string ini dengan token yang sama ( %s
)
str.replace(str.find("%s"), string("%s").size(), "Something");
Jika semua string std :: string, Anda akan menemukan masalah aneh dengan cutoff karakter jika menggunakan sizeof()
karena itu dimaksudkan untuk string C, bukan string C ++. Cara mengatasinya adalah dengan menggunakan .size()
metode kelas std::string
.
sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);
Itu menggantikan inline sHaystack - tidak perlu melakukan tugas = kembali itu.
Contoh penggunaan:
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);
Jika Anda ingin melakukannya dengan cepat, Anda dapat menggunakan pendekatan dua pemindaian. Kode palsu:
Saya tidak yakin apakah ini dapat dioptimalkan ke algo di tempat.
Dan contoh kode C ++ 11 tapi saya hanya mencari satu karakter.
#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;
}
Implementasi saya sendiri, dengan mempertimbangkan bahwa string perlu diubah ukuran hanya sekali, maka ganti bisa terjadi.
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;
}
Penggunaan bisa misalnya seperti ini:
std::string dirSuite = replaceAll(replaceAll(relPath.parent_path().u8string(), "\\", "/"), ":", "");
Saya baru saja belajar C ++, tetapi mengedit beberapa kode yang sebelumnya diposting, saya mungkin akan menggunakan sesuatu seperti ini. Ini memberi Anda fleksibilitas untuk mengganti 1 atau beberapa instance, dan juga memungkinkan Anda menentukan titik awal.
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;
}
Ini bisa lebih baik untuk digunakan
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);
}
}