如标题中所述,我正在寻找一种方法将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;
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是最好的方法,所以如果你能告诉我什么是好方法?
没有必要使用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;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用strtol(3)能够在整数溢出(ERANGE)的情况下返回错误,并简单地检查解析的整数是否与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;
}
Run Code Online (Sandbox Code Playgroud)
编辑
由于问题涉及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;
}
Run Code Online (Sandbox Code Playgroud)
它取得了成功:
198165535(UINT16_MAX)它返回转换错误(如预期):
65536(UINT16_MAX+1)a19811981aabcd9223372036854775808(INTMAX_MAX+1:在这种情况下ERANGE发生)-9223372036854775809(INTMAX_MIN-1:在这种情况下ERANGE发生)| 归档时间: |
|
| 查看次数: |
10470 次 |
| 最近记录: |