วิธีที่มีประสิทธิภาพในการแทนที่อักขระทั้งหมดด้วยอักขระอื่นมี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::strings เป็นพารามิเตอร์ของคุณเพื่อให้คุณสามารถส่งผ่านสตริง 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เป็นคอนเทนเนอร์ที่ออกแบบมาเพื่อใช้งานกับลำดับของอักขระ ลิงก์