简体   繁体   English

使用 atoi 将命令行 arguments 转换为 int,仅返回输入的第一个数字

[英]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> .而不是TRUEFALSE ,您应该使用<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM