您的代码存在许多问题,但有两个主要问题与您转换为uint8_t 有关。尝试使用getline (fin, line, ','); 读取.csv 文件的一个普遍问题是您无法跟踪每行中存在的值的数量。使用',' 分隔符读取将导致getline 跳过行尾并简单地读取下一个值,直到遇到EOF。最好用getline (fin, line); 将整行读入line,然后从line 创建一个stringstream,允许您读取行中的值,直到到达字符串流的末尾(将值转换限制为每一行)。
将值存储为uint8_t 的主要障碍是您未能验证在进行分配之前stoi 转换的结果在uint8_t 的范围内。此外,由于uint8_t 是unsigned 值,因此使用stoul 更合适。虽然 C 样式转换为 (uint8_t) 是有效的,但最好使用 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;
}
注意:您也可以在 hex1 前面加上数字 + 来强制提升,而不是在 cout 中使用大小写,例如
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