2

我有一个程序,我想采用 MAC 地址的命令行参数,例如"./myapp 00:11:22:33:44:55"

稍后 MAC 地址用于struct sockaddr_ll.sll_addr无符号字符数组中,每个元素是 MAC 地址的一个八位字节。这个函数(在博客上找到)接受命令行参数并使用冒号“:”作为分隔符分隔它;

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

我的命令行参数代码如下所示;

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

但是,这会打印出“以太网 00:0b:16:21:2c:37”。这是因为 atoi() 正在环绕吗?我似乎无法在这里指出问题,但是,我觉得这可能是一种不好的做事方式。我是 c++ 的新手,但即使对我来说,这也感觉很啰嗦,所以我希望这里的键盘英雄能够解释它有多糟糕,并希望我可以如何让它更有效率。

谢谢你。

4

3 回答 3

3

问题是您将八位字节解析为十进制数字而不是十六进制 - 11 = 0xb、22 = 0x16 等。

我不确定执行此操作的最 C++ 方式是什么,但您可以使用strtoul和基本参数:

for(int i = 0; (i < 6) && (i < R.size()); ++i) {
    MAC[i] = (unsigned char)strtoul(R[i].c_str(), NULL, 16);
}
于 2012-05-08T09:51:36.013 回答
2

问题是您正在读取表示十六进制数字的字符串,就好像它们是十进制一样。C++11 字符串到整数转换函数有一个参数,您可以在其中指定输入的基数,因此要将十六进制字符串转换为无符号整数,您可以这样做:

unsigned int i2 = std::stoi("ff", nullptr, 16); // input is base 16

stoul, stoull, stol, stoi

于 2012-05-08T10:11:46.583 回答
1

从我的角度来看,一切都很好。唯一的一点是您正在以十六进制视图打印十进制值。将输入值转换为十六进制。

于 2012-05-08T09:50:30.167 回答