J'écris un analyseur c ++ pour un fichier d'options personnalisé pour une application. J'ai une boucle qui lit les lignes sous la forme de option=value
à partir d'un fichier texte où value
doit être converti en double
. En pseudocode, il fait ce qui suit:
while(not EOF)
statement <- read_from_file
useful_statement <- remove whitespaces, comments, etc from statement
equal_position <- find '=' in useful_statement
option_str <- useful_statement[0:equal_position)
value_str <- useful_statement[equal_position:end)
find_option(option_str) <- double(value_str)
Pour gérer le fractionnement de chaîne et le passage aux fonctions, j'utilise std::string_view
car il évite une copie excessive et indique clairement l'intention de visualiser les segments d'un _ std::string
. J'ai tout fait au point où std::string_view value_str
pointe vers la partie exacte de useful_statement
qui contient la valeur que je veux extraire, mais je ne sais pas comment lire un double
à partir d'un std::string_view
.
Je connais std::stod
qui ne fonctionne pas avec std::string_view
. Ça me permet d'écrire
double value = std::stod(std::string(value_str));
Cependant, c'est moche car il se convertit en une chaîne qui n'est pas réellement nécessaire, et même si cela ne fera vraisemblablement pas de différence notable dans mon cas, cela pourrait être trop lent si l'on devait lire une énorme quantité de nombres dans un texte fichier.
D'un autre côté, atof
ne fonctionnera pas car je ne peux pas garantir un terminateur nul. Je pourrais le pirater en ajoutant \0
à useful_statement
lors de sa construction, mais cela rendra le code déroutant pour un lecteur et le rendra trop facile à casser si le code est modifié/refactorisé.
Alors, quel serait un moyen propre, intuitif et raisonnablement efficace de le faire?
Puisque vous avez marqué votre question avec C++ 1z, cela signifie (théoriquement) que vous avez accès à from_chars
. Il peut gérer votre conversion de chaîne en nombre sans avoir besoin de plus d'une paire de const char*
s:
double dbl;
auto result = from_chars(value_str.data(), value_str.data() + value_str.size(), dbl);
Bien sûr, cela nécessite que votre bibliothèque standard fournisse une implémentation de from_chars
.
En-têtes:
#include <boost/convert.hpp>
#include <boost/convert/strtol.hpp>
Ensuite:
std::string x { "aa123.4"};
const std::string_view y(x.c_str()+2, 5); // Window that views the characters "123.4".
auto value = boost::convert<double>(y, boost::cnv::strtol());
if (value.has_value())
{
cout << value.get() << "\n"; // Prints: 123.4
}
Compilateurs testés:
p.s. Peut facilement installer Boost en utilisant vcpkg (par défaut à 32 bits, la deuxième commande est pour 64 bits):
vcpkg install boost-convert
vcpkg install boost-convert:x64-windows