c++ замена однобайтового и двухбайтного символа
пишу программу, которая переводит транслит на кириллицу
std::vector <std::pair<std::string, std::string>> vec = {
{"a", "а"},
{"b", "б"},
{"v", "в"},
{"g", "г"},
{"d", "д"},
{"e", "е"},
{"yo", "ё"},
{"zh", "ж"},
{"z", "з"},
{"i", "и"},
{"j", "дж"},
{"k", "к"},
{"l", "л"},
{"m", "м"},
{"n", "н"},
{"o", "о"},
{"p", "п"},
{"r", "р"},
{"s", "с"},
{"t", "т"},
{"u", "у"},
{"f", "ф"},
{"h", "х"},
{"cz", "ц"},
{"ch", "ч"},
{"sh", "ш"},
{"shh", "щ"},
{"''", "ъ"},
{"'", "ь"},
{"y", "ай"},
{"e'", "э"},
{"yu", "ю"},
{"ya", "я"},
{"x", "кс"},
{"w", "ви"},
{"c", "к"},
{"q", "к"},
{"A", "А"},
{"B", "Б"},
{"V", "В"},
{"G", "Г"},
{"D", "Д"},
{"E", "Е"},
{"yo", "Ё"},
{"zh", "Ж"},
{"Z", "З"},
{"I", "И"},
{"J", "Дж"},
{"K", "К"},
{"L", "Л"},
{"M", "М"},
{"N", "Н"},
{"O", "О"},
{"P", "П"},
{"R", "Р"},
{"S", "С"},
{"T", "Т"},
{"U", "У"},
{"F", "Ф"},
{"H", "Х"},
{"CZ", "Ц"},
{"CH", "Ч"},
{"SH", "Ш"},
{"SHH", "Щ"},
{"''", "ъ"},
{"'", "ь"},
{"Y", "Ай"},
{"E'", "Э"},
{"yu", "Ю"},
{"ya", "Я"},
{"X", "Кс"},
{"W", "Ви"},
{"C", "К"},
{"Q", "к"}
};
std::string text = "savchik";
for (auto it : vec) {
size_t f = std::string::npos;
do {
size_t f = text.find(it.first);
if (f != std::string::npos)
text = text.replace(f, it.first.length(), it.second);
} while (f != std::string::npos);
}
std::cout << text << std::endl;
программа выводит вместо "савчик", "савкхик"
Ответы (1 шт):
Это еще не все неприятности :) -- добавьте, например, в конце s — savchiks — и вы получите савкхикs.
Ну, с этой неприятностью справиться просто, достаточно только объявить size_t f один раз вне цикла. Посмотрите внимательно: в проверке while (f != std::string::npos) участвует совсем не та переменная f, которая изменяется в цикле! И, кстати, компилятор должен был об этом предупредить — если, конечно, он настроен на выдачу всех предупреждений (а именно так он и должен быть настроен даже у опытного программиста).
Ну, а у вас проблема в том, что вы ищете по своему списку, нет ли того, что надо заменить, а в нем h идет до ch, вот и меняется сначала h, а потом остается "голая" c, которая меняется на к.
В вашей программе (хотя я бы действовал, исходя из того, что надо менять, а не списка, что можно менять) надо список отсортировать по длине, начиная его как
{"SHH", "Щ"},
{"shh", "щ"},
{"yu", "Ю"},
{"ya", "Я"},
{"yo", "Ё"},
{"zh", "Ж"},
{"CZ", "Ц"},
{"CH", "Ч"},
{"SH", "Ш"},
{"cz", "ц"},
{"ch", "ч"},
{"sh", "ш"},
{"yo", "ё"},
{"zh", "ж"},
{"yu", "ю"},
{"ya", "я"},
{"a", "а"},
Кстати, не стал исправлять — обратите внимание, что во второй части списка у вас куча повторов из-за того, что всякие yo, yu написаны со строчной буквы, а не с прописной!
Кстати, проблему вы бы увидели сразу, если бы, даже не умея работать с отладчиком, просто добавили отладочный вывод типа
if (f != string::npos)
{
text = text.replace(f, it.first.length(), it.second);
cout << "replace " << it.first << " for " << it.second
<< ", text = " << text << endl;
}
а не бросались бы сразу в Интернет за решением тривиального вопроса. Так сказать, на работе вы тоже планируете решать проблемы таким образом? Напоминает маленького мальчика, который в ответ на "и как ты в армию пойдешь, если шнурки не научишься завязывать?" поясняет, что он с сотой для этого маму заберет :) Учитесь завязывать шнурки самостоятельно... Это не попытка наехать на вас, это попытка вам помочь в дальнейшей деятельности...