2013-03-30 2 views
3

Я хочу заменить некоторые слова, не используя внешние библиотеки. Моя первая попытка была сделать копию строки, но это не было эффективным, так что это еще одна попытка, где я использую адреса:Заменить целые слова в строковом списке без использования внешних библиотек

void ReplaceString(std::string &subject, const std::string &search, const std::string &replace) 
{ 
    size_t position = 0; 
    while ((position = subject.find(search, position)) != std::string::npos) //if something messes up --> failure 
    { 
     subject.replace(position, search.length(), replace); 
     position = position + replace.length(); 
    } 
} 

Потому что это не очень эффективно либо, я хочу использовать другую вещь , но я застрял; Я хочу использовать такую ​​функцию, как replace_stuff(std::string & a);, с одним параметром, используя string.replace() и string.find() (разбор его с помощью цикла for или что-то еще), а затем используйте std::map <std::string,std::string>;, что очень удобно для меня.

Я хочу использовать его для большого количества входных слов. (скажем, заменить многие плохие слова некоторыми безобидными)

+0

Не опускайтесь на себя. То, что вы делаете, на самом деле намного чище, чем вы можете подумать, особенно для тех, кто только делает это на C++ в течение нескольких месяцев. – WhozCraig

ответ

0

Вы можете создать класс, скажем Заменитель:

class Replacer 
{ 
    std::map<std::string,> replacement; 

public: 
    Replacer() 
    { 
    // init the map here 
    replacement.insert (std::pair<std::string,std::string>("C#","C++")); 
    //... 
    } 
    void replace_stuff(std::string & a); 
} 

Тогда определение replace_stuff будет очень похож на ваш оригинал ReplaceString (он использовал бы записи на карте вместо переданных параметров).

2

Проблема с вашим вопросом заключается в отсутствии необходимых компонентов в стандартной библиотеке. Если вам нужна эффективная реализация, вам, вероятно, понадобится trie для эффективного поиска. Написание одного из них в качестве части ответа было бы способом много кода.

Если вы используете std::map или, если C++ 11 доступен в вашей среде, std::unordered_map, вам нужно будет утилизировать дополнительную информацию о входной строке и парах поиска-замены с карты. Затем вы должны токенизировать строку и проверить каждый токен, если он должен быть заменен. Использование позиций, указывающих на входную строку, является хорошей идеей, поскольку она позволяет избежать копирования данных. Что приводит нас к:

Эффективность будет зависеть от доступа к памяти (чтение и запись), поэтому вы не должны изменять строку ввода. Создайте результат, начиная с пустой строки и добавляя фрагменты из ввода. Проверьте каждую часть ввода: если это слово, проверьте, нужно ли его заменять, или если он добавлен к выходу без изменений. Если это не часть слова, добавьте его немодифицированным.

2

Похоже, что вы хотите заменить все «плохие» слова в строке безвредными, но ваша текущая реализация неэффективна, потому что список плохих слов намного больше длины вашей входной строки (subject). Это верно?

Если это так, то следующий код должен сделать его более эффективным. Как вы можете видеть, мне пришлось передать карту в качестве параметра, но если ваша функция будет частью класса, вам не нужно это делать.

void ReplaceString(std::string &subject, const std::map<std::string, std::string>& replace_map) 
{ 
    size_t startofword = 0, endofword = 0; 
    while(startofword < subject.size()) 
    { 
     size_t length = std::string::npos; 

     //get next word in string 
     endofword = subject.find_first_of(" ", startofword); 
     if(endofword != std::string::npos) 
     length = endofword-startofword; 

     std::string search = subject.substr(startofword, length); 

     //try to find this word in the map 
     if(replace_map.find(search) != replace_map.end()) 
     { 
     //if found, replace the word with a new word 
     subject.replace(startofword, length, replace_map[search]); 
     startofword += replace_map[search].length(); 
     } 
     else 
     { 
     startofword += length; 
     } 

    } 

} 
2

Я использую следующие функции, надеюсь, что это помогает:

//============================================================================= 
//replaces each occurence of the phrase in sWhat with sReplacement 
std::string& sReplaceAll(std::string& sS, const std::string& sWhat, const std::string& sReplacement) 
{ 
    size_t pos = 0, fpos; 
    while ((fpos = sS.find(sWhat, pos)) != std::string::npos) 
    { 
     sS.replace(fpos, sWhat.size(), sReplacement); 
     pos = fpos + sReplacement.length(); 
    } 
    return sS; 
} 

//============================================================================= 
// replaces each single char from sCharList that is found within sS with entire sReplacement 
std::string& sReplaceChars(std::string& sS, const std::string& sCharList, const std::string& sReplacement) 
{ 
    size_t pos=0; 
    while (pos < sS.length()) 
    { 
     if (sCharList.find(sS.at(pos),0)!=std::string::npos) //pos is where a charlist-char was found 
     { 
      sS.replace(pos, 1, sReplacement); 
      pos += sReplacement.length()-1; 
     } 
     pos++; 
    } 
    return sS; 
} 
Смежные вопросы