преобразовать длинную строку символов в uint32_t или uint64_t в c

#c

#c

Вопрос:

Я хочу преобразовать строку, содержащую буквенно-цифровые символы, либо в uint32_t, либо в uint64_t. Попытался выполнить следующее. Но я получаю сообщение об ошибке «terminate вызывается после создания экземпляра ‘std:: out_of_range’ «. Кроме того, когда строка меньше по длине, например: string s = «hello», это работает, но что, если я хочу преобразовать более длинную строку в uint32_t или uint64_t.

 #include <iostream>
#include <sstream>
#include <iomanip>

std::string string_to_hex(const std::stringamp; in) {
    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    for (size_t i = 0; i < in.size();   i) {
        ss << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(in[i]));
    }

    return ss.str(); 
}

int main() {
   std::string s = "hello world, this 123";
   std::string hex_str = string_to_hex(s);
   uint32_t value = std::stoul(hex_str , nullptr, 16);
   cout<<value<<endl; 
}
  

Итак, согласно приведенным комментариям, является ли следующий лучший способ сделать это?

 int main()
{
    std::string s = "hello world, this 123";
    std::hash<std::string> hashed_name;
    uint32_t value = hashed_name(s);
    cout<<value<<endl;

    return 0;
}
  

Комментарии:

1. В вашем примере input string создается шестнадцатеричная строка "68656c6c6f20776f726c642c207468697320313233" , которая СЛИШКОМ ВЕЛИКА stoul() , чтобы вписаться как есть в an unsigned long . Похоже, вы пытаетесь преобразовать входную строку в число. Использование промежуточной шестнадцатеричной строки не является способом достижения этой цели. Hex — это просто способ представления двоичных данных в удобочитаемом формате. Это не изменяет сами данные. Вместо этого вам нужен реальный алгоритм хэширования, такой как CRC, MD5, SHA и т. Д. Они принимают произвольные данные в качестве входных данных и математически преобразуют их в числа фиксированной ширины в качестве выходных данных.

2. Сделайте себе одолжение и непосредственно std::cout << hex_str << 'n'; перед попыткой этого преобразования. Теперь посмотрите на эту вещь и спросите себя, есть ли шанс, что это превратится в платформу без знака длиной (которая обычно составляет 32 бита на x86, 64 бита на x64). Для предоставленных вами примеров данных 68656c6c6f20776f726c642c207468697320313233 будет источником преобразования, который преобразуется в 152575196276689931390365168237947948156825094926899 десятичный. Это никак не вписывается ни в 32-битное, ни в 64-битное значение.

3. Что вы собираетесь делать с этим числом? Вы когда-нибудь хотели преобразовать ее обратно в исходную строку?

4. @Vlad Feinstein, да, возможно, мне тоже придется это сделать.

5. Тогда о хешировании не может быть и речи (оно выполняется только в одну сторону). Снова, What are you going to do with that number?

Ответ №1:

Это, строго говоря, делает то, что вам нужно:

 #include <iostream>
#include <string>
#include <unordered_map>

class Converter
{
public:
  static int StringToInt(const std::stringamp; s)
  {
    auto it = cache.find(s);
    if (it != cache.end())
      return it->second;
    cache[s] = count;
    lookup[count  ] = s;
  }
  static std::string IntToString(unsigned i)
  {
    auto it = lookup.find(i);
    if (it != lookup.end())
      return it->second;
    return "";
  }
private:
  static inline unsigned count = 0;
  static inline std::unordered_map<std::string, int> cache;
  static inline std::unordered_map<int, std::string> lookup;
};

int main() {
  std::string s = "hello world, this 123";
  int  value = Converter::StringToInt(s);
  std::cout << value << std::endl;
  std::string s2 = Converter::IntToString(value);
  std::cout << s2 << std::endl;
  int  value2 = Converter::StringToInt("hello world, this 123");
  std::cout << value2 << std::endl;

}
  

Ответ №2:

Ваша проблема в том, что результирующее hex_str значение является ОГРОМНЫМ числом. В частности: 0x68656c6c6f20776f726c642c207468697320313233

Вы преобразуете каждый символ в двузначное шестнадцатеричное значение (т.Е. В один байт). Строки размером 4 (8, если используется 64-разрядный int) или более приведут к слишком большому числу, чтобы вписаться в ваш результирующий uint32_t или uint64_t

Посмотрите эту распечатку GDB вашей программы

Как упоминал Реми в комментариях, изучите алгоритмы хэширования.