У вас есть ряд проблем с вашим кодом, но две основные проблемы связаны с вашим преобразованием в uint8_t
.Общая проблема с попыткой чтения файла .csv
с getline (fin, line, ',');
заключается в том, что у вас нет возможности отследить количество значений, присутствующих в каждой строке.Чтение с разделителем ','
приведет к тому, что getline
пропустит конец строки и просто прочитает следующее значение, пока не встретится EOF
.Лучше прочитать всю строку в line
с помощью getline (fin, line);
, а затем создать stringstream
из line
, позволяя вам читать значение в строке до тех пор, пока не будет достигнут конец потока строки (ограничивая преобразование значений теми, которые вкаждая строка).
Основным препятствием для сохранения значений как 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;
}
note: вместо префикса 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;
, как правило, рекомендуется, поэтому, хотя это может облегчить набор текста для коротких примеров программ, вы, как правило, хотите избегать включения enУтомляет 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