【问题标题】:How to read command-line arguments as integers instead of strings?如何将命令行参数读取为整数而不是字符串?
【发布时间】:2017-02-12 21:01:52
【问题描述】:

对不起我的问题,我知道有很多类似的,但我没有找到任何简单的足以帮助我的东西。

我已经开始用 C 编写代码并尝试解决一个简单的练习:从命令行读取一个整数数组,使用函数 array_sum 对元素求和并打印结果。 (输入 3 个元素的示例数组:3 0 1 2)

int array_sum(int *array,  size_t size);
int main(int argc, char **argv){
    int sum=array_sum(argv, argc);
    printf("array_sum: %i\n", sum);
    return 0;
}

我的问题是 argv 是一个字符数组,而函数需要一个整数数组。 我应该在新的 int 数组中一个一个地转换元素吗?还有更好的方法吗?

【问题讨论】:

  • Should I convert elements one by one in a new int array? 是的。
  • @adev 3 0 1 2 不是四个元素的数组吗?
  • @VladfromMoscow 第一个元素是数组的长度

标签: c argv


【解决方案1】:

argv 是一个指向 C 字符串的指针数组。您需要首先将字符串转换为整数。你可以这样做:

int array_sum(int *array,  size_t size);
int main(int argc, char **argv){
    int *num_arr = malloc((argc - 1) * sizeof *num_arr);

    for (int i = 0; i < argc - 1; ++i)
      num_arr[i] = atoi(argv[i+1]);

    int sum = array_sum(num_arr, argc - 1);
    printf("array_sum: %i\n", sum);

    free(num_arr);
    return 0;
}

使main 中的代码更短的唯一方法是将转换循环移动到返回malloced 指针的单独函数中。

【讨论】:

  • 谢谢,不需要使用 malloc,因为我知道数组的长度
  • @adev - 如果你引用argc,那么数组长度是可变的,你肯定需要malloc。虽然如果argc 不是“太大”,您可以使用可变长度数组。
  • array_sum(argv, argc) 的调用无法编译。大概你打算array_sum(num_arr, (size_t)argc-1)
  • @Peter - 我做到了,谢谢。在正确完成示例之前分心了。
【解决方案2】:

在您的代码中,char *argv[] 是由命令行提供的char* 指针数组。为了转换提供的数字,您可以使用以下内容:

  • atoi(),将字符串参数转换为整数类型。
  • strtol(),将字符串的初始部分转换为long int,给定一个基数。
  • 来自 C99 的其他特殊功能,其中很多在 post 中进行了描述。

由于atoi() 没有错误检查,最好使用strtol(),它允许进行广泛的错误检查。

您应该将这些转换后的数字存储在动态分配的int* 指针中,这需要使用@StoryTeller 在他的回答中建议的malloc() 在堆上分配。您也可以只在堆栈上声明一个数组,例如int arr[n]。当您想在函数中返回此数组时会出现问题,这是不可能的。在这种情况下使用指针将为抽象提供更大的灵活性。

malloc()在堆上分配内存块,并返回一个void*指向它的指针。

注意: malloc() 应始终选中,因为它可以返回 NULL。最后你还需要free()这个指针。

下面是一些示例代码:

#include <stdio.h>
#include <stdlib.h>

#define BASE 10

/* Guessed that your function would look like this */
int array_sum(int *array, size_t size) {
    int sum = 0;

    for (size_t i = 0; i < size; i++) {
        sum += array[i];
    }

    return sum;
}

int main(int argc, char *argv[]) {
    int *arr = NULL;
    char *endptr = NULL;
    int check, sum;
    size_t ndigits = (size_t)argc-1;

    /* allocate pointer */
    arr = malloc(ndigits * sizeof *arr);
    if (arr == NULL) {
        fprintf(stderr, "Cannot %zu spaces for integers\n", ndigits);
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < ndigits; i++) {

        /* sufficient checking for strtol(), more can possibly be added here */
        check = strtol(argv[i+1], &endptr, BASE);
        if (endptr != argv[i+1] && *endptr == '\0') {
            arr[i] = check;
        }
    }

    sum = array_sum(arr, ndigits);

    printf("array_sum: %d\n", sum);

    /* pointer is free'd */
    free(arr);
    arr = NULL;

    return 0;
}

示例输入:

$ gcc -Wall -Wextra -std=c99 -o sumcommands sumcommmands.c
$ ./sumcommands 3 2 1

输出:

array_sum: 6

注意:您可以在Man page 上对strtol() 使用更多错误检查。

【讨论】:

    【解决方案3】:

    为什么需要将int 数组作为参数传递给函数?当您可以简单地执行此操作时,无需创建额外的 int 数组:

    int array_sum(char **argv, int argc){
      int sum = 0;
      for(int i = 0;i < argc - 1;i++){
        sum += atoi(argv[i])
      }
      return sum;
    }
    

    【讨论】:

    • 没错,但只有在可以放宽使用array_sum的要求的情况下才可行
    • 是的@StoryTeller,我必须使用提供的功能。我认为锻炼的目的是连接
    【解决方案4】:

    您可以使用 atoi() 函数将 char ** 数组转换为 **int 。我在这里看到的是您输入的每个整数都转换为 string 而不是 char

    【讨论】:

      猜你喜欢
      • 2012-11-29
      • 1970-01-01
      • 2021-07-17
      • 2011-04-03
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      相关资源
      最近更新 更多