将csv读取的十六进制字符串值转换为c ++中的uint8_t

时间:2019-05-29 02:08:20

标签: c++ csv hex getline uint8t

因此,我目前能够使用ifstream从csv文件中读取一些十六进制值。我能够读取值并将它们分配给字符串变量。但是我想将它们转换为uint8_t值。所以本质上我想要这样的uint8_t A = 0x41;

我尝试了atoistoistrtol,但是我似乎没有得到任何有效的输出。(我可能错误地使用了它们)

int read_csv(){
using namespace std;
ifstream fin;
fin.open("simpletrajhex.txt");
while (fin.good ()){
      char[] line;
      getline (fin, line, ',');
      uint8_t hex1 = (uint8_t)stoi(line,NULL,16);
      cout << line << " " << hex1 << endl;
    }
  return 1;
}

当我读取csv文件时,我得到了类似的东西

0xFF
0x5F
0x02
0x00
0xFF

但是这些是字符串,我需要将每个值都转换为uint8_t 当我尝试转换时,什么都没有显示。

2 个答案:

答案 0 :(得分:0)

您无法像在uint8_t变量中那样存储 hex 值,因此无法使用uint8_t A = 0x41。取而代之的是,您必须将与 hex decimal 等效的数字放入uint8_t中。 / p>

尝试使用std::stoul

获得与 hex 等效的 十进制 ,并获得 hex ,在需要时从 十进制 返回。

答案 1 :(得分:0)

您的代码有很多问题,但是有两个主要问题与您转换为uint8_t有关。尝试使用.csv读取getline (fin, line, ',');文件的一个普遍问题是您无法跟踪每一行中存在的值的数量。使用','分隔符读取将导致getline跳过行尾,并简单地读取下一个值,直到遇到EOF。最好用line将整行读入getline (fin, line);,然后从stringstream创建一个line,使您可以读取行中的值,直到到达字符串流的末尾(将值转换限制为每行中的值转换)。

将值存储为uint8_t的主要障碍是您无法进行 validate (验证),因为stoi转换的结果在uint8_t的范围内进行分配。此外,由于uint8_t是一个unsigned值,因此更适合使用stoul。尽管强制转换为(uint8_t)的C样式有效,但最好使用static_cast<uint8_t>(...)(尽管两者都提供相同的结果)。最后,由于<< hex1 ...运算符期望一个<<(或int)值,因此您尝试输出unsigned的尝试将始终失败。

将所有这些部分放在一起,您可以重新制作read_csv()以将文件名作为参数打开,而不是对函数中的文件名进行硬编码(不要这样做),并执行类似的操作:

int read_csv (const string& name)
{
    string line;
    ifstream fin (name);

    while (getline (fin, line)) {           /* read entire line into line */
        stringstream ss (line);             /* create stringstream from line */
        string field;                       /* string to hold each field */
        cout << "line: " << line << '\n';
        while (getline (ss, field, ',')) {  /* read each hex value from line */
            uint64_t tmp = stoul (field, 0, 0); /* convert to uint64_t */
            if (tmp <= UINT8_MAX) {         /* validate in range of uint8_t */
                uint8_t hex1 = static_cast<uint8_t>(tmp);   /* store uint8_t */
                /* output with cast to unsigned for << */
                cout << "  " << field << " -> " <<
                        static_cast<uint32_t>(hex1) << '\n';
            }
        }
    }
    return 1;
}

注意,而不是cout中的大小写,您也可以在hex1之前加上数字+以强制进行促销,例如

cout << "  " << field << " -> " << +hex1 << '\n';

还请注意:使用0作为stoul中的基数,会自动检测到数字基数:如果前缀为 0 ,基数为八进制,如果前缀为 0x 0X ,则基数为十六进制,否则基数为十进制。

使用该功能的简短示例可能是:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdint>

using namespace std;

int read_csv (const string& name)
{
    string line;
    ifstream fin (name);

    while (getline (fin, line)) {           /* read entire line into line */
        stringstream ss (line);             /* create stringstream from line */
        string field;                       /* string to hold each field */
        cout << "line: " << line << '\n';
        while (getline (ss, field, ',')) {  /* read each hex value from line */
            uint64_t tmp = stoul (field, 0, 0); /* convert to uint64_t */
            if (tmp <= UINT8_MAX) {         /* validate in range of uint8_t */
                uint8_t hex1 = static_cast<uint8_t>(tmp);   /* store uint8_t */
                /* output with cast to unsigned for << */
                cout << "  " << field << " -> " <<
                        static_cast<uint32_t>(hex1) << '\n';
            }
        }
    }
    return 1;
}

int main (int argc, char **argv) {

    if (argc < 2) {
        cerr << "error: insufficient input\n" <<
                "usage: " << argv[0] << " <file>\n";
        return 1;
    }

    read_csv (argv[1]);
}

注意:通常鼓励使用using namespace std;,因此尽管它可以简化简短示例程序的键入,但通常您希望避免在每个示例程序中都包含整个std源文件(尤其是避免将其包含在头文件中)

示例输入文件

$ cat dat/hexcsv.csv
0xff,0x5f
0x02,0x00
0xff,0xaa

使用/输出示例

每个数字值都存储在uint8_t变量hex1中,然后以十进制输出。

$ ./bin/read_csv_uint8 dat/hexcsv.csv
line: 0xff,0x5f
  0xff -> 255
  0x5f -> 95
line: 0x02,0x00
  0x02 -> 2
  0x00 -> 0
line: 0xff,0xaa
  0xff -> 255
  0xaa -> 170