creo que cualquier respuesta canónica (wRTlas notas de recompensas) implicarían algunas fases distintas en la solución:
- Comprobación de errores de entrada válida
- cheque Longitud y
- Contenido de los datos de verificación de conversión
- Elemento creación
- salida
Given th Para la utilidad de tales conversiones, la solución probablemente debería incluir alguna flexibilidad w.r.t. los tipos que se usan y la configuración regional requerida.
Desde el principio, dada la fecha de la solicitud de una "respuesta más canónica" (circa agosto de 2014) se aplicará el uso liberal de C++ 11.
una versión anotada del código, con los tipos correspondientes a la OP:
std::vector<std::uint8_t> convert(std::string const& src)
{
// error check on the length
if ((src.length() % 2) != 0) {
throw std::invalid_argument("conversion error: input is not even length");
}
auto ishex = [] (decltype(*src.begin()) c) {
return std::isxdigit(c, std::locale()); };
// error check on the data contents
if (!std::all_of(std::begin(src), std::end(src), ishex)) {
throw std::invalid_argument("conversion error: input values are not not all xdigits");
}
// allocate the result, initialised to 0 and size it to the correct length
std::vector<std::uint8_t> result(src.length()/2, 0);
// run the actual conversion
auto str = src.begin(); // track the location in the string
std::for_each(result.begin(), result.end(), [&str](decltype(*result.begin())& element) {
element = static_cast<std::uint8_t>(std::stoul(std::string(str, str + 2), nullptr, 16));
std::advance(str, 2); // next two elements
});
return result;
}
La versión de la plantilla del código añade flexibilidad;
template <typename Int /*= std::uint8_t*/,
typename Char = char,
typename Traits = std::char_traits<Char>,
typename Allocate = std::allocator<Char>,
typename Locale = std::locale>
std::vector<Int> basic_convert(std::basic_string<Char, Traits, Allocate> const& src, Locale locale = Locale())
{
using string_type = std::basic_string<Char, Traits, Allocate>;
auto ishex = [&locale] (decltype(*src.begin()) c) {
return std::isxdigit(c, locale); };
if ((src.length() % 2) != 0) {
throw std::invalid_argument("conversion error: input is not even length");
}
if (!std::all_of(std::begin(src), std::end(src), ishex)) {
throw std::invalid_argument("conversion error: input values are not not all xdigits");
}
std::vector<Int> result(src.length()/2, 0);
auto str = std::begin(src);
std::for_each(std::begin(result), std::end(result), [&str](decltype(*std::begin(result))& element) {
element = static_cast<Int>(std::stoul(string_type(str, str + 2), nullptr, 16));
std::advance(str, 2);
});
return result;
}
La función convert()
entonces se puede basar en la basic_convert()
como sigue:
std::vector<std::uint8_t> convert(std::string const& src)
{
return basic_convert<std::uint8_t>(src, std::locale());
}
Live sample.
Hey @Nirav, parece que algunas respuestas a continuación han ayudado a resolver su problema. Si ese es el caso, sería bueno "aceptar" la respuesta que más te guste (con la casilla de verificación a la izquierda de la respuesta). Puede (o podrá con suficiente reputación) [votar] (http://stackoverflow.com/privileges/vote-up) todas las respuestas útiles. –