【问题标题】:Storing user variable and printing in C [duplicate]在C中存储用户变量和打印[重复]
【发布时间】:2021-07-07 11:31:45
【问题描述】:

如果这是一个相对简单的问题,我深表歉意。在学习了 Python 之后,我正在尝试掌握 C 编程。我正在尝试读取像./myprogram 8 这样的命令行参数,并能够访问该8。我已经设法通过直接访问像printf("%s\n", argv[1]); 这样的用户输入来让它工作 但我正在努力将其存储为变量。下面的代码运行,但它根本不打印8

#include <stdio.h>

int main(int argc, char* argv[]) {
    int UserInput1;

    UserInput1 = argv[1];
    printf("%s\n", UserInput1);

    return 0;
}

感谢所有帮助,并提前感谢您抽出宝贵时间

【问题讨论】:

  • 正如声明所说,argv[1] 是 char-array 类型。因此,如果不执行一些转换(例如strtol),就无法将其分配给int UserInput1。此外,printf 格式说明符 %s 需要 char * 参数,但您传递了 int 参数。
  • @Jeremiah Longlow 注意这篇文章没有提出特定的问题。考虑添加一个以帮助关注问题。

标签: c variables type-conversion printf command-line-arguments


【解决方案1】:

下面的代码运行,但它根本不打印 8。

这里要学习的第一件事是启用所有编译器警告。这可以节省您(和我们)的时间。

一个良好的、启用良好的编译器,带有类似的报告

UserInput1 = argv[1];
// warning: assignment to 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion]

printf("%s\n", UserInput1);
// warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat=]

代码正在尝试更改指向int 的指针。而是使用函数将argv[1] 指向的字符串读取为十进制文本并转换为整数。


读取命令行参数...并能够访问

argv[1] 值得进行一些测试。并非所有字符串都表示整数。

它存在吗?

有要解析的字符串吗?

if (argc < 2) {
  puts("argv[1] missing");
}

从字符串转换为整数

我们要限制范围吗? “123456789012345678901234567890”可以吗?

让我们假设int 范围。

遗憾的是,C 没有到 int 的强大转换函数,但可以为更广泛的类型提供它们。

errno = 0;
char *endptr;
long number = strtol(argv[1], &endptr, 10);

if (argv[1] == endptr) {
  puts("No conversion");
} else if (errno == ERANGE) {
  puts("Outside long range");
} else if (number < INT_MIN || number > INT_MAX) {
  errno = ERANGE;
  puts("Outside int range");
} else if (*endptr)) {
  puts("Extra text after the number");
} else {
  int UserInput1 = (int) number;
  printf("Success %d\n", UserInput1);
}

【讨论】:

    【解决方案2】:

    您也可以将 UserInput 变量的类型从 int 更改为 char

    【讨论】:

    • [...] 读取像 ./myprogram 8 这样的命令行参数,并且能够访问那个 8 [...]
    【解决方案3】:

    通过命令行传递的参数作为字符串 (char*) 传递。要将其存储为 int 变量,您需要将其转换为整数。

    int main(int argc, char* argv[]){
        if(argc < 2){
            fprintf(stderr, "Pass an integer through the command line\n./%s 8\n", argv[0]);
            return -1;
        }
        long intarg = strtol(argv[1], NULL, 10);
        printf("%ld\n",intarg);
    }
    

    您还可以检查用户是否通过 argc 传递参数,即参数的数量。

    【讨论】:

    • 严格来说应该是strtol(argv[1], NULL, 10)
    • 这样我们成功地防止了对strtol 的任何错误检查,使其不比atoi 好。当然,应该使用 endptr arg,因为它是一个双指针,所以应该在 strtol 函数返回后检查它指向的原始指针与第一个参数的差异。如果没有区别,则 argv[1] 不包含数字文字。如果不同,至少argv[1] 的前几个字符是数字。如果argv[1] 完全是数字,则原始指针应指向空格或\0
    • 是的,应该进行错误检查。但是在这种特定情况下,因为我正在打印 intarg 并且可能在任何情况下都会检查返回值,所以感觉没有必要。如果它没有打印我要求的值,那么我们总是可以知道它失败了。但最好指出来。
    • @Jabberwocky strtol(argv[1], NULL, 10);strtol(argv[1], 0, 10); 都可以。风格问题,而不是“应该”的问题。
    • @pqans “防止对 strtol 进行任何错误检查,使其不比 atoi 好”。 strtol()atoi() 好,因为 atoi() 是溢出的 UB。 strtol() 定义明确。 endptr 的其余部分很好。
    猜你喜欢
    • 2012-08-14
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 2021-07-15
    • 2015-02-11
    • 2018-12-23
    • 2023-01-22
    • 1970-01-01
    相关资源
    最近更新 更多