C语言中的自定义命令行参数

C语言中的自定义命令行参数,c,C,我目前正在通过K&R的《C编程语言》学习C语言,并在书中讨论了命令行参数。在这本书中,主要的程序是这样写的: int main(int argc, char *argv[]) { do something } 据我所知,在某个时刻,传递给程序的参数数量必须被计数并存储在argc中。此外,必须存储参数本身,并且指向每个参数的第一个字符的指针存储在数组argv中,其中argv[0]是指向命令名的指针,argv[argc]是空指针。这些步骤不能只是神奇地发生,这种行为必须在某个地方定义 例如

我目前正在通过K&R的《C编程语言》学习C语言,并在书中讨论了命令行参数。在这本书中,主要的程序是这样写的:

int main(int argc, char *argv[])
{
    do something
}
据我所知,在某个时刻,传递给程序的参数数量必须被计数并存储在
argc
中。此外,必须存储参数本身,并且指向每个参数的第一个字符的指针存储在数组
argv
中,其中
argv[0]
是指向命令名的指针,
argv[argc]
是空指针。这些步骤不能只是神奇地发生,这种行为必须在某个地方定义

例如,假设我想存储传递给程序的每个参数的第一个字符,
firstc
,并丢弃该参数的其余部分(让我们假设我有一个非常非常好的理由这样做)。我可以这样写main():

显然,使用默认的
argc
argv
可以很容易地做到这一点,实际上我不会这么做。我甚至无法想象在什么情况下这是必要的,但我很想知道这是否可能

因此,我(完全理论化,完全不切实际)的问题是:是否可以为命令行参数定义我自己的行为?如果是,人们将如何着手这样做?如果相关的话,我正在使用Ubuntu 16.04和GNOME终端

附言


我在写这个问题的时候才意识到,完全有可能(也许可能)C脚本完全无视外部的情况,而终端仿真器是为C程序准备命令行参数的工具。

参数的设置实际上不在C标准的范围内,它只是规定了可以使用的
main
的允许形式。这有两种规范形式(假设是托管实现),一种是
argc/argv
选项,另一种是
void
选项(尽管请注意,一个实现可以自由提供其他实现)

通常,在调用
main
之前会运行一些代码,例如从对象文件(如
crt0.o
中的启动代码)

然而,如前所述,该标准并没有规定在该阶段发生的任何事情,“环境”有责任正确设置,以便调用
main

根据您的要求,我认为最简单的解决方案是提供一个采用规范形式的
main
,只需使用每个参数的第一个字符调用
myMain
,尽管您可能需要智能地处理可能提供给
main
的任何数量的参数

下面的示例可以处理一到三个参数:

#include <stdio.h>

int myMain0(void) {
    printf ("myMain0\n");
    return 0;
}

int myMain1(char p1) {
    printf ("myMain1 [%c]\n", p1);
    return 0;
}

int myMain2(char p1, char p2) {
    printf ("myMain2 [%c] [%c]\n", p1, p2);
    return 0;
}

int main(int argc, char *argv[]) {
    switch (argc) {
        case 1: return myMain0();
        case 2: return myMain1(argv[1][0]);
        case 3: return myMain2(argv[1][0], argv[2][0]);
    }
    printf ("Invalid argument count of %d\n", argc - 1);
    return 1;
}
#包括
int myMain0(无效){
printf(“myMain0\n”);
返回0;
}
int myMain1(字符p1){
printf(“myMain1[%c]\n”,p1);
返回0;
}
int myMain2(字符p1、字符p2){
printf(“myMain2[%c][%c]\n”,p1,p2);
返回0;
}
int main(int argc,char*argv[]){
开关(argc){
案例1:返回myMain0();
案例2:返回myMain1(argv[1][0]);
案例3:返回myMain2(argv[1][0],argv[2][0]);
}
printf(“无效参数计数%d\n”,argc-1);
返回1;
}

操作系统将参数数量和参数本身从命令行传递给C程序

函数
main
对其参数并不挑剔。您完全不能获取任何参数,只能获取
argc
,并且可以同时获取
argc
argv

您甚至可以获得3或4个参数,这些参数的类型是您想要的,但它们将包含垃圾。操作系统将始终以int和字符串指针数组的形式传递参数数量及其名称。

您的
main()
声明实际上并不定义您得到的参数。这是程序环境的责任:操作系统和调用程序,通常是命令行处理器

调用者(通常是一个shell程序)准备参数并将其传递给相应的操作系统例程,以便调用该程序。操作系统例程通常在堆栈上为被调用方准备这些数据,并跳转到程序的入口点,然后跳转到
main
函数

您的
main()
声明只声明了
main
对堆栈的期望,这间接定义了如何使用这些数据,而不是它们是什么。这也是为什么您可以在没有参数的情况下将
main
声明为
main(void)
——这仅仅意味着“无论传递给我什么,我都将忽略它”。

有一些标准(如ANSI C、C89等),它们提供了主要规则和一组限制,并且有协议,这不会违反标准,并为您提供一些可能性

首先,我再举一个例子:

#包括
int main(int argc,char*argv[],char*envs[]
{
int i=1;
while(envs[i]!=NULL)
{ 
printf(“%d:%s\n”,i,envs[i]);
i++;
}
返回0;
}
试着看看
main
的第三个参数是如何有用的

另外,我想解释一下我处理命令行参数的方法。我创建
ParseCommandLine
(或
EvaluateParameters
)并在
main
的开头调用它。该函数分析命令行中的字符串,并存储所有设置,以便于进一步使用。例如,如果我希望我的程序以

  prog.exe -i input_file_name -o output_file_name -e
我会这样做:

#包括
#包括
#定义FNAME_LEN 20
结构设置
{
字符输入FNAME[FNAME_LEN];
  prog.exe -i input_file_name -o output_file_name -e