- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试创建一个小型 Linux 命令行应用程序。可以通过在调用应用程序时传递参数来运行应用程序,我使用 getopt() 对其进行解析。
可以选择以交互模式运行此应用程序,在这种情况下会显示一个小菜单,用户应该能够输入与他们在运行应用程序时添加的选项类似的选项。
为了避免在交互模式下创建不同的解析器,我想将键盘输入解析为 argc 和 argv,并将其提供给同一个 getopt() 函数。
我创建的 c
函数的概念证明如下:
void menuDlg()
{
char kbinput[256];
wordexp_t we;
char **argAr;
int argCount = 0 ,i,er=0;
printf("showing menu options\n");
//...
//...
///grab keyboard input
fgets(kbinput,256,stdin);
///the "\n" in kbinput breaks we
///and we.we_wordc return weird value,
///so we need to remove it
for (i=0; i<256; i++)
{
if (kbinput[i]=='\n')
{
kbinput[i]='\0';
break;
}
}
printf("you typed |%s|\n",kbinput);
we.we_offs = 0;
if ( (er=wordexp(kbinput, &we, 0)) != 0)
{
printf("error in word expansion %d\n",er);
}
argAr = we.we_wordv;
argCount = we.we_wordc;
printf("we.c=%u\n",we.we_wordc);
main_dialog( argCount, argAr );
wordfree(&we);
}
是 main_dialog() 解析 cli 选项
void main_dialog( int argc, char* argv[] )
{
while ( (ch = getopt_long(argc, argv, "yscvh", longopts, NULL)) != -1 )
switch (ch)
{
...
}
}
但是当我运行它时,我的应用程序在对 getopt_long()
的调用中崩溃了。
我读到 argv
应该有一个 null
的最终条目。所以对于参数 "foo bar",我们有 argc=2 ,但是 argv[0]="foo"、 argv[1]="bar"和 argv[2]='\0' 。在 wordexp documentation它几乎没有说明 we_wordv 的内部结构(即关于尾部 NULL 数组条目),所以我不知道这是否是问题所在。
这会是问题的根源吗?是否有另一个 glib
函数可以满足我的需要?
谢谢
最佳答案
将评论转化为答案——然后扩展想法。
getopt()
或 getopt_long()
在调用 main_dialog()
中的代码之前?如果是这样,您可能需要重新初始化它们,以便它们从当前参数列表的开头开始,而不是继续使用原始参数列表。并不总是很清楚如何进行重置。
BSD (Mac OS X) 文档:
In order to use
getopt()
to evaluate multiple sets of arguments, or to evaluate a single set of arguments multiple times, the variableoptreset
must be set to 1 before the second and each additional set of calls togetopt()
, and the variableoptind
must be reinitialized.
它还记录了额外的变量:extern int optreset;
其他系统没有清楚地记录需要做什么。请注意 getopt()
的 POSIX 规范具体说明(添加了强调):
The variable
optind
is the index of the next element of theargv[]
vector to be processed. It shall be initialized to 1 by the system, andgetopt()
shall update it when it finishes with each element ofargv[]
. If the application setsoptind
to zero before callinggetopt()
, the behavior is unspecified. When an element ofargv[]
contains multiple option characters, it is unspecified howgetopt()
determines which options have already been processed.
因此,您可能需要进行试验才能找到有效的方法。
从response comment来看, 有时设置 optind = 0;
将工作(这似乎适用于 Linux)。目前还不清楚它是否适用于任何地方(POSIX 说它可能不会);使用前测试!
你可以尝试像这样的程序,我称之为 getopt-test.c
:
#include <stdio.h>
#include <unistd.h>
static void dump_getopt_state(const char *tag)
{
printf("%s:\n", tag);
printf("optind = %d, ", optind);
printf("opterr = %d, ", opterr);
printf("optopt = %d, ", optopt);
printf("optarg = %p\n", (void *)optarg);
}
int main(int argc, char **argv)
{
int opt;
dump_getopt_state("Initial");
char tag[32];
while ((opt = getopt(argc, argv, "ab:cd:")) != -1)
{
switch (opt)
{
case 'a':
case 'c':
sprintf(tag, "Option %c", opt);
break;
case 'b':
case 'd':
sprintf(tag, "Option %c", opt);
printf("Argument: %s\n", optarg);
break;
}
dump_getopt_state(tag);
}
dump_getopt_state("Final");
return 0;
}
示例输出(Mac OS X 10.10.4):
$ getopt-test
Initial:
optind = 1, opterr = 1, optopt = 0, optarg = 0x0
Final:
optind = 1, opterr = 1, optopt = 0, optarg = 0x0
$ getopt-test -a
Initial:
optind = 1, opterr = 1, optopt = 0, optarg = 0x0
Option a:
optind = 2, opterr = 1, optopt = 97, optarg = 0x0
Final:
optind = 2, opterr = 1, optopt = 97, optarg = 0x0
$ getopt-test -ac
Initial:
optind = 1, opterr = 1, optopt = 0, optarg = 0x0
Option a:
optind = 1, opterr = 1, optopt = 97, optarg = 0x0
Option c:
optind = 2, opterr = 1, optopt = 99, optarg = 0x0
Final:
optind = 2, opterr = 1, optopt = 99, optarg = 0x0
$
注意处理 a
后的状态-ac
的选项.唯一可见的状态变化在 optopt
中。 , 很可能修改 optopt
不会触发复位。设置optind
归零可能会奏效,但 optind
的官方值(value)在程序启动时是 1
.
这也是为什么全局变量不好的一个实例。
另请注意,如果您更改 argc
的值,将会发生什么情况尚不清楚。和 argv
在调用 getopt()
之间.规范并未说明每次值都应相同,但如果您不将代码重置为起点,则可能会出现困惑。
我的代码的输出格式可以改进为打印 optopt
作为 2 位十六进制值。如果 :
可能会更好作为标签的一部分传递给转储函数;那么第一次打印可能是:printf("%-.12s ", tag)
所以一切都一致。 optarg
的值是长度最有可能变化的那个;这就是为什么它是最后一个。
关于c - 将 wordexp 的输出提供给 getopt_long 会使我的 linux cli 应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31862523/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
Linux 管道可以缓冲多少数据?这是可配置的吗? 如果管道的两端在同一个进程中,但线程不同,这会有什么不同吗? 请注意:这个“同一个进程,两个线程”的问题是理论上的边栏,真正的问题是关于缓冲的。 最
我找到了here [最后一页] 一种有趣的通过 Linux 启动 Linux 的方法。不幸的是,它只是被提及,我在网上找不到任何有用的链接。那么有人听说过一种避免引导加载程序而使用 Linux 的方法
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我试图了解 ld-linux.so 如何在 Linux 上解析对版本化符号的引用。我有以下文件: 测试.c: void f(); int main() { f(); } a.c 和 b.c:
与 RetroPie 的工作原理类似,我可以使用 Linux 应用程序作为我的桌面环境吗?我实际上并不需要像实际桌面和安装应用程序这样的东西。我只需要一种干净简单的方法来在 RaspberryPi 上
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
有什么方法可以覆盖现有的源代码,我应该用 PyQt、PyGTK、Java 等从头开始构建吗? 最佳答案 如果您指的是软件本身而不是它所连接的存储库,那么自定义应用程序的方法就是 fork 项目。据我所
我的情况是:我在一个磁盘上安装了两个 linux。我将第一个安装在/dev/sda1 中,然后在/dev/sda2 中安装第二个然后我运行第一个系统,我写了一个脚本来在第一个系统运行时更新它。
我在 i2c-0 总线上使用地址为 0x3f 的系统监视器设备。该设备在设备树中配置有 pmbus 驱动程序。 问题是,加载 linux 内核时,这个“Sysmon”设备没有供电。因此,当我在总线 0
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我正试图在 linux 模块中分配一大块内存,而 kalloc 做不到。 我知道唯一的方法是使用 alloc_bootmem(unsigned long size) 但我只能从 linux 内核而不是
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我有 .sh 文件来运行应用程序。在该文件中,我想动态设置服务器名称,而不是每次都配置。 我尝试了以下方法,它在 CentOS 中运行良好。 nohup /voip/java/jdk1.8.0_71/
我是在 Linux 上开发嵌入式 C++ 程序的新手。我有我的 Debian 操作系统,我在其中开发和编译了我的 C++ 项目(一个简单的控制台进程)。 我想将我的应用程序放到另一个 Debian 操
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我使用4.19.78版本的稳定内核,我想找到带有企鹅二进制数据的C数组。系统启动时显示。我需要在哪里搜索该内容? 我在 include/linux/linux_logo.h 文件中只找到了一些 Log
我知道可以使用 gdb 的服务器模式远程调试代码,我知道可以调试针对另一种架构交叉编译的代码,但是是否可以更进一步,从远程调试 Linux 应用程序OS X 使用 gdbserver? 最佳答案 当然
是否有任何可能的方法来运行在另一个 Linux 上编译的二进制文件?我知道当然最简单的是在另一台机器上重建它,但假设我们唯一能得到的是一个二进制文件,那么这可能与否? (我知道这可能并不容易,但我只是
我是一名优秀的程序员,十分优秀!