【问题标题】:Checking command line inputs for errors in C++在 C++ 中检查命令行输入是否有错误
【发布时间】:2013-11-23 23:17:36
【问题描述】:

我刚刚让这个程序工作,但改变了一些东西,现在我的错误处理变得疯狂了。我几乎要把我的头撞到墙上,试图让它恢复原状,但无论我现在做什么,它都会吐出一个错误。

该程序应该使用命令行参数来定义行和列,并在此基础上创建一个动态二维数组。格式为“-rows (number) -columns (number)”。在提交作业之前,我尝试添加更多案例,但我必须在其他地方更改了一些逻辑,因为即使在我删除了新部分之后,无论我输入什么,它仍然无法正常工作。在这一点上,我想我只需要一双新鲜的眼睛来指引我正确的方向。

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

// Checks if the user input the correct number of arguments.
// If so, checks if they were input corecctly. If so, it assigns
// the user input values to rows/columns, and if not, prints
// an error message.
     if(argc == 5) {
            for(int i = 1; i < argc; i++) {
                    rows = getArg(argc, argv, i, compare1);
            }
            for(int i = 1; i < argc; i++) {
                    columns = getArg(argc, argv, i, compare2);
            }
    } else {
           printError(argv);
    }

这是main的相关部分。

以下是检查错误所涉及的功能。我实际上一直在研究的是 getArg,所以我假设这是逻辑失败的地方,但为了清楚起见,我包含了另一个必要的函数。

// Description: Checks if user input was valid
// Parameters: Command line arguments, int i from the for
// loop used to run this check on all command line arguments
// in main, and an array of chars used to compare the user's
// inputs to "-rows" or "-columns"
// Return value: If user input was valid, returns an int
// If not, exits program.

int getArg(int argc, char* argv[], int i, char compare[]) {

    int arg;
    if (strcmp(argv[i], compare) == 0) {
           if (isInt((i + 1), argv)) {
                    arg = atoi(argv[i + 1]);
            } else {
                    printError(argv);
            }
    } else {
            printError(argv);
    }

    return arg;
}

// Description: Checks user input for valid integers
// Parameters: Command line arguments
// Return value: Returns true if input is an int;
// false if not.

bool isInt(int argc, char* argv[]) {
    bool isInt;

    for (int j = 0; j < strlen(argv[argc]); j++) {  //For loop runs through each char in the array at argc
            if (isdigit(argv[argc][j])) {   // Checks to see if char is an integer
                    isInt = true;
                    return isInt;
            } else {
                    isInt = false; // If there is ever a non-integer character, exit loop and return false
                    return isInt;
            }
    }

}

【问题讨论】:

  • "我刚刚让这个程序工作,但改变了一些东西,现在......我几乎把我的头撞到墙上,试图让它恢复原来的样子,但不管我现在所做的,它吐出一个错误。” - 听起来像是一个很好的源代码控制用例!
  • 您是否尝试过使用调试器?还是打印调试信息来追踪问题出在哪里?
  • 为什么不boost::program_options?

标签: c++ command-line-arguments


【解决方案1】:

main 中的第一个 for 循环在匹配“-rows”后继续扫描参数列表。循环进行以下调用(我假设 compare1="-rows" 因为你没有提到它):

i=1: getArg(argc=5, argv={"a.out", "-rows", "2", "-columns", "3"}, i=1, compare="-rows") 
    returns 2
i=2: getArg(argc=5, argv={"a.out", "-rows", "2", "-columns", "3"}, i=2, compare="-rows")
    calls printError(argv) because strcmp("2", "-rows") is nonzero

另外,正如 Abhishek 所提到的,isInt 只检查字符串的第一个字符,因为您在 isInt = true 分支中返回。

【讨论】:

  • 这让我走上了正轨,谢谢。我把它弄坏了是件好事,因为它似乎一开始就不应该起作用。我完全放弃了 for 循环,并在其位置添加了一些 if/else 逻辑,并且能够在一个函数中同时定义行和列,因此它更加简洁。
【解决方案2】:

我可以发现的一个可能错误是您在 isInt() 函数中的循环不正确。

在第一次迭代后,您总是会退出函数。

【讨论】:

    【解决方案3】:

    很高兴你得到了答案,但这是一个非常容易使用的问题,而且在整个 SO 中,无论这些问题被标记为 C++,你都会找到这个建议

    使用boost::program_options

    #include <iostream>
    #include <boost/program_options.hpp>
    
    namespace po = boost::program_options;
    
    int main( int argc, char *argv[ ] )
    {
    
        try {
            int rows,cols;
            po::options_description desc("Allowed options");
            desc.add_options()
                ( "help", "produce this help message" )
                ( "rows", po::value< int>(&rows)->required(), "No. of Rows" )
                ( "cols", po::value< int>(&cols)->required(), "No. of Cols"  )
            ;
    
            po::variables_map vm;
            po::store( po::parse_command_line( argc, argv , desc ), vm );
            po::notify( vm );
    
    
            if ( vm.count( "help" ) )
            {
                std::cout << desc;
                return 0;
            }
    
            std::cout<<"Rows :"<<rows<<" "<<"Cols :"<<cols<<std::endl;
        }
        catch( std::exception& e )
        {
            std::cout << e.what() << "\n";
            return 1;
        }    
    
        return 0;
    }
    

    用法: ./test --cols 4 --rows 3

    输出:

    Rows :3 Cols :4

    好教程Here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-12
      • 2016-05-25
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多