我有这段代码:
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的第一个值呢?
感谢您的帮助!
答案 0 :(得分:1)
我是C的新手,指向数组的指针/指针的概念仍然让我感到困惑。
在C字符串中,由空终止('\0'
)字符数组表示。让我们考虑以下示例:
char str[] = "Hello world!"
字符在内存中是连续的,str
将decay用于指向字符串第一个元素的字符指针(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;
}
argv
是一个字符串数组,因此argv [x]指向一个字符串。 atoi ()
接受ASCII字符串作为输入并返回int
。
奖金:这仍然有点不安全。尝试运行此程序而不传递参数,看看会发生什么。
此外,您必须查看documentation for strtol (),这是一种安全的方法。