C ++ преобразование строки идентификатора Mac в массив uint8_t - PullRequest
1 голос
/ 09 ноября 2008

Я хочу прочитать идентификатор Mac из командной строки и преобразовать его в массив значений uint8_t, чтобы использовать его в структуре. Я не могу заставить его работать. У меня есть вектор строки для Mac ID, разделенный на :, и я хочу использовать 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)); 
  }

Ответы [ 4 ]

3 голосов
/ 30 ноября 2008

Я не хочу отвечать на это таким образом, но 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]);
}
2 голосов
/ 10 ноября 2008

Сначала я хочу отметить, что я думаю, что ответ @ Стивена очень хороший - действительно, я заметил то же самое: значения верны, но результат выглядит неловко. Это связано с тем, что используется 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 о том, как он тогда выглядит)

1 голос
/ 10 ноября 2008

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

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

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:î:◄
0 голосов
/ 09 ноября 2008

Я думаю, что вы используете 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";
}
...