Question

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.

Was it helpful?

Solution

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);
}

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top