С ++ преобразование строки идентификатора Mac в массив uint8_t

Я хочу прочитать идентификатор Mac из командной строки и преобразовать его в массив значений uint8_t, чтобы использовать его в структуре. Не могу заставить его работать. У меня есть вектор строки для идентификатора Mac, разделенного на :, и я хочу использовать stringstream для их преобразования без везения. Что мне не хватает?

int parseHex(const string &num){
  stringstream ss(num);
  ss << std::hex;
  int n;
  ss >> n;  
  return n;
}

uint8_t tgt_mac[6] = {0, 0, 0, 0, 0, 0};
  v = StringSplit( mac , ":" );
  for( int j = 0 ; j < v.size() ; j++ ){
    tgt_mac[j] = parseHex(v.at(j)); 
  }
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
12 924
4

Ответы 4

Я думаю, вы используете std :: hex не в том месте:

#include <sstream>
#include <iostream>

int main()
{
    std::string     h("a5");
    std::stringstream   s(h);
    int x;

    s >> std::hex >> x;
    std::cout << "X(" << x << ")\n";
}

когда я делаю cout int функцию синтаксического анализа, я получаю правильные значения, но когда я назначаю их массиву uint8_t, они сбиваются. Я попробовал ваше предложение, он работает в функции, но они все равно запутались, когда я их назначаю.

Hamza Yerlikaya 09.11.2008 20:22

Ваша проблема может заключаться в выводе проанализированных данных. Оператор «<<» принимает решения о том, как отображать данные на основе переданного им типа данных, а uint8_t может интерпретироваться как char. Убедитесь, что вы преобразовали значения массива в целые при печати или исследуете в отладчике.

Пример программы:

uint8_t tgt_mac[6] = {0};
std::stringstream ss( "AA:BB:CC:DD:EE:11" );
char trash;

for ( int i = 0; i < 6; i++ )
{
    int foo;
    ss >> std::hex >> foo >> trash;
    tgt_mac[i] = foo;
    std::cout << std::hex << "Reading: " << foo << std::endl;
}

std::cout << "As int array: " << std::hex
    << (int) tgt_mac[0]
    << ":"
    << (int) tgt_mac[1]
    << ":"
    << (int) tgt_mac[2]
    << ":"
    << (int) tgt_mac[3]
    << ":"
    << (int) tgt_mac[4]
    << ":"
    << (int) tgt_mac[5]
    << std::endl;
std::cout << "As unint8_t array: " << std::hex
    << tgt_mac[0]
    << ":"
    << tgt_mac[1]
    << ":"
    << tgt_mac[2]
    << ":"
    << tgt_mac[3]
    << ":"
    << tgt_mac[4]
    << ":"
    << tgt_mac[5]
    << std::endl;

Дает следующий результат (cygwin g ++)

Reading: aa
Reading: bb
Reading: cc
Reading: dd
Reading: ee
Reading: 11
As int array: aa:bb:cc:dd:ee:11
As unint8_t array: ª:»:I:Y:î:◄

Сначала я хочу отметить, что я считаю ответ @Steven очень хорошим - действительно, я заметил то же самое: значения верны, но результат выглядит неуклюже. Это связано с использованием ostream& operator<<( ostream&, unsigned char ), поскольку используемый вами тип uint8_t является typedef для unsigned char (как я нашел на страницах руководства Linux). Обратите внимание, что в VC++ typedef отсутствует, и вместо этого вам нужно использовать unsigned __int8 (который также направит вас к специализации char).

Затем вы можете тестовое задание своего кода следующим образом (независимо от вывода):

assert( uint8_t( parseHex( "00" ) ) == uint8_t(0) );
assert( uint8_t( parseHex( "01" ) ) == uint8_t(1) );
//...
assert( uint8_t( parseHex( "ff" ) ) == uint8_t(255) );

В дополнение к ответу Стивена я просто хочу указать на существование алгоритма transform, который все еще может упростить ваш код.

for( int j = 0 ; j < v.size() ; j++ ){
  tgt_mac[j] = parseHex(v.at(j)); 
}

Пишет одной строкой:

std::transform( v.begin(), v.end(), tgt_mac, &parseHex );

(И я знаю, что это не имеет отношения к вопросу ...)

(См. codepad.org, чтобы узнать, как это тогда выглядит)

Я не хочу отвечать на этот вопрос таким образом, но sscanf(), вероятно, является наиболее лаконичным способом разобрать MAC-адрес. Он обрабатывает нулевые / ненулевые отступы, проверку ширины, складывание регистра и все другие вещи, с которыми никто не любит иметь дело. Во всяком случае, вот моя не совсем версия на C++:

void
parse_mac(std::vector<uint8_t>& out, std::string const& in) {
    unsigned int bytes[6];
    if (std::sscanf(in.c_str(),
                    "%02x:%02x:%02x:%02x:%02x:%02x",
                    &bytes[0], &bytes[1], &bytes[2],
                    &bytes[3], &bytes[4], &bytes[5]) != 6)
    {
        throw std::runtime_error(in+std::string(" is an invalid MAC address"));
    }
    out.assign(&bytes[0], &bytes[6]);
}

Другие вопросы по теме