argc & argv in C

本文介绍了一个简单的C语言程序,该程序能够将多个文件的内容串联输出。通过使用fopen函数打开文件,并利用main函数中的参数argc和argv来指定要处理的文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽说输入/输出不是C语言本身的组成部分,但是它是程序与数据间交互中不可缺少的一部分。下边我们编写一个访问文件的程序cat,它把一批命名文件串联后输出到标准输出(stdout)上。例如,下列命令行:
cat x.c y.c
将在标准输出上打印文件x.c和y.c的内容。
读写一个文件前,需要通过库函数fopen打开该文件,并返回用于文件读写操作的文件指针。因为<stdio.h>中已经定义了结构FILE,在程序中只需按照下列方式声明一个文件指针即可:

FILE *fp;
FILE *fopen(char *name, char *mode);

有了这些预备知识后,我们就可以编写cat这个程序了。如果有命令行参数,参数将被解释为文件名,并按顺序逐个处理。如果没有参数,则处理标准输入。

#include <stdio.h>

int main(int argc, char const *argv[])
{
    FILE *fp;
    void filecopy(FILE *, FILE *);

    if (argc == 1)
        filecopy(stdin, stdout);
    else
        while (--argc > 0)
            if ((fp = fopen(*++argv, "r")) == NULL)
            {
                printf("cat: can't open %s\n", *argv);
                return 1;
            }
            else
            {
                filecopy(fp, stdout);
                fclose(fp);
            }
    return 0;
}

void filecopy(FILE *ifp, FILE *ofp)
{
    int c;

    while ((c = getc(ifp)) != EOF)
        putc(c, ofp);
}

一直以来,在写完main函数之后都会带有参数argc和argv,之前虽有了解但是对于如何使用还是不知道。在这个程序中,才真正搞明白其具体的含义。arg表示的是参数(argument),argc和argv分别代表argument counter和argument vector。argc是整型类,用来统计参数个数。argv是字符类型指针数组,指向字符串参数。
很多程序是带有参数的,argc是指参数的个数,而argv[]就是指向这些参数的地址,其中argv[0]指向编译后的可执行文件本身,argv[1]、argv[2]…则指向程序之后带的参数。
比如,我们编写的这个程序,先编译

gcc -o cat cat.c

直接运行cat,参数只有1个即cat本身,所以执行从标准输入到标准输出,即将输入的内容输出。
现在我们再编辑两个文件cat1.c和cat2.c里面的内容分别为cat1和cat2,运行cat并带有两个参数

cat cat1.c cat2.c

则输出结果就是两个文件串联在一起的内容:cat1cat2
这里文件名cat1.c和cat2.c分别作为参数argv[1]和argv[2]输入到我们的程序中。

