如何获取 argv 并将其转换为 uint16_t

How to take a argv and convert it to uint16_t

我需要获取一个参数 (argv[2]) 并将其转换为 uint16_t 类型。我怎么能得到这个? 我在参数中放置了一个端口,所以我需要在 uint16_t 中进行转换,我试过这个:

uint16_t PORT;

PORT = argv[2];

但是当我这样做时

servaddr.sin_port = htons(PORT) 

我明白了

warning: assignment makes integer from pointer without a cast

您可以通过 atoi() 函数将 char * 转换为 int(因此,转换为 uint16_t):

#include <stdlib.h>

[...]

uint16_t PORT = atoi(argv[2]);

你需要使用the strtoul() function,一个快速的方法是这样的:

errno = 0;
uint16_t PORT = strtoul(argv[2], NULL, 0);
if ( errno != 0 )
{
    //invalid input
}

一种更稳健的方法是使用中间 unsigned long 值并检查它是否包含适合 16 位端口的值。

有关更多详细信息,请参阅

永远不要使用 atoi()。它无法 return 任何错误条件,如果您向它传递一些无效输入,它会调用未定义的行为。

How to take a argv and convert it to uint16_t (?)

argv[i] 可能指向一个 字符串 。然后任务是将该字符串转换为 uint16_t.

OP 的代码失败,因为下面更像是获取字符串的 地址 并将其转换为可能被截断的 16 位值。

uint16_t PORT;
PORT = argv[2]; // poor code

确保有效argv[2]

int main(int argc, char *argv[]) {
  if (argc <= 2) {
    fprintf(stderr, "argv[2] missing.\n");
    return EXIT_FAILURE;
  }
  ...

处理非数字输入

"abc""123abc""-123"""" "" 123 "、[=24 等情况下应该发生什么=]、"123456""123456789012345678901234567890""0x123""-0""0.0" 等?

通常的目标是慷慨地允许领先的白色-space 和尾随的 WS(即使这样的 WS 在 argv[] 中并不常见)。抱怨超出范围 [0...65535] 的值。抱怨其他非整数数字,非白色-space字符。

strtoul() 是一个良好的开端,其定义明确的错误处理。

当输入格式不正确或 int 为 16 位时,

atoi() 无法很好地转换为 uint16_t

我不喜欢 strtoul() 的一个属性是 '-' 在转换后应用,因此 "-1" 可以输入,returns ULONG_MAX。我宁愿将其检测为错误。由于 long 的范围总是比 uint16_t 宽,如果代码应该将负值检测为错误,我建议 strtol()

样本

  char *endptr;
  errno = 0; 
  long value = strtol(argv[2], &endptr, 0);

  if (errno) { // This test not certainly needed here as later test will catch
    perror("argv[2] error");
    return EXIT_FAILURE;
  }

  if (argv[2] == endptr) { // No conversion happened
    fprintf(stderr, "argv[2] <%s> non-numeric\n", argv[2]);
    return EXIT_FAILURE;
  }

  if (value < 0 || value > UINT16_MAX) {
    fprintf(stderr, "argv[2] %ld outside uint16_t range\n", value);
    return EXIT_FAILURE;
  }

  while (isspace((unsigned char) *endptr)) {
    endptr++;
  }
  if (*endptr) {
    fprintf(stderr, "argv[2] <%s> trailing non-numeric text\n", argv[2]);
    return EXIT_FAILURE;
  }

  PORT = (uint16_t) value;  // Cast to quiet conversion warning

  printf("argv[2] --> %u success\n", PORT);
  return EXIT_SUCCESS;
}     

这个冗长的代码最好作为辅助函数合并,而不是为每个 字符串 uint16_t 复制。但我怀疑 OP 稍后会使用这些功能。