J'ai une longue chaîne et j'ai besoin de convertir des chiffres en mots (ex. 5 à cinq). Puis-je faire cela avec une regex? J'ai essayé d'utiliser regex_replace , mais cela a changé tous les nombres en celui qui a été trouvé en premier (par exemple, il a converti "5 10 1 0" en "cinq cinq cinq cinq", mais j'ai besoin de "cinq dix un zéro ").
C'était ma tentative:
string text ="a lot of text";
regex pattern("(\\d)+");
smatch result;
int x; string buffer;
while (regex_search(text, result, pattern))
{
buffer = result[0];
x = atoi(buffer.c_str());
switch (x)
{
case 0: text = regex_replace(text, pattern, numbers[0]); break;
case 1: text = regex_replace(text, pattern, numbers[1]); break;
case 2: text = regex_replace(text, pattern, numbers[2]); break;
case 3: text = regex_replace(text, pattern, numbers[3]); break;
case 4: text = regex_replace(text, pattern, numbers[4]); break;
case 5: text = regex_replace(text, pattern, numbers[5]); break;
case 6: text = regex_replace(text, pattern, numbers[6]); break;
case 7: text = regex_replace(text, pattern, numbers[7]); break;
case 8: text = regex_replace(text, pattern, numbers[8]); break;
case 9: text = regex_replace(text, pattern, numbers[9]); break;
case 10: text = regex_replace(text, pattern, numbers[10]); break;
}
text = result.suffix().str();
}
3 Réponses :
Le code suivant fera ce que vous demandez. Ce n'est pas très efficace car il trouve le numéro deux fois (une fois avec std :: regex_search , une fois avec std :: string :: find ) mais il remplacera les chiffres 0 - 10 avec les mots zéro - dix.
#include <iostream>
#include <regex>
#include <string>
int main()
{
std::vector<std::string> numbers {
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
std::string text = "These numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 are text now";
std::string tmp_text = text;
std::regex pattern("(\\d)+");
std::smatch result;
int n;
std::string buffer;
std::size_t pos;
while (std::regex_search(tmp_text, result, pattern))
{
buffer = result[0];
n = atoi(buffer.c_str());
switch (n)
{
case 0:
pos = text.find('0');
text.replace(pos, 1, numbers[0]);
break;
case 1:
pos = text.find('1');
text.replace(pos, 1, numbers[1]);
break;
case 2:
pos = text.find('2');
text.replace(pos, 1, numbers[2]);
break;
case 3:
pos = text.find('3');
text.replace(pos, 1, numbers[3]);
break;
case 4:
pos = text.find('4');
text.replace(pos, 1, numbers[4]);
break;
case 5:
pos = text.find('5');
text.replace(pos, 1, numbers[5]);
break;
case 6:
pos = text.find('6');
text.replace(pos, 1, numbers[6]);
break;
case 7:
pos = text.find('7');
text.replace(pos, 1, numbers[7]);
break;
case 8:
pos = text.find('8');
text.replace(pos, 1, numbers[8]);
break;
case 9:
pos = text.find('9');
text.replace(pos, 1, numbers[9]);
break;
case 10:
pos = text.find("10");
text.replace(pos, 2, numbers[10]);
break;
}
tmp_text = result.suffix().str();
}
std::cout << text << std ::endl;
}
// output:
// These numbers: zero, one, two, three, four, five, six, seven, eight, nine, ten are text now
std :: regex_replace remplace toutes les occurrences de l'expression régulière, donc lors du premier appel, il remplacera tous les chiffres par la première correspondance.
Vous devez à la place parcourir les correspondances et ajouter le bon remplacement de la sortie.
Quelque chose comme ceci:
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string text = "before 5 10 1 11 after";
std::string numbers[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
std::regex pattern("\\d+");
std::string result;
std::smatch match;
auto begin = text.cbegin();
while (std::regex_search(begin, text.cend(), match, pattern)) {
result += match.prefix(); // copy the substring before the match
int x = std::stoi(match[0]);
if (x >= 0 && x <= 10) {
result += numbers[x];
} else {
result += match[0]; // a number but out-of-range - copy it as-is
}
begin += match.position() + match.length();
}
result += match.suffix(); // copy the substring after the last match
if (result.empty()) {
result = text; // special case - nothing matched
}
std::cout << result << std::endl;
}
Contrairement à d'autres solutions, celle-ci ne parcourt l'entrée qu'une seule fois, donc ce sera beaucoup plus rapide, en particulier sur les longues chaînes.
La raison pour laquelle vous obtenez "cinq cinq cinq" est que 5 est la première correspondance de la recherche regex, mais comme votre modèle est \ d + (chaque chiffre), il remplacera toutes les correspondances par "cinq"
Vous pouvez donc simplement faire un regex_replace pour chaque chiffre que vous souhaitez remplacer
#include <array>
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main(int, char**) {
auto numbers = array{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
string text = "6 18 2 3 4 5 2 0 0 1 4 10 19 9 1nin1ja xd3 10";
for (size_t i = 0; i < numbers.size(); ++i) {
regex pattern("\\b" + std::to_string(i) + "\\b");
text = regex_replace(text, pattern, numbers[i]);
}
cout << text << endl; //six 18 two three four five two zero zero one four ten 19 nine 1nin1ja xd3 ten
return 0;
}
tableau de nombres ressemble à: nombres [0] = "zéro" nombres [1] = "un" nombres [5] = "cinq" nombres [10] = "dix"