``` #include &quot;a2.h&quot; int main (int argc, char *argv[]) { char *subopts, *value; int opt, sjf = 0, fcfs = 0, srtf = 0, rr = 0, unix_sched = 0, verbose = 0, number_of_jobs = 0, no_scheduler = 1; char *filename = NULL; if(argc == 1) { print_usage(argc, argv); return 1; } while((opt = getopt(argc, argv, &quot;hvn:i:s:&quot;)) != -1) switch(opt) { case &#39;h&#39;: print_usage(argc, argv); break; case &#39;v&#39;: verbose = 1; break; case &#39;n&#39;: number_of_jobs = strtol(optarg, NULL, 10); break; case &#39;i&#39;: filename = optarg; break; case &#39;s&#39;: subopts = optarg; while(*subopts != &#39;\0&#39;) switch(getsubopt(&amp;subopts, scheduler_opts, &amp;value)) { case SJF: sjf = 1; break; case FCFS: fcfs = 1; break; case SRTF: srtf = 1; break; case RR: rr = 1; break; case UNIX: unix_sched = 1; break; default: printf(&quot;unknown scheduler passed in list to -s\n&quot;); break; } no_scheduler = 0; break; default: print_usage(argc, argv); abort(); break; } if(number_of_jobs &gt; 0 &amp;&amp; filename) { fprintf(stderr, &quot;cannot specify both -n and -i parameters.\n&quot;); print_usage(argc, argv); return 1; } if(number_of_jobs == 0 &amp;&amp; filename == NULL) { fprintf(stderr, &quot;must specify either -n or -i parameter.\n&quot;); print_usage(argc, argv); return 1; } if(no_scheduler) { fprintf(stderr, &quot;must specify a scheduler with -s parameter.\n&quot;); print_usage(argc, argv); return 1; } if(sjf) process_jobs(sjf_comparison, filename, number_of_jobs, verbose); if(fcfs) process_jobs(fcfs_comparison, filename, number_of_jobs, verbose); if(srtf) process_jobs(srtf_comparison, filename, number_of_jobs, verbose); if(rr) process_jobs(rr_comparison, filename, number_of_jobs, verbose); if(unix_sched) process_jobs(unix_comparison, filename, number_of_jobs, verbose); return 0; }```请解释这个代码内容。
03-24
&lt;think&gt;好的,我现在需要仔细分析用户提供的这段C代码,并解释它的功能。首先,我会先通读代码,了解整体结构,然后逐部分理解。 这段代码看起来像是一个主函数,属于某个程序的入口点。主要处理命令行参数,并基于这些参数执行不同的调度算法。可能是一个模拟进程调度的程序。 首先,代码开头包含了头文件a2.h,可能定义了一些函数和结构,比如process_jobs和各种比较函数(sjf_comparison等)。主函数main的参数是标准的argcargv,用于处理命令行输入。 接下来,声明了一些变量:subopts和value用于处理子选项;一系列的整型变量sjf、fcfs、srtf等,初始化为0,可能作为标志位表示是否启用对应的调度算法;verbose控制详细输出;number_of_jobs和filename用于指定作业数量或输入文件;no_scheduler初始化为1,表示默认没有选择调度器。 在argc为1时(即没有参数),调用print_usage并返回,提示用户正确用法。然后使用getopt循环处理命令行参数,选项字符串是&quot;hvn:i:s:&quot;,对应的选项处理如下: - -h:打印帮助信息。 - -v:设置verbose为1。 - -n:指定作业数量,转换为整数。 - -i:指定输入文件名。 - -s:处理子选项,使用getsubopt解析,可能的值包括SJF、FCFS等,对应设置标志位为1,并将no_scheduler设为0。 之后,检查参数冲突:如果同时指定了-n和-i,报错;如果两者都没指定,也报错;如果没有指定调度器(no_scheduler为1),同样报错。 最后,根据启用的调度算法标志,调用process_jobs函数,传入对应的比较函数和其他参数。每个调度算法可能有不同的比较逻辑,比如sjf_comparison代表短作业优先,fcfs_comparison是先来先服务等。 需要注意的是,代码中使用了多个if语句来处理不同的调度算法,这意味着可以同时指定多个调度器吗?但根据选项处理逻辑,-s参数可能接受多个子选项,例如-s SJF,FCFS,这样会同时设置sjf和fcfs为1,导致多次调用process_jobs。但这是否合理取决于process_jobs的实现,可能该程序支持同时比较多个调度算法。 可能存在潜在的问题,例如,当用户同时指定多个调度算法时,process_jobs会被多次调用,每次处理相同的作业数据。需要确认这样的设计是否符合预期。 总结来说,这段代码的功能是解析命令行参数,验证输入的有效性,并根据选择的调度算法处理作业数据,可能用于模拟或比较不同调度策略的表现。&lt;/think&gt;这是一个使用C语言编写的命令行程序,主要用于模拟不同进程调度算法。以下是对代码的逐步解析: $1.$ **头文件包含和主函数声明** - 包含自定义头文件`a2.h`(可能定义了调度算法相关函数) - `main`函数接收命令行参数`argc`和`argv` $2.$ **变量声明** ```c int sjf=0, fcfs=0, ...; // 调度算法标志位 int verbose=0; // 详细输出模式 int number_of_jobs=0; // 作业数量 char *filename=NULL; // 输入文件名 ``` - 使用多个整型变量作为调度算法的开关 - `no_scheduler=1`表示默认未选择任何调度器 $3.$ **参数检查** ```c if(argc == 1) { // 无参数时显示帮助 print_usage(argc, argv); return 1; } ``` - 无参数时调用`print_usage`显示使用说明 $4.$ **命令行参数解析** 使用`getopt`处理选项: - `-h` 显示帮助 - `-v` 启用详细模式 - `-n &lt;数字&gt;` 设置作业数量 - `-i &lt;文件&gt;` 指定输入文件 - `-s &lt;算法&gt;` 关键部分:使用`getsubopt`解析子选项: ```c while(*subopts != &#39;\0&#39;) switch(getsubopt(...)){ case SJF: sjf=1; break; // 短作业优先 case FCFS: fcfs=1; break; // 先来先服务 case SRTF: srtf=1; break; // 最短剩余时间优先 case RR: rr=1; break; // 时间片轮转 case UNIX: unix_sched=1; // UNIX风格调度 } ``` $5.$ **参数冲突检测** ```c if(number_of_jobs &gt; 0 &amp;&amp; filename) // -n和-i不能共存 if(number_of_jobs==0 &amp;&amp; filename==NULL) // 必须指定其一 if(no_scheduler) // 必须指定调度算法 ``` - 确保输入参数的合法性 $6.$ **调度执行** ```c if(sjf) process_jobs(sjf_comparison,...); if(fcfs) process_jobs(fcfs_comparison,...); // 其他算法类似... ``` - 根据选择的调度算法调用`process_jobs`函数 - 不同算法通过函数指针传入(如`sjf_comparison`) **程序功能总结**: 1. 支持5种调度算法:$SJF$(短作业优先)、$FCFS$(先来先服务)、$SRTF$(最短剩余时间优先)、$RR$(时间片轮转)、$UNIX$风格调度 2. 支持两种数据输入方式: - `-n` 指定随机生成的作业数量 - `-i` 从文件读取作业数据 3. 通过`-v`参数启用详细输出模式 4. 可同时比较多个调度算法(通过`-s`指定多个子选项) **典型使用示例**: ```bash # 比较SJF和RR算法,使用input.txt文件 ./program -i input.txt -s SJF,RR -v ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值