当前课程知识点:面向对象程序设计(C++) > 第一讲 课程简介与编程环境 > 1.2 main函数的命令行参数 > main函数的命令行参数
好 刚才大家在看这个make工具的使用
可以看到呢你既可以直接敲make
也可以在后面跟一个名字
那这两者的这个在运行的时候
肯定是有区别的
那那个make这个工具
它当年的那个编程人员是怎么来
区分这两种不同的情形呢
他怎么知道你这个后面带不带参数
或者说怎么来获得这个参数内容呢
这个是一个非常有用的
一个编程的技巧和知识
所以下面我们就来介绍一下
这个里头到底藏着什么东西
大家先看这样的一个例子
我问大家这个程序它的功能是什么
看上去很简单对吧定义了A跟B
然后呢用cin的办法
去得到A跟B的值
然后呢把它加起来输出来
这里头有一个新的写法
就是std::
如果大家对于我们以前
程序设计基础的慕课课
看过有印象的话就知道
为了去用cin cout我们除了去inlcude
还有一个指令叫using namespace std;
现在呢我没有写这句话
那没有写好像是不能去用cincout对吧
但其实我在cincout之前加上std::
冒号冒号是一个预操作符
用这个一样可以起到跟using namespace std;
一样的这种效果
所以我们省掉那一行
然后呢多了这么几个
在cincout前面加了这么几个
加了这么个前缀 所以是std::
cin>>A>>B
我们知道它是一个回车换行
那么这个时候呢也得用std来把它引导出来
所以呢一个名字空间的名字std
加上一个预操作符冒号冒号
那么再跟上cin cout或者endl
就能起到类似的这种作用
很简单这个程序就是把a b从键盘上得到
然后输出它们的和
这个程序运行的时候很简单
它就等着你输入啊
你不输入的话它就不会去往下走
所以可以看到呢这两个数
是在这程序运行它问你的时候
你才输入
我们可以把这个称之为一种强制交互
就是要求你输输完之后我才往下走
否则我就等着
那么有没有别的这种交互方式呢
那我们看下面这样的一个例子
在这个例子里头出现了一个新东西
在main函数的圆括号里头
多了两个参数 第一个是一个整数
它的名字叫argc
第二个呢 是一个字符串数组
你既可以写成char* argv[]
也可以写成
像我们现在这个例子里头看到的char**
有的书上可能会告诉你说这个叫指针的指针
但是对于我们来讲
我们习惯于把它称之为字符串
就是char*字符串的数组
所以你既可以用char** argv
也可以写成char*argv[]
多了这个干什么用呢
看源代码
这个时候我们不再去用std::cin来获得a跟b
而是调了atoi这个函数
把argv的这个数组的第一个元素
argv数组的第二个元素
分别去传给atoi这个函数
这个函数大家可以
课下去查一下在网络上搜索一下
你就会发现这个函数的功能
是把字符串转成整数
a表示字符 i表示整数 atoi
把字符串变成整数
大家经过程序设计基础课
前一门课程的学习知道
字符串要让你写一个字符串123
它就是个字符串对吧
它并不代表一百二十三对不对
那我怎么能够让它变成整数
让它去代表123呢
就用这个函数atoi
你就可以把它变成一个整数值
我们把它存到a里头去
同理把argv[2]这个元素里头的
数组元素里头的这个字符串
把它变成整数存到b里头去
这样呢我们就可以算a加b的这个和
这就是这个代码的含义
那他运行起来长什么样呢
刚刚看到的是源代码
它的运行会有什么样的一种不同呢
我们在windows平台下面
对这个代码做了一个测试
对它进行编译cl -GX ex2.cpp
那么编译好了之后
就会产生一个ex2.exe的这种可执行代码
我们去输入这个命令注意后面跟上
空格4 空格5 把这个参数
在输入ex2的这个命令的时候
同时跟在后面输进去
就和我们前面用那个make工具的时候后面跟上
任务的名字跟上makefile的文件的名字一样 对吧
还记得我们前面写的make -f
对吧 然后makefile的名字
然后后面是任务的名字
那现在这个ex2这个执行程序呢
我们跟的是4和5分别用空格跟在后面
回车 我们得到的结果是这个9
因为我们给了一个4一个5
那么它自动地读进去
然后就得到了
4跟5两个整数
然后相加输出了9
这是它在编译之后
这样的程序它在执行的时候
会是什么样子的这样一个外在表现
那么这里头就要解释一下
这个输入命令行上ex2.exe 4 5
4跟5是怎么送到程序里去的呢
我们可以看到呢
在argv这个数组里头
当你的程序运行的时候
操作系统 这个当然是我们高年级后续课程要学到的
一门课程里头会告诉你呢
在你程序运行的时候
计算机的那个操作系统
它会把命令行上跟的那个内容
送给你的程序
所以你的程序运行的时候
在argv这个数组里头
它是有内容的
其中第一个元素或者说0号元素
它的内容是一个字符串
这个字符串的内容是ex2.exe
就是你这个执行的程序的名字
1号元素argv1就是你的第一个参数
那就是4
这个地方4是双引号引起来的
因为它字符串嘛
同理 下标为2的那个元素
它也是个字符串
它是5
那么可以看到
你运行的时候一共是有三个参数
所以argc它的值是3
这个3呢它实际上包含了你输入的两个参数4跟5
也还包含了ex2.exe这个程序名字本身
所以是三个
那么其中4跟5是你送进去的
而第一个呢下标为零的那个是程序的名字
这就是这个命令行参数的含义
希望大家能够把它理解记忆下来
那么当然我们刚才是在这个命令行上运行它的时候你去输入的
我们知道程序不可能不出错 对吧
那当我们要对这样的程序用到argc argv这种程序
进行调试的时候
我什么时候输入这个参数呢
特别是当我在ide这种集成环境下调试的时候
我什么时候有机会去输入这个命令行参数呢
这是个问题
下面这个我们给出两个例子
在这个大家看到的上半部分是Dev C++这个集成环境
去输入命令行参数用于调试的方法
可以看到你要去选择debug菜单
去选择参数这样的菜单项
然后在对话框里头输入4 5这样的一个命令行参数
那么设置好这个之后
你就可以在集成环境里头去一步步执行你的程序
那么呢这个你输入的参数就自动地送到argc argv这个里头去了
你如果是vc 就是下半部分大家看到的
在它的这个工程属性里头会有一个调试这样一个选单
在那个选项单里头你可以看到
它里头有一个可执行调试对话里头它有一个程序变量
那么把4跟5送到这里头去
将来呢 你设置好之后
你在vc环境下面去进行单步跟踪时候
这两个参数4跟5就送到你的argv里头去了
这是这两个集成环境
至于你用的是其它的这种集成环境
我想它的帮助文档会详细告诉你
怎么输入这个命令行参数
这个工作呢留给大家课后自己去练习
那么比如说我运行之后
刚才那个ex2这个程序
我不输入参数会咋样呢
好 大家看下面这个结果
在这个里头我们先试了一遍把4跟5输入进去
这个时候正常输出是个9
但是如果我不输入
直接ex2一回车
那你会看到出现了一个
我们叫做程序崩溃的那样一个画面
它叫应用程序出现错误
然后里头说什么内存不能读什么不能写
这个会导致一个程序崩溃的一个后果
所以如果你有参数的要求
然后你又在运行的时候不输入
那它就会出现这种崩溃
那这岂不是一个有很大隐患的一种技巧吗
不是技巧有隐患 而是你的代码有隐患
什么意思
只要我们重新地改造一下我们的程序代码
这个隐患就会消掉
怎么消掉呢 怎么去掉这个隐患呢
下面这个示例的截图就告诉我们
运行时的这个隐患是怎么消掉的
我们用框框把它框出来
可以看一个紫色的方框 框出几行代码
你可以看到在main函数的最开始我们对argc argv做了检查
if (argc != 3)
那就是我要求你输入两个参数嘛 对不对
再带上程序的名字这个参数
相当于是有三个参数
所以argc如果不等于3
那就意味着你没有按照我的要求给我提供两个整数
是吧
if它不等于那怎么办呢
那我就告诉你我应该怎么去使用
对吧
所以这个里头cout一个提示信息告诉你呢
必须是有两个参数输进来 我的程序才能运行
如果你不是三个 那怎么办呢
我就直接return了
通常情况下 在main函数里头return 0表示没有错误
return1 return非0表示它有错误
所以我们这个里头就直接return1了
这个值可以是一个非0的任意值
表示它在我们编程的时候约定俗成
一个非零的值表示有问题
这个值你自己去选择就好了
一般我们选的就是1或者有的人甚至选的是-1
这个问题不大 只要你明白它表达这么一个意思就行了
所以 如果argc不等于3 就意味着你没有按照我的要求来
我就直接退出了
所以它不会出现崩溃
也就是说 加了这个方框里头代码之后
你再去直接敲exe2它就不会出现崩溃错误
而只是一种默默的退出
告诉你个提示信息之后就什么也不干
-1.0 课程定位、教学内容
-1.0 课程定位、教学内容--作业
-1.1 编程环境与工具
--源程序拆分
-1.2 main函数的命令行参数
-作业一--作业
-2.1 变量定义
--变量定义
-2.2 变量的初始化、类型推导与基于范围的循环
-2.3 函数重载
--函数重载
-2.4 函数参数的缺省值与追踪返回类型的函数
-2.5 类的定义
--类的定义
-2.6 类成员的访问权限与友元
-第二讲 基础语法(1)--作业二
-3.1 构造函数析构函数
--构造函数析构函数
-3.2 赋值运算符重载
--赋值运算符重载
-3.3 流运算符重载
--流运算符重载
-3.4 函数运算符重载
--函数运算符重载
-3.5 下标运算符与自增减运算符重载
-3.6 静态成员与常量成员
-3.7 对象组合
--对象组合
-3.8 移动构造函数
--Video
--Video
-3.9 default修饰符
--Video
-第三讲 基础语法(2)--作业三
-4.1 继承
--Video
-4.2 函数重写
--Video
-4.3 虚函数
--Video
--Video
-4.4 自动类型转换
--Video
-4.5 禁止自动类型转换
--Video
-4.6 强制类型转换
--Video
-4.7 函数模板
--Video
-4.8 类模板
--Video
-4.9 成员函数模板
--Video
-4.10 模板特化
--Video
-作业四--作业
-5.0 引言
--Video
-5.1 从FOP到OOP
--Video
-5.2 对象在哪里
--Video
-5.3 接口在哪儿
--Video
-5.4 实现接口
--Video
-5.5 变与不变:多态的威力
--Video
-6.0 引言
--讨论
-6.1 从负载监视器的设计开始
-6.2 接口的分离与单一责任原则
-6.3 委托与接口的进一步分解
-6.4 分离不同层面的可变性
-7.0 引言
--Video
-7.1 迭代器
--Video
-7.2 迭代器的实现
--Video
-7.3 迭代器与模板
--Video
-7.4 算法与数据的解耦
--Video
-7.5 抽象结构与类模板
--Video
-7.6 函数对象与算法分解
--Video
-7.7 基于模板的策略模式
--Video
-8.0 引言
--Video
-8.1 已有资源的组合
--Video
-8.2 适当引入接口
--Video
-8.3 接口不变时的功能变化
--Video
-8.4 装饰
--Video
-8.5 责任的传递与责任链
--Video
-8.X 小结
--Video
-9.0 引言
--Video
-9.1 通过封装增加隔离、应对变化
--Video
--Video
-9.2 增加抽象层,应对变化
--Video
--Video
-9.3 相互关联对象的创建
--Video
-9.4 示例:自动组卷系统设计
--Video
-9.5 设计思路(上)
--Video
-9.6 设计思路(中)
--Video
-9.7 设计思路(下)
--Video
-9.X 小结
--Video
-课程总结
--Video
-期末考试--作业