如何在C的主函数中将参数从char转换为int?

时间:2017-08-15 06:00:16

标签: c arrays pointers

我有这段代码:

int main(int argc, char *argv[]) {
    int num = *argv[1];

当我在终端中使用参数运行该功能时:例如,如果我要拨打./main 17,我需要num = 17。但是,使用此代码,num = 49(ASCII值为1,因为argv是一个字符数组)。我怎么能把它作为一个int来读num = 17?使用代码,我可以让它将参数转换为int,但它仍然只能读取/转换第一个值(1而不是17)。

我是C的新手,指向数组的指针/指针的概念仍然让我感到困惑。 *argv[1]不应该返回数组中第二个char的值吗?为什么它会读取数组中第二个char的第一个值呢?

感谢您的帮助!

4 个答案:

答案 0 :(得分:1)

  

我是C的新手,指向数组的指针/指针的概念仍然让我感到困惑。

在C字符串中,由空终止('\0')字符数组表示。让我们考虑以下示例:

char str[] = "Hello world!"

字符在内存中是连续的,strdecay用于指向字符串第一个元素的字符指针(char*)。 &所采用的第一个元素的地址(&str[0])也将指向该地址:

| . | . | . | H | e | l | l | o |   | W | o | r | l | d | ! | \0 | . | . | . |
              ^                                               ^
             str                                        null terminator
  

不应该*argv[1]返回数组中第二个字符的值吗?

首先,argv是一个字符指针数组char* argv[],因此它可以被解释为字符串数组。

第一个字符串argv[0]是程序本身的程序名称,之后传递的参数即将来临:

argv[0] contains a pointer to the string:    "program name"
argv[1] contains a pointer to the argument:  "17"

如果您使用argv[1]取消引用*,则会获得该地址的第一个字符,此处1在Ascii代码中为49位小数。例如:

    p             r        ("program name")
    ^             ^
 argv[0]    (argv[0] + 1)
--------------------------------------------
    1             7        ("17")
    ^             ^
 argv[1]    (argv[1] + 1)
  

我如何才能将num = 17视为int

使用argc检查传递的参数数量,其中也包含程序名称(read here more about argc and argv)。如果有2个,您可以使用strtol() to convert argv[1]来表示整数。使用strtol()而不是atoi(),因为atoi()被认为已弃用,因为没有可用的错误检查。如果atoi()失败,则只返回0作为整数而不是strtol(),它将第二个参数和全局errno变量设置为特定值。

followig代码将使用strtol()设置第二个参数的指针来检查转换错误。还有溢出和下溢错误来检查like it's described here on SO。此外,如果要将long变量存储到int变量中,则必须检查返回的int值是否适合#include <stdio.h> #include <stdlib.h> int main (int argc, char* argv[]) { /* At least 1 argument passed? */ if (argc >= 2) { char* endptr; long num = strtol(argv[1], &endptr, 10); /* Were characters consumed? */ if (argv[1] != endptr) { printf("Entered number: %ld\n", num); } else { printf("Entered argument was not a number!\n"); } } else { printf("Usage: %s [number]!\n", argv[0]); } return 0; } 变量。但为了简单起见,我已将其排除在外:

from tensorflow.python.ops import gen_logging_ops as _gen_logging_ops

答案 1 :(得分:1)

  

如何将参数从char转换为int?

可以通过简单的演员表(促销)来完成,但这不是你的情况。

在你的情况下argv[1]指向char的指针数组(你可以使用this来分解复杂的C声明),这意味着char*是数组中的第二个元素,即数组中的第二个*argv[1],意味着char是数组中第二个char*中的第一个argv

为了更清楚地显示,假设{"good", "day"}拥有2个字符串argv[1]"day"*argv[1]'d'char(请注意类型的差异 - char*char!)

现在,您的输入字符串中只有'1',即"int"。它的ascii确实是49,所以为了获得atoi值,你应该像这样使用int i = atoi("17");

atoi

但是 const char *获得17,因此向char发送atoi是不错的。这意味着argv[1]应该*argv[1]而不是int main(int argc, char *argv[]) { int num = atoi(argv[1]); // not : int num = *argv[1]; --> simple promotion that would take the ascii value of '1' :( // and not: int num = atoi(*argv[1]); --> argument is char

atoi

注意:long int strtol(const char *str, char **endptr, int base)被认为已过时,因此您可能希望使用atoi,但对于一个简单示例,我更喜欢使用{{1}}

答案 2 :(得分:1)

  

不应该 * argv [1] 返回数组中第二个字符的值吗?

看签名:

int main(int argc, char *argv[])

此处,argv指针[])到*数组char)。所以argv[1]是此数组中的第二个指针。它指向命令行中给出的 first 参数。 argv[0]保留给程序本身的名称。虽然这也可以是任何字符串,但程序的名称按照惯例放在那里 (shell执行此操作)。

如果您只是取消引用指针,则会获得它指向的值,因此*argv[1]将为您提供第一个参数的第一个字符。你可以把它写成argv[1][0],它们是等价的。要获取第一个参数的第二个字符,您需要编写argv[1][1]

这里要注意的一件重要事情是永远不能将数组传递给C中的函数。上面的签名显示了一个数组类型,但是C会自动将数组类型调整为函数声明中的指针类型。这导致以下声明:

int main(int argc, char **argv)

C中的索引运算符([])按指针算术运算:a[x]相当于*(a+x)。数组的标识符被评估为指向大多数上下文中第一个数组元素的指针(例外包括sizeof运算符)。因此,无论a是数组还是指针,索引的工作方式都相同。这就是为什么你可以将argv与数组非常相似。

解决“核心”问题:argv中总是有字符串,并且您想要数字输入,这意味着您必须将字符串转换为数字。已有功能这样做。一个非常简单的是atoi(),您可以像这样使用它:

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

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        // use program name in argv[0] for error message:
        fprintf(stderr, "Usage: %s [number]\n", argv[0]);
        return EXIT_FAILURE;
    }
    int i = atoi(argv[1]);
    printf("Argument is %d.\n", i);
    return EXIT_SUCCESS;
}

如果参数无法解析为数字,并且溢出您的0,则会为您提供一些不确定的值,这将为您提供int。如果您必须确保参数 是有效整数,则可以使用strtol()代替(注意它转换为long,而不是int,并且它可以处理不同的基数,所以我们必须通过10进行十进制):

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

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        // use program name in argv[0] for error message:
        fprintf(stderr, "Usage: %s [number]\n", argv[0]);
        return EXIT_FAILURE;
    }

    errno = 0;    // reset error number
    char *endptr; // this will point to the first character not read by strtol
    long i = strtol(argv[1], &endptr, 10);
    if (errno == ERANGE)
    {
        fprintf(stderr, "This number is too small or too large.\n");
        return EXIT_FAILURE;
    }
    else if (endptr == argv[1])
    {
        // no character was converted. This also catches the case of an empty argument
        fprintf(stderr, "The argument was not a number.\n");
        return EXIT_FAILURE;
    }
    else if (*endptr)
    {
        // endptr doesn't point to NUL, so there were characters not converted
        fprintf(stderr, "Unexpected characters in number.\n");
        return EXIT_FAILURE;
    }

    printf("You entered %ld.\n", i);
    return EXIT_SUCCESS;
}

答案 3 :(得分:-1)

这是你想做的事情:

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

int main (int argc, char *argv []) {
    int num = atoi (argv[1]);
    printf ("Here's what you gave me: %d", num);
    return 0;
}

这里是documentation for atoi ()

argv是一个字符串数组,因此argv [x]指向一个字符串。 atoi ()接受ASCII字符串作为输入并返回int

奖金:这仍然有点不安全。尝试运行此程序而不传递参数,看看会发生什么。

此外,您必须查看documentation for strtol (),这是一种安全的方法。