使用 getopt/long_getopt 的正确方法

Posted

技术标签:

【中文标题】使用 getopt/long_getopt 的正确方法【英文标题】:Correct way to use getopt/long_getopt 【发布时间】:2011-11-19 05:37:02 【问题描述】:

我知道这个话题已经被打死了,但我仍然找不到我要搜索的内容。 我需要在 C++ 中解析命令行参数。

我不能使用 Boost 和 long_getopt

问题在于转换,当我简单地打印 arguments 时,它在循环中按预期工作,但分配给变量的值无法以某种方式工作。

这是完整的、可编译的程序。

#include <iostream>
#include <getopt.h>
using namespace std;

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

    int c;
    int iterations = 0;
    float decay = 0.0f;
    int option_index = 0;
    static struct option long_options[] =
    
        "decay",  required_argument, 0, 'd',
        "iteration_num",  required_argument, 0, 'i',
        0, 0, 0, 0
    ;

    while ((c = getopt_long (argc, argv, "d:i:",
                long_options, &option_index)  ) !=-1)
     
        /* getopt_long stores the option index here. */

        switch (c)
        
        case 'i':
        //I think issue is here, but how do I typecast properly? 
        // especially when my other argument will be a float 
        iterations  = static_cast<int>(*optarg);    
        cout<<endl<<"option -i value "<< optarg;
        break;

        case 'd':
        decay = static_cast<float>(*optarg);
        cout<<endl<<"option -d with value "<<optarg;
        break;

     
    //end while
    cout << endl<<"Value from variables, which is different/not-expected";
    cout << endl<< decay << endl << iterations <<  endl;
return(0);

正如我在评论中提到的 - 认为问题在于类型转换,如何正确地做到这一点?如果有其他更好的方法,请告诉我。

您可以将程序运行为 --- ./program-name -d .8 -i 100

感谢您的帮助。我是 Unix 和 C++ 的新手,但努力学习它:)

【问题讨论】:

getopt 和朋友(几乎)已经过时,并已被 argp_parse() 取代。 【参考方案1】:

因为 optarg 是 char*。是纯文本。因此,如果您将程序 .8 作为参数,则 optarg 是一个字符串“.8”,并且将其转换为 float 是行不通的。例如,使用 atoi 和 atof 函数(在 'stdlib.h' 中声明)将字符串解析为 int 和 float。在您的代码中,它将是:

iterations = atoi(optarg);
decay = atof(optarg);

【讨论】:

我来自C背景,所以对C++不太了解,但是这种类型的演员在C++中是不是很不受欢迎?我的意思不是“让它发挥作用”,而是优雅而完美地做到这一点。感谢您的帮助【参考方案2】:

您正在将字符串 (char*) 值转换为整数值,这与解析它非常不同。通过强制转换,您将第一个字符的 ASCII 值用作数值,而通过解析字符串,您尝试将整个字符串解释为文本并将其转换为机器可读的值格式。

您需要使用如下解析函数:

std::stringstream argument(optarg);
argument >> iterations;

boost::lexical_cast<int>(optarg);

或(C 风格)

atoi(optarg)

【讨论】:

+1,除了一方面。此演员表不会“重新解释字节”;它只是将第一个char 的值转换为等效的int。 (这与 *(reinterpret_cast&lt;int *&gt;(optarg)) 等非常不同。) @thiton,谢谢,我尝试了你的第一个建议,但我得到了错误 - 从‘char’到‘std::_Ios_Openmode’的无效转换我包含了必要的文件 - fstream 和 iostream 你需要包含 并且可能需要从 optarg 构建一个 std::string 像 "std::stringstream argument(std::string(optarg)); " @thiton,谢谢。那解决了它。我完全忘记了字符串流。再次感谢。

以上是关于使用 getopt/long_getopt 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用 Composer 安装 Laravel 扩展包

如何正确使用 Composer 安装 Laravel 扩展包

如何正确使用 Composer 安装 Laravel 扩展包

如何正确使用 Composer 安装 Laravel 扩展包

如何正确强制正确使用类方法?

C#注释的正确的使用方法有哪些?