Я хочу прочитать идентификатор 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));
}





Я думаю, вы используете 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";
}
Ваша проблема может заключаться в выводе проанализированных данных. Оператор «<<» принимает решения о том, как отображать данные на основе переданного им типа данных, а 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]);
}
когда я делаю cout int функцию синтаксического анализа, я получаю правильные значения, но когда я назначаю их массиву uint8_t, они сбиваются. Я попробовал ваше предложение, он работает в функции, но они все равно запутались, когда я их назначаю.