正如标题中所提到的,我正在寻找一种方法将char *(来自argv)转换为uint16_t。命令行参数是端口号,因此不能是>到65535,也不是负面的。
目前,我这样做了(用-std = gnu99编译):
#include <stdbool.h>
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>
/*
* Converts a string to an unsigned int and stores the result in "res".
*/
bool str_to_uint(const char* str, unsigned long int* res) {
if (str[0] == '-')
return false;
char* first_wrong_character;
uintmax_t result = strtoumax(str, &first_wrong_character, 10);
if ((result == UINTMAX_MAX) && (errno == ERANGE))
return false; // Overflow)
if ((*str != '\0') && (*first_wrong_character != '\0'))
return false; // Not everything has been converted
if ((result == 0) && (str == first_wrong_character))
return false; // Nothing to convert
*res = result;
return true;
}
/*
* Converts a string to an uint16_t and stores the result in "res".
*/
bool str_to_uint16(const char* str, uint16_t* res) {
unsigned long uint;
if (!str_to_uint(str, &uint))
return false;
if (uint > UINT16_MAX)
return false;
*res = (uint16_t)uint;
return true;
}
我不确定这是最好的方法,所以如果你能告诉我什么是好方法?
答案 0 :(得分:5)
您可以使用能够在整数溢出(ERANGE
)的情况下返回错误的strtol(3)
,并简单地检查解析的整数是否与uint16_t
相比不是太大容量:
#include <stdint.h> /* fixed-width integer types */
#include <stdlib.h> /* strtol */
#include <stdbool.h>
#include <errno.h>
static bool
str_to_uint16(const char *str, uint16_t *res)
{
long int val = strtol(str, NULL, 10);
if (errno == ERANGE || val > UINT16_MAX || val < 0)
return false;
*res = (uint16_t) val;
return true;
}
修改强>
由于问题涉及C99,如果我包含更好的错误管理(感谢@nwellnhof和@chux),我会说下面的版本应该是正确的候选人:
#include <inttypes.h> /* strtoimax */
static bool
str_to_uint16(const char *str, uint16_t *res)
{
char *end;
errno = 0;
intmax_t val = strtoimax(str, &end, 10);
if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || *end != '\0')
return false;
*res = (uint16_t) val;
return true;
}
成功:
1981
65535
(UINT16_MAX
)它返回转换错误(按预期方式):
65536
(UINT16_MAX+1
)a1981
1981a
abcd
9223372036854775808
(INTMAX_MAX+1
:在这种情况下发生ERANGE
)-9223372036854775809
(INTMAX_MIN-1
:在这种情况下发生ERANGE
)答案 1 :(得分:5)
无需使用strtoumax
。我会选择更便携的strtol
。错误处理也可以简化为:
bool str_to_uint16(const char *str, uint16_t *res) {
char *end;
errno = 0;
long val = strtol(str, &end, 10);
if (errno || end == str || *end != '\0' || val < 0 || val >= 0x10000) {
return false;
}
*res = (uint16_t)val;
return true;
}