C语言 . 第三章第三节 . 变参函数

一、引入

复制代码
前文我们学过的printf函数和scanf函数叫做变参函数。
顾名思义,这些函数的参数个数是变化的,不固定

一、最值函数

复制代码
这是 max_int 的声明

这里 a 代表有 a 个整数,并且......不代表省略号,而是用来表示变参列表的 
代码演示:
c 复制代码
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
 
 
//此位置的参数n表示后面的变参参数个数
int max_int(int n,...) {
    va_list args;//args表示变参列表
    va_start(args, n);//这段代码表示,变参参数从参数n后面开始
    int ans = INT32_MIN;//这里用到INT32_MIN,需要包含头文件<stdint.h>
    for (int i = 0; i < n; i++) {
    		 //记录当前值
        //开始从第一个位置获取变参参数
        //并且为int类型
        //这里获取后下次获取就是下一个变参参数
        int a = va_arg(args, int);
        //判断当前参数的值是否大于之前的最大值
        //如果大于就记录当前值为最大值
        if (a > ans) ans = a;
    }
    va_end(args);//结束对参数列表的读取动作
    return ans;
}
 
 
 
int main() {
   printf("max_int(%d, %d, %d, %d) = %d\n", 2, 4, 6, 1, max_int(4, 2, 4, 6, 1));
   printf("max_int(%d, %d, %d, %d, %d) = %d\n", 10, 4, 6, 1, 88,  max_int(5, 10, 4, 6, 1, 88));
    return 0;
}

转载自@初猿

二、主函数的参数

1、主函数的第二种形式

c 复制代码
#include<stdio.h>

//第一个位置代表的是命令行中参数的个数
//第二个位置代表的是,每一个命令行中的参数
int main(int argc, char *argv[]) {
    printf("argc = %d\n", argc);
    for (int i = 0; i < argc; i++) {//循环argc次
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}

效果:

如果加上双引号,可以将双引号内的视作一个整体

我们尝试一个小程序:

假设现在有一个程序名字是NEU_UUN,如果不是按照 ./NEU_UUN 进行调用,就无法运行。

如何实现?

其实在上面的效果图中,我们能看出来 argv[0] 存储的就是调用命令,我们只需让其与我们规定的 ./NEU_UUN 进行比较即可

那怎么比较呢?

这时我们需要借用string.h头文件的一些方法了

c 复制代码
#include<stdio.h>
#include<string.h>

//第一个位置代表的是命令行中参数的个数
//第二个位置代表的是,每一个命令行中的参数
int main(int argc, char *argv[]) {
    //strcmp函数的返回值分为三类
    //1. 前 > 后,返回一个大于0的值
    //2. 前 = 后,返回一个等于0的值
    //3. 前 < 后,返回一个小于0的值

    if (strcmp(argv[0], "./NEU_UUN") != 0) {
        printf("wrong call, please call :./NEU_UUN\n");//打印错误调用的信息
        return 0;
    };
    printf("right call\n");
    printf("argc = %d\n", argc);
    for (int i = 0; i < argc; i++) {//循环argc次
        printf("argv[%d] = %s\n", i, argv[i]);
    };
    return 0;
}

效果:

2、主函数的第三种形式

相较于第二种形式,它多存储了一个参数------环境变量char **env

python、Java底层的解释器基本都是用C语言实现的

因为C语言提供了main函数的第三种形式------具有读取环境变量的特点

这里的环境变量 其实就储存着我们当前这个终端环境的各种信息------包括用户名、终端字体颜色等等

原型:

c 复制代码
int main(int argc, char *argc[], char **env);

我们尝试实现一个限制性功能

如果用户名不是NEU_UUN,则无法执行该程序

代码实现

c 复制代码
#include<stdio.h>
#include<string.h>
//新增的第三个参数是二维数组,现在试着理解就行
int main(int argc, char *argv[], char **env) {
    int flag = 0;
    for (char **p = env; p[0]; p += 1) {//遍历环境变量中的所有字符串
       if (strcmp (p[0], "LOGNAME=NEUwithUUN") == 0) {
           flag = 1;
           break;
        };
    };
    if (flag == 0){//设定flag的用处就在于此,便于判断if语句是否执行
        printf("error log name, please use NEUwithUUN\n");
        return 0;
    };
    printf("argc = %d\n", argc);
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    };
    return 0;
}

现在只对main函数的三种形式进行初步了解,以防后续在工程设计时看到这些感到陌生

相关推荐
墨雪不会编程4 分钟前
C++之【深入理解Vector】三部曲最终章
开发语言·c++
浅念-11 分钟前
C语言编译与链接全流程:从源码到可执行程序的幕后之旅
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
小宋102122 分钟前
Java 项目结构 vs Python 项目结构:如何快速搭一个可跑项目
java·开发语言·python
爱吃生蚝的于勒23 分钟前
【Linux】进程信号之捕捉(三)
linux·运维·服务器·c语言·数据结构·c++·学习
The森36 分钟前
Linux IO 模型纵深解析 01:从 Unix 传统到 Linux 内核的 IO 第一性原理
linux·服务器·c语言·经验分享·笔记·unix
一晌小贪欢1 小时前
Python 爬虫进阶:如何利用反射机制破解常见反爬策略
开发语言·爬虫·python·python爬虫·数据爬虫·爬虫python
阿猿收手吧!1 小时前
【C++】异步编程:std::async终极指南
开发语言·c++
小程故事多_801 小时前
Agent Infra核心技术解析:Sandbox sandbox技术原理、选型逻辑与主流方案全景
java·开发语言·人工智能·aigc
沐知全栈开发1 小时前
SQL 日期处理指南
开发语言
黎雁·泠崖1 小时前
【魔法森林冒险】3/14 Allen类(一):主角核心属性与初始化
java·开发语言