วิธีที่มีประสิทธิภาพในการแทนที่อักขระทั้งหมดด้วยอักขระอื่นมีstd::string
อะไรบ้าง
วิธีที่มีประสิทธิภาพในการแทนที่อักขระทั้งหมดด้วยอักขระอื่นมีstd::string
อะไรบ้าง
คำตอบ:
std::string
ไม่มีฟังก์ชันดังกล่าว แต่คุณสามารถใช้replace
ฟังก์ชันสแตนด์อะโลนจากalgorithm
ส่วนหัว
#include <algorithm>
#include <string>
void some_func() {
std::string s = "example string";
std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}
std::string::replace()
แทนที่จะเป็นstd::replace()
! 'x' ( char
) ถูก castic โดยนัยถึงsize_t
[ค่า 120] ดังนั้นสตริงทั้งหมดหรือบางส่วนจะเต็มไปด้วย 120 สำเนาของ 'y'
ฉันคิดว่าฉันจะโยนในโซลูชันเพิ่มเช่นกัน:
#include <boost/algorithm/string/replace.hpp>
// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");
// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");
-I
ค่าสถานะสำหรับคอมไพเลอร์ของคุณเพื่อให้สามารถค้นหาไลบรารี Boost บนระบบของคุณ บางทีคุณต้องติดตั้งมันเสียก่อน
คำถามอยู่ตรงกลางของการcharacter
แทนที่ แต่เมื่อฉันพบหน้านี้มีประโยชน์มาก (โดยเฉพาะหมายเหตุของKonrad ) ฉันต้องการแบ่งปันการใช้งานทั่วไปที่มากกว่านี้ซึ่งช่วยให้จัดการกับsubstrings
:
std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
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(); // Handles case where 'to' is a substring of 'from'
}
return str;
}
การใช้งาน:
std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;
ขาออก:
Number_Of_Beans
XXjXugtXty
hhjhugthty
แก้ไข:
ดังกล่าวข้างต้นสามารถดำเนินการในทางที่เหมาะสมมากขึ้นในการแสดงกรณีที่มีความกังวลของคุณโดยการกลับมาไม่มีอะไร ( void
) และการแสดงการเปลี่ยนแปลงโดยตรงบนสตริงstr
ให้เป็นอาร์กิวเมนต์, ส่งตามที่อยู่แทนด้วยค่า สิ่งนี้จะหลีกเลี่ยงการคัดลอกสตริงต้นฉบับที่ไม่มีประโยชน์และมีค่าใช้จ่ายสูงขณะที่ส่งคืนผลลัพธ์ สายของคุณแล้ว ...
รหัส:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
หวังว่านี่จะเป็นประโยชน์สำหรับคนอื่น ๆ ...
from
สายอักขระว่างเปล่ามิฉะนั้นจะเกิดการวนซ้ำไม่รู้จบ
ลองนึกภาพ Blob ไบนารีขนาดใหญ่ที่ 0x00 ไบต์ทั้งหมดจะถูกแทนที่ด้วย "\ 1 \ x30" และ 0x01 ไบต์ทั้งหมดด้วย "\ 1 \ x31" เพราะโปรโตคอลการขนส่งไม่อนุญาตให้ \ 0 ไบต์
ในกรณีที่:
ไม่สามารถใช้โซลูชันที่ให้มาได้ (เพราะพวกเขาแทนที่ตัวอักษรเดียวเท่านั้น) หรือมีปัญหาด้านประสิทธิภาพเนื่องจากพวกเขาจะเรียก string :: แทนที่หลาย ๆ ครั้งซึ่งสร้างสำเนาขนาดของหยดขึ้นไป (ฉันไม่ทราบวิธีเพิ่มประสิทธิภาพบางทีมันก็โอเคจากมุมมองนั้น)
สิ่งนี้เดินตามเหตุการณ์ที่เกิดขึ้นทั้งหมดในสตริงต้นฉบับและสร้างสตริงสตริงใหม่ทีละชิ้น:
void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
std::string newString;
newString.reserve(source.length()); // avoids a few memory allocations
std::string::size_type lastPos = 0;
std::string::size_type findPos;
while(std::string::npos != (findPos = source.find(from, lastPos)))
{
newString.append(source, lastPos, findPos - lastPos);
newString += to;
lastPos = findPos + from.length();
}
// Care for the rest after last occurrence
newString += source.substr(lastPos);
source.swap(newString);
}
การค้นหาและแทนที่อย่างง่ายสำหรับตัวละครตัวหนึ่งจะเป็นอย่างไร:
s.replace(s.find("x"), 1, "y")
การทำเช่นนี้สำหรับสตริงทั้งสิ่งที่ง่ายที่จะทำจะเป็นห่วงจนกว่าคุณจะเริ่มต้นกลับมาs.find
npos
ฉันคิดว่าคุณสามารถจับrange_error
เพื่อออกจากลูปได้ แต่มันก็น่าเกลียด
{
ตัวละคร ฉันไม่รู้ว่า "รั้งสองครั้ง" คืออะไร บางทีคุณอาจมีปัญหาเกี่ยวกับแบบอักษรบ้าง
หากคุณต้องการแทนที่อักขระมากกว่าหนึ่งตัวและกำลังจัดการกับข้อมูลเท่านั้นstd::string
ตัวอย่างข้อมูลนี้จะทำงานแทนที่ sNeedle ใน sHaystack ด้วย sReplace และ sNeedle และ sReplace ไม่จำเป็นต้องมีขนาดเท่ากัน รูทีนนี้ใช้วงวน while เพื่อแทนที่เหตุการณ์ทั้งหมดแทนที่จะเป็นเพียงครั้งแรกที่พบจากซ้ายไปขวา
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
find
โทรสองครั้ง ลองพิจารณาทำให้ผลลัพธ์นั้นเป็นตัวแปรชั่วคราว
ตามที่คิริลล์แนะนำให้ใช้วิธีการแทนที่หรือวนซ้ำตามสตริงเพื่อแทนที่ถ่านแต่ละตัวโดยอิสระ
หรือคุณสามารถใช้find
วิธีการหรือfind_first_of
ขึ้นอยู่กับสิ่งที่คุณต้องทำ ไม่มีวิธีแก้ปัญหาใดที่จะทำงานได้ในคราวเดียว แต่ด้วยโค้ดเพิ่มเติมอีกสองสามบรรทัดคุณควรทำให้มันทำงานให้คุณได้ :-)
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
int len, loop=0;
string nword="", let;
len=word.length();
len--;
while(loop<=len){
let=word.substr(loop, 1);
if(let==target){
nword=nword+replacement;
}else{
nword=nword+let;
}
loop++;
}
return nword;
}
//Main..
int main() {
string word;
cout<<"Enter Word: ";
cin>>word;
cout<<replace(word, "x", "y")<<endl;
return 0;
}
word
ยาวอาจมีโอเวอร์เฮดจำนวนมากขณะเรียกใช้ฟังก์ชัน คุณสามารถเพิ่มประสิทธิภาพนี้โดยผ่านword
, target
และreplacement
เป็น const อ้างอิง
แล้วAbseil StrReplaceAllล่ะ? จากไฟล์ส่วนหัว:
// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});
โรงเรียนเก่า :-)
std::string str = "H:/recursos/audio/youtube/libre/falta/";
for (int i = 0; i < str.size(); i++) {
if (str[i] == '/') {
str[i] = '\\';
}
}
std::cout << str;
ผลลัพธ์:
H: \ Recursos \ เสียง \ YouTube \ ฟรี \ falta \
มันใช้งานได้! ฉันใช้สิ่งที่คล้ายกับสิ่งนี้สำหรับแอปหนังสือที่เก็บสินค้าคงคลังในรูปแบบ CSV (เช่นไฟล์. dat) แต่ในกรณีของถ่านตัวเดียวหมายความว่าตัวจำลองเป็นเพียงตัวเดียวเช่น '|' จะต้องอยู่ในเครื่องหมายคำพูดคู่ "|" เพื่อไม่ให้เกิดการแปลง const char ที่ไม่ถูกต้อง
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count = 0; // for the number of occurences.
// final hold variable of corrected word up to the npos=j
string holdWord = "";
// a temp var in order to replace 0 to new npos
string holdTemp = "";
// a csv for a an entry in a book store
string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";
// j = npos
for (int j = 0; j < holdLetter.length(); j++) {
if (holdLetter[j] == ',') {
if ( count == 0 )
{
holdWord = holdLetter.replace(j, 1, " | ");
}
else {
string holdTemp1 = holdLetter.replace(j, 1, " | ");
// since replacement is three positions in length,
// must replace new replacement's 0 to npos-3, with
// the 0 to npos - 3 of the old replacement
holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3);
holdWord = "";
holdWord = holdTemp;
}
holdTemp = "";
count++;
}
}
cout << holdWord << endl;
return 0;
}
// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85
ตอนนี้ฉันใช้ CentOS อยู่แล้วดังนั้นรุ่นคอมไพเลอร์ของฉันจึงอยู่ด้านล่าง รุ่น C ++ (g ++), C ++ 98 เริ่มต้น:
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
หากคุณยินดีที่จะใช้std::string
คุณสามารถใช้strsub
ฟังก์ชั่นตัวอย่างของแอพนี้หรืออัปเดตหากคุณต้องการให้ใช้พารามิเตอร์ประเภทอื่นหรือชุดพารามิเตอร์เพื่อให้บรรลุเป้าหมายเดียวกันโดยประมาณ โดยทั่วไปจะใช้คุณสมบัติและฟังก์ชันการทำงานของได้อย่างรวดเร็วลบชุดการจับคู่ของตัวอักษรและแทรกตัวอักษรที่ต้องการโดยตรงภายในstd::string
std::string
ทุกครั้งที่มีการดำเนินการเปลี่ยนนี้ offset จะอัปเดตหากยังคงสามารถค้นหาตัวอักษรที่ตรงกันเพื่อแทนที่และหากไม่สามารถแทนที่ได้อีกต่อไปจะส่งคืนสตริงในสถานะจากการอัพเดตล่าสุด
#include <iostream>
#include <string>
std::string strsub(std::string stringToModify,
std::string charsToReplace,
std::string replacementChars);
int main()
{
std::string silly_typos = "annoiiyyyng syyyllii tiipos.";
std::cout << "Look at these " << silly_typos << std::endl;
silly_typos = strsub(silly_typos, "yyy", "i");
std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
silly_typos = strsub(silly_typos, "ii", "y");
std::cout << "There, no more " << silly_typos << std::endl;
return 0;
}
std::string strsub(std::string stringToModify,
std::string charsToReplace,
std::string replacementChars)
{
std::string this_string = stringToModify;
std::size_t this_occurrence = this_string.find(charsToReplace);
while (this_occurrence != std::string::npos)
{
this_string.erase(this_occurrence, charsToReplace.size());
this_string.insert(this_occurrence, replacementChars);
this_occurrence = this_string.find(charsToReplace,
this_occurrence + replacementChars.size());
}
return this_string;
}
หากคุณไม่ต้องการพึ่งพาการใช้std::string
s เป็นพารามิเตอร์ของคุณเพื่อให้คุณสามารถส่งผ่านสตริง C-style แทนคุณสามารถดูตัวอย่างที่อัปเดตด้านล่าง:
#include <iostream>
#include <string>
std::string strsub(const char * stringToModify,
const char * charsToReplace,
const char * replacementChars,
uint64_t sizeOfCharsToReplace,
uint64_t sizeOfReplacementChars);
int main()
{
std::string silly_typos = "annoiiyyyng syyyllii tiipos.";
std::cout << "Look at these " << silly_typos << std::endl;
silly_typos = strsub(silly_typos.c_str(), "yyy", "i", 3, 1);
std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
silly_typos = strsub(silly_typos.c_str(), "ii", "y", 2, 1);
std::cout << "There, no more " << silly_typos << std::endl;
return 0;
}
std::string strsub(const char * stringToModify,
const char * charsToReplace,
const char * replacementChars,
uint64_t sizeOfCharsToReplace,
uint64_t sizeOfReplacementChars)
{
std::string this_string = stringToModify;
std::size_t this_occurrence = this_string.find(charsToReplace);
while (this_occurrence != std::string::npos)
{
this_string.erase(this_occurrence, sizeOfCharsToReplace);
this_string.insert(this_occurrence, replacementChars);
this_occurrence = this_string.find(charsToReplace,
this_occurrence + sizeOfReplacementChars);
}
return this_string;
}
สำหรับสถานการณ์ง่าย ๆ มันใช้งานได้ค่อนข้างดีโดยไม่ต้องใช้ไลบรารี่ตัวอื่นจากนั้น std :: string (ซึ่งใช้งานอยู่แล้ว)
แทนที่อักขระa ทั้งหมดด้วยอักขระbในsome_string :
for (size_t i = 0; i < some_string.size(); ++i) {
if (some_string[i] == 'a') {
some_string.replace(i, 1, "b");
}
}
หากสตริงมีขนาดใหญ่หรือโทรซ้ำเพื่อแทนที่เป็นปัญหาคุณสามารถใช้เทคนิคที่กล่าวถึงในคำตอบนี้: https://stackoverflow.com/a/29752943/3622300
นี่คือทางออกที่ฉันรีดด้วยจิตวิญญาณ DRI สูงสุด มันจะค้นหา sNeedle ใน sHaystack และแทนที่ด้วย sReplace, nTimes ถ้าไม่ใช่ 0, อื่น ๆ ทั้งหมดที่เกิดขึ้น sNeedle มันจะไม่ค้นหาอีกครั้งในข้อความที่ถูกแทนที่
std::string str_replace(
std::string sHaystack, std::string sNeedle, std::string sReplace,
size_t nTimes=0)
{
size_t found = 0, pos = 0, c = 0;
size_t len = sNeedle.size();
size_t replen = sReplace.size();
std::string input(sHaystack);
do {
found = input.find(sNeedle, pos);
if (found == std::string::npos) {
break;
}
input.replace(found, len, sReplace);
pos = found + replen;
++c;
} while(!nTimes || c < nTimes);
return input;
}
std::string
เป็นคอนเทนเนอร์ที่ออกแบบมาเพื่อใช้งานกับลำดับของอักขระ ลิงก์