在 C++ 中将 csv 读取的十六进制字符串值转换为 uint8_t
Converting csv read hex string values to uint8_t in c++
所以我目前能够使用 ifstream 从 csv 文件中读取一些十六进制值。我能够读取这些值并将它们分配给一个字符串变量。但我想将它们转换为 uint8_t
值。所以基本上我想要这样的东西 uint8_t A = 0x41;
我试过 atoi
、 stoi
和 strtol
但我似乎没有得到任何有效的输出。(我可能用错了)
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
当我尝试转换时,什么也没有显示。
您不能存储 hex 值,因为它在 uint8_t
变量中,所以 uint8_t A = 0x41
不是可能的。相反,您将必须获得 decimal 等效于 hex数变成uint8_t
.
尝试使用 std::stoul
得到十进制相当于十六进制 并从 decimal 返回 hex when你需要它。
您的代码有很多问题,但有两个主要问题与您向 uint8_t
的转换有关。尝试使用 getline (fin, line, ',');
读取 .csv
文件的一个普遍问题是您无法跟踪每一行中存在的值的数量。使用 ','
分隔符读取将导致 getline
跳过 line-ending 并简单读取下一个值,直到遇到 EOF
。最好用 getline (fin, line);
将整行读入 line
,然后从 line
创建一个 stringstream
,这样您就可以读取行中的值,直到到达字符串流的末尾(将值转换限制为每行内的值)。
将值存储为 uint8_t
的主要障碍是 validate 失败 stoi
转换的结果在 uint8_t
在进行分配之前。此外,由于 uint8_t
是 unsigned
值,因此使用 stoul
更合适。虽然 C-style 转换为 (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;
}
注意: 而不是 cout
内的大小写,你也可以在 hex1
之前加上数字 +
来强制升级,例如
cout << " " << field << " -> " << +hex1 << '\n';
另请注意:在stoul
中使用0
作为基数,则数字基数为auto-detected:如果前缀为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
例子Use/Output
每个数值在以十进制输出之前都存储在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
所以我目前能够使用 ifstream 从 csv 文件中读取一些十六进制值。我能够读取这些值并将它们分配给一个字符串变量。但我想将它们转换为 uint8_t
值。所以基本上我想要这样的东西 uint8_t A = 0x41;
我试过 atoi
、 stoi
和 strtol
但我似乎没有得到任何有效的输出。(我可能用错了)
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
当我尝试转换时,什么也没有显示。
您不能存储 hex 值,因为它在 uint8_t
变量中,所以 uint8_t A = 0x41
不是可能的。相反,您将必须获得 decimal 等效于 hex数变成uint8_t
.
尝试使用 std::stoul
得到十进制相当于十六进制 并从 decimal 返回 hex when你需要它。
您的代码有很多问题,但有两个主要问题与您向 uint8_t
的转换有关。尝试使用 getline (fin, line, ',');
读取 .csv
文件的一个普遍问题是您无法跟踪每一行中存在的值的数量。使用 ','
分隔符读取将导致 getline
跳过 line-ending 并简单读取下一个值,直到遇到 EOF
。最好用 getline (fin, line);
将整行读入 line
,然后从 line
创建一个 stringstream
,这样您就可以读取行中的值,直到到达字符串流的末尾(将值转换限制为每行内的值)。
将值存储为 uint8_t
的主要障碍是 validate 失败 stoi
转换的结果在 uint8_t
在进行分配之前。此外,由于 uint8_t
是 unsigned
值,因此使用 stoul
更合适。虽然 C-style 转换为 (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;
}
注意: 而不是 cout
内的大小写,你也可以在 hex1
之前加上数字 +
来强制升级,例如
cout << " " << field << " -> " << +hex1 << '\n';
另请注意:在stoul
中使用0
作为基数,则数字基数为auto-detected:如果前缀为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
例子Use/Output
每个数值在以十进制输出之前都存储在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