getopt()在C中不读取选项参数。

huangapple go评论58阅读模式
英文:

getopt() in C doesn't read option arguments

问题

I understand that you want a translation of the provided text, excluding the code. Here's the translation:

我正在编写一个程序,它需要三个命令行选项:s、f 和 c。
因为我被告知要使用 getopt() 函数来获取它们,所以我查看了相关信息。

这三个选项的作用如下:
s - 这只是一个“无日志”选项,我只需要检查它是否存在。
f - 这是一个文件路径选项,后面跟着它的参数(我决定将其作为字符数组并使用 fopen 处理)。
c - 这是另一个字符数组,它在自身之后接受一个参数。

在经过2个小时的尝试并未能够正确地通过函数获取这些选项后,我联系了您。

关于 getopt() 的文档非常有限,我找不到一个能够逐行解释代码的好示例,但尽管如此,经过阅读 geeksforgeeks 页面和 GNU 文档的几页后,我得出了以下代码:

(以下为代码部分,已省略)

我使用 argv[optind] 而不是 optarg,因为它无法记录正确的参数。到目前为止,我一直在尝试运行以下 CLI 输入:
filename -s -f abc -c abc

我得到的结果是“Program is executing without logs.”,仅此而已。
在某些时候,我实际上能够让所有的 printf 在最后打印出来。
但现在只有这个打印出来,我完全没有想法。
而且编译时间非常长(几秒钟)。
我使用 CLion IDE 和其捆绑的 MinGW 编译器。
我到底做错了什么,为什么我无法正确获取 CLI 参数?

如果您需要更多帮助或有其他问题,请随时告诉我。

英文:

I am typing up a program and it takes three command-line options: s, f and c
Since I was told to use getopt() as a function to get them, I looked into it.

The three options do the following:
s - this is just a "no logs" option, all I need to do is check if it's there or not
f - this is a file path option, followed by its argument (I decided it best to take it as a char array and then use fopen with it)
c - this is another char array that takes an argument after itself

I'm reaching out to you after 2 hours of trying to get these options properly through the function and being unable to.

There is surprisingly little documentation for getopt(), I couldn't find a good example where the code is explained line by line, but nevertheless, this is what I came up with after reading the geeksforgeeks page and the several pages of the GNU documentation regarding it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int opt;
    char *cli_input_s = NULL;
    char *cli_input_f = NULL;
    char *cli_input_c = NULL;

    while ((opt = getopt(argc, argv, "fc:s")) != -1)
    {
        switch (opt)
        {
            case 's':
                printf("Program is executing without logs.\n");
                break;
            case 'f':
                strcpy(cli_input_f, argv[optind]);
                break;
            case 'c':
                strcpy(cli_input_c, argv[optind]);
                break;
            case '?':
                printf("The program has encountered an unknown argument, aborting.");
                break;
            default:
                printf("I don't know what exactly is going on but...");
                break;
        }
    }

    printf("%d \n", argc);
    printf("%s \n", cli_input_s);
    printf("%s \n", cli_input_f);
    printf("%s \n", cli_input_c);
}

I am using argv[optind] instead of optarg because it wouldn't record the correct thing to the arguments. So far, I've been trying to run the following CLI input:
filename -s -f abc -c abc

The result I'm getting is "Program is executing without logs." and that's it.
At some point I was actually managing to get all the printf's at the end to... print.
But now this is the only thing that prints and I'm completely out of ideas.
It also takes a surprisingly long time to compile (several seconds).
I'm using the CLion IDE and its bundled MinGW compiler.

What exactly am I doing wrong and why can I not get the CLI arguments properly?

答案1

得分: 1

The option string "fc:s" 表示只有 -c 可以带一个参数。对于每个可以带参数的选项,你都需要有参数字符 :

所以如果你想让 -f 选项也可以带参数,你的字符串应该是 "f:c:s"


那个选项参数字符串只是你问题中的小问题。一个更严重的问题是你因为空指针的使用而导致了未定义行为...

举个例子

strcpy(cli_input_f, argv[optind]);

指针 cli_input_f 是一个空指针。它没有指向任何地方。但你却试图将其用作字符串的目的地。这是不可能的。

你必须有一个足够长的字符串来容纳源字符串,包括末尾的空终止符。

我建议你将变量从指针改为足够大的数组:

char cli_input_f[256] = { 0 };  // 将所有元素初始化为字符串的空终止符
英文:

The option string "fc:s" say that only -c can have an argument. You need the argument character : for each option that can take an argument.

So your string should be "f:c:s" if you want the -f option to also have an argument.


That option argument string is the least of your problem. A much worse problem is that you have undefined behavior due to your usage of null pointers...

Take for example

strcpy(cli_input_f, argv[optind]);

The pointer cli_input_f is a null pointer. It doesn't point anywhere. And yet you use it as a destination for a string. That's not possible.

You must have a pointer to a string long enough to hold the sources string, including the null-terminator at the end.

I recommend you simply change your variables from pointers to arrays of sufficient size:

char cli_input_f[256] = { 0 };  // Initialize all elements to the string null-terminator

huangapple
  • 本文由 发表于 2023年5月6日 16:59:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76188015.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定