Конвертирование шестнадцатеричных строковых значений csv в uint8_t в c ++ - PullRequest
0 голосов
/ 29 мая 2019

Так что в настоящее время я могу читать некоторые шестнадцатеричные значения из CSV-файла, используя ifstream. Я могу прочитать значения и назначить их для строковой переменной. Но я хочу преобразовать их в 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 и когда я пытаюсь конвертировать, ничего не появляется.

Ответы [ 2 ]

0 голосов
/ 29 мая 2019

У вас есть ряд проблем с вашим кодом, но две основные проблемы связаны с вашим преобразованием в 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
0 голосов
/ 29 мая 2019

Вы не можете сохранить шестнадцатеричное значение, так как оно находится в переменной uint8_t, поэтому uint8_t A = 0x41 невозможно.Вместо этого вам нужно будет получить десятичный эквивалент шестнадцатеричного числа в uint8_t.

Попробуйтеиспользуя std::stoul

Получите десятичный эквивалент hex и получите hex назад от десятичных , когда вам это нужно.

...