[英]using atoi to convert command-line arguments to int, is only returning the first digit entered
I have to use command line arguments to set up a map for a snake game for my uni assignment.我必须使用命令行 arguments 为我的大学作业设置一个 map 蛇游戏。 We were not specifically told to use
atoi
to help convert the command line argument from string to int
, However I thought the simple nature of atoi
would do the trick.我们没有被特别告知要使用
atoi
来帮助将命令行参数从 string 转换为int
,但是我认为atoi
的简单性质可以解决问题。 On testing I discovered it is only taking the first digit.在测试中我发现它只取第一位数字。
int main(int argc, char *argv[])
{
int isUserInput;
char arg1, arg2, arg3;
arg1 = argv[1][0];
arg2 = argv[2][0];
arg3 = argv[3][0];
isUserInput = checkUserArg(arg1, arg2, arg3);
int checkUserArg(char arg1, char arg2, char arg3)
{
int validation;
int rowMap, colMap, snakeLength;
rowMap = atoi(&arg1);
colMap = atoi(&arg2);
snakeLength = atoi(&arg3);
if ((rowMap < 5) || (colMap < 5) || (snakeLength < 3))
{
validation = FALSE;
}
else if ((rowMap >= 5) || (colMap >= 5) || (snakeLength >= 3))
{
if (snakeLength < colMap)
{
validation = TRUE;
}
else
{
validation = FALSE;
}
}
else
{
validation = FALSE;
}
return validation;
}
User has to enter 3 command line arguments ( ./file num1 num2 num3
).用户必须输入 3 命令行 arguments (
./file num1 num2 num3
)。 I used atoi
to convert the string command line arguments to int
, but while testing I printed the numbers back and it won't convert the second digit only the first, eg 1-9 works, but anything from 10 onwards only shows the first digit.我使用
atoi
将字符串命令行 arguments 转换为int
,但是在测试时我打印回数字并且它不会仅转换第一个数字的第二个数字,例如 1-9 有效,但是从 10 开始的任何内容都只显示第一个数字.
Any thoughts on why this is?关于为什么会这样的任何想法? Cheers.
干杯。
A single character is not a string.单个字符不是字符串。 A string is an array of characters with null termination at the end.
字符串是一个以 null 结尾的字符数组。
You should do something like this instead:你应该做这样的事情:
bool checkUserArg (const char* arg1, const char* arg2, const char* arg3);
const
since we shouldn't modify the args. const
因为我们不应该修改参数。 Now this function can call atoi
using the parameters directly.现在这个function可以直接用参数调用
atoi
了。
However atoi
is a broken function by design that should never be used, because it does not have well-defined error handling.然而
atoi
是一个损坏的 function 设计不应该被使用,因为它没有明确定义的错误处理。 Using it directly on argv
is dangerous.直接在
argv
上使用它是危险的。 You should always use strtol
instead of atoi
, it's a safer and more powerful function.您应该始终使用
strtol
而不是atoi
,它更安全、更强大 function。
Example:例子:
#include <stdlib.h>
#include <stdbool.h>
int main (int argc, char *argv[])
{
if(argc != 4)
{
// error handling!
}
if(checkUserArg(argv[1], argv[2], argv[3]) == false)
{
/* error handling */
}
...
bool checkUserArg (const char* arg1, const char* arg2, const char* arg3)
{
const char* endptr;
...
rowMap = strtol(arg1, &endptr, 10); // 10 for decimal base
if(endptr == arg1) // if these compare equal, the conversion failed
{
return false;
}
...
return true;
}
There are multiple problems in your code:您的代码中存在多个问题:
atoi
is only using the first digit because you explicitly extract the first digit and pass it as a char
. atoi
仅使用第一个数字,因为您明确提取第一个数字并将其作为char
传递。 The function call actually has undefined behavior as &arg1
is the address of a single char
, not that of a null terminator C string. function 调用实际上具有未定义的行为,因为
&arg1
是单个char
的地址,而不是 null 终止符 C 字符串的地址。
checkUserArg
converts the arguments using atoi
which has undefined behavior if the value converted exceeds the range of type int
. checkUserArg
使用atoi
转换 arguments,如果转换的值超出int
类型的范围,则 atoi 具有未定义的行为。 Using strtol
is recommended and allows for finer checks.建议使用
strtol
并允许进行更精细的检查。
checkUserArg
should return the converted values to the caller via pointer arguments. checkUserArg
应该通过指针 arguments 将转换后的值返回给调用者。
the second test in checkUserArg
is redundant: if the first test is false, then all 3 comparisons in the second test will be true. checkUserArg
中的第二个测试是多余的:如果第一个测试为假,那么第二个测试中的所有 3 个比较都为真。
instead of TRUE
and FALSE
, you should use definitions from <stdbool.h>
.而不是
TRUE
和FALSE
,您应该使用<stdbool.h>
中的定义。
Here is modified version:这是修改后的版本:
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
bool convertArg(const char *arg, int *vp) {
char *p;
long num;
errno = 0;
num = strtol(arg, &p, 10);
if (errno || p == arg || *p != '\0' || num < INT_MIN || num > INT_MAX) {
*vp = 0;
return false;
} else {
*vp = (int)num;
return true;
}
}
int main(int argc, char *argv[]) {
int rowMap, colMap, snakeLength;
if (argc != 4) {
fprintf(stderr, "program needs 3 arguments\n");
return 1;
}
if (!converArg(argv[1], &rowMap) || rowMap < 5) {
fprintf(stderr, "invalid rowMap argument\n");
return 1;
}
if (!converArg(argv[2], &colMap) || colMap < 5) {
fprintf(stderr, "invalid colMap argument\n");
return 1;
}
if (!converArg(argv[3], &snakeLength) || snakeLength < 3 || snakeLength >= colMap) {
fprintf(stderr, "invalid snakeLength argument\n");
return 1;
}
[...]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.