Конвертировать из массива char в 16-битные целые числа и 32-битные целые числа без знака
Я работаю над некоторым встроенным C для разработанной мной платы, но мой C немного ржавый!
Я хочу сделать некоторые преобразования из массива char в различные целочисленные типы.
Первый пример:
[input] " 1234" (note the space before the 1)
[convert to] (int16_t) 1234
Второй пример:
[input] "-1234"
[convert to] (int16_t) -1234
Третий пример:
[input] "2017061234"
[convert to] (uint32_t) 2017061234
Я пытался поиграть с atoi(), но, похоже, я не получил ожидаемого результата. Какие-либо предложения?
[РЕДАКТИРОВАТЬ]
Это код для конверсий:
char *c_sensor_id = "0061176056";
char *c_reading1 = " 3630";
char *c_reading2 = "-24.30";
uint32_t sensor_id = atoi(c_sensor_id); // comes out as 536880136
uint16_t reading1 = atoi(c_reading1); // comes out as 9224
uint16_t reading2 = atoi(c_reading2); // comes out as 9224
3 ответа
Пара вещей:
- Никогда не используйте
atoi
семейство функций, так как они не обрабатывают ошибки и могут аварийно завершить работу, если формат ввода плохой. Вместо этого используйтеstrtol
семейство функций. - Любая из этих функций несколько ресурсоемка для ограниченных в ресурсах микроконтроллеров. Возможно, вам придется выкатить свою собственную версию
strtol
,
Пример:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
int main()
{
const char* c_sensor_id = "0061176056";
const char* c_reading1 = " 3630";
const char* c_reading2 = "-1234";
c_reading1++; // fix the weird string format
uint32_t sensor_id = (uint32_t)strtoul(c_sensor_id, NULL, 10);
uint16_t reading1 = (uint16_t)strtoul(c_reading1, NULL, 10);
int16_t reading2 = (int16_t) strtol (c_reading2, NULL, 10);
printf("%"PRIu32 "\n", sensor_id);
printf("%"PRIu16 "\n", reading1);
printf("%"PRId16 "\n", reading2);
}
Выход:
61176056
3630
-1234
Наблюдаемое поведение очень удивительно. Я предлагаю написать функции для преобразования строк символов в int32_t
а также uint32_t
и использовать их вместо atoi()
:
uint32_t atou32(const char *s) {
uint32_t v = 0;
while (*s == ' ')
s++;
while (*s >= '0' && *s <= '9')
v = v * 10 + *s++ - '0';
return v;
}
int32_t atos32(const char *s) {
while (*s == ' ')
s++;
return (*s == '-') ? -atou32(s + 1) : atou32(s);
}
Там нет обработки ошибок, а +
даже не поддерживается, но, по крайней мере, значение преобразуется в 32 бита, что не относится к atoi()
если тип int
только 16 бит на вашей целевой платформе.
Попробуйте инициализировать ваши строки следующим образом:
char c_sensor_id[] = "0061176056";
char c_reading1[] = " 3630";
char c_reading2[] = "-24.30";