#c
#c
Вопрос:
#include <iostream> // std::cout
#include <string> // std::string, std::stoi
int main ()
{
const char* arrNumber = "ff000A;";
const std::string firstNum = std::string(arrNumber, 2);
const std::string secondNum = std::string(arrNumber 2, 4);
const int i_first = std::stoi(firstNum, nullptr, 16);
const int i_second= std::stoi(secondNum, nullptr, 16);
std::cout << "i_first: " << i_first << std::endl;
std::cout << "i_second: " << i_second << std::endl;
return 0;
}
У меня здесь два вопроса.
-
Как преобразовать символ фиксированной длины
char*
в число? В приведенном выше примере нам нужно извлечь первые два шестнадцатеричных символа в целое число. Предлагаемый метод медленный из-за построения astd::string
, и я ищу лучшее решение, подобное следующему прототипу.stoi_x(const char* start_, size_t len, int base = 10)
Учитывая этот прототип, приведенный выше пример можно записать следующим образом:
const int i_first = stoi_x(arrNumber, 2, 16);
-
Как преобразовать символ
char*
без нулевого терминатора в число?. Опять же, я ищу лучшее решение, подобное следующему прототипу.stoi_x(const char* start_, char end_, int base = 10)
Учитывая этот прототип, приведенный выше пример можно записать следующим образом:
const int i_second = stoi_x(arrNumber 2, ';', 16);
Комментарии:
1. @SergeyA это было из любопытства, извините, если это вызвало сомнение в мотивах операций
2. из любопытства: почему у вас есть строки с ненулевым завершением?
3. @user463035818, некоторые сетевые протоколы НЕ используют » в качестве завершителя для строки. Вместо этого он указывает только длину и начало строки.
Ответ №1:
Вы можете использовать std::from_chars
, и это поможет вам проделать большую часть пути прямо из коробки. Он принимает указатели на начальный элемент и один за последним элементом и преобразует его в число. Если он вообще не может преобразовать строку, он заполнит код ошибки в возвращаемом объекте, в противном случае он преобразует то, что может, и возвращает указатель на часть данных, которые он не смог преобразовать в возвращаемом объекте. Его использование в вашем коде изменяет его на
int main ()
{
const char* arrNumber = "ff000A;";
int i_first, i_second;
std::from_chars(arrNumber, arrNumber 2, i_first, 16);
std::from_chars(arrNumber 2, arrNumber 6, i_second, 16);
std::cout << "i_first: " << i_first << std::endl;
std::cout << "i_second: " << i_second << std::endl;
return 0;
}
Если вам не нравится, что вы не можете присвоить результат преобразования постоянной переменной, вы можете обернуть его в свою собственную функцию, например
template<typename T>
auto from_chars(char const * begin, char const * end, int base = 10)
{
T ret{};
std::from_chars(begin, end, ret, base);
return ret;
}
и затем вы можете использовать его как
int main ()
{
const char* arrNumber = "ff000A;";
const int i_first = from_chars<int>(arrNumber, arrNumber 2, 16);
const int i_second = from_chars<int>(arrNumber 2, arrNumber 6, 16);
std::cout << "i_first: " << i_first << std::endl;
std::cout << "i_second: " << i_second << std::endl;
return 0;
}
Обратите внимание, что я не выполняю никакой обработки ошибок. В производственном коде вы должны проверять, произошла ли ошибка, поскольку std::from_chars
не будет генерироваться никаких исключений.
Комментарии:
1. вы можете подумать о добавлении базового параметра в свой post, поскольку
std::from_chars
поддерживает это, а OP требует шестнадцатеричного преобразования. Спасибо2. @q0987 просто сделал так, как я видел, я пропустил это.
3. Сегодня я узнал от вас о новой функции и благодарю вас!
4. @q0987 Добро пожаловать. Рад помочь. Существует
to_chars
также часть счетчикаfrom_chars
, которая также должна быть максимально быстрой.