Reputation: 11020
I have a program and I want to take a command line argument of a MAC address like "./myapp 00:11:22:33:44:55"
Later on the MAC address is used for struct sockaddr_ll.sll_addr
in an unsigned char array, each element is one octet of the MAC address. This function (found on a blog) takes the command line argument and seperates it using the colon ":" as the delimiter;
void StringExplode(string str, string separator, vector<string>* results){
int found;
found = str.find_first_of(separator);
while(found != string::npos){
if(found > 0){
results->push_back(str.substr(0,found));
}
str = str.substr(found+1);
found = str.find_first_of(separator);
}
if(str.length() > 0){
results->push_back(str);
}
}
My code taking in the command line argument looks like this;
unsigned char MAC[6];
vector<string> R;
string thisstring = argv[2];
StringExplode(thisstring, ":", &R);
MAC[0] = (unsigned char)atoi(R[0].c_str());
MAC[1] = (unsigned char)atoi(R[1].c_str());
MAC[2] = (unsigned char)atoi(R[2].c_str());
MAC[3] = (unsigned char)atoi(R[3].c_str());
MAC[4] = (unsigned char)atoi(R[4].c_str());
MAC[5] = (unsigned char)atoi(R[5].c_str());
printf("Ethernet %02x:%02x:%02x:%02x:%02x:%02x\n",MAC[0],MAC[1],MAC[2],MAC[3],MAC[4], MAC[5]);
However, this prints out "Ethernet 00:0b:16:21:2c:37". Is this because atoi() is wrapping around? I can't seem to pin point the issue here, however, I feel this probably is a bad way of doing things. I'm new to c++ but even to me this feels long winded so I expect someone of the keyboard heros here will be able to explain just how bad it is, and hopefully how I could make this more efficient.
Thank you.
Upvotes: 2
Views: 2951
Reputation: 227618
The problem is that you are reading in strings representing hexadecimal numbers as if they were decimal. C++11 string to integer conversion functions have a parameter where you can specify the base of the input, so to convert a hex string to an unsigned integer you can do this:
unsigned int i2 = std::stoi("ff", nullptr, 16); // input is base 16
See stoul, stoull, stol, stoi.
Upvotes: 2
Reputation: 34418
The problem is that you're parsing the octets as decimal numbers not hex - 11 = 0xb, 22 = 0x16, etc.
I'm not sure what the most C++ way of doing this is, but you can e.g. use strtoul with a base argument:
for(int i = 0; (i < 6) && (i < R.size()); ++i) {
MAC[i] = (unsigned char)strtoul(R[i].c_str(), NULL, 16);
}
Upvotes: 3
Reputation: 765
From my point of view everything is OK. The only point is that you are printing decimal values in hexadecimal view. Convert input values to hexadecimal.
Upvotes: 1