C++控制台程序的命令行参数输入-且支持参数opts扩展

 C++控制台程序的命令行参数输入

1. C/C++语言中的main函数,经常带有参数argc,argv,如下:

int main(int argc, char** argv)
int main(int argc, char* argv[])

  argc(第一个形参)必须是整型变量,标识该控制台命令调用中接收到的参数个数,注意,包括该命令程序名字itself。

  argv( 第二个形参)必须是指向字符串的指针数组,用于保存argc个参数的具体数据。注意数组起始索引为0开始,到argc-1结束。即:argv[0]为命令行中可执行程序名本身,argv[1]为命令行中第二个参数的内容,依次类推。

加上形参说明后,因此C程序中的main函数的函数头应写为:

 main (int argc,char *argv[])

2. 控制台程序参数获取

  由于main函数不能被其它函数调用,因此不可能在程序内部取得实际值。那么,在何处把实参值赋予main函数的形参呢? 实际上,main函数的参数值是从操作系统命令行上获得的。

  如何在操作系统命令行获取参数呢?

(1)在VS中设置时右键项目->属性->调试->命令参数,在命令参数中添加所需参数,字符串之间用空格分开即可。如果是.txt文件,要放在当前目录下(.cpp所在目录)【实质为exe生成目录位置】,不然找不到。

 

 

(2)或者:假如你的程序是hello.exe,如果在命令行运行该程序,(首先应该在命令行下用 cd 命令进入到 hello.exe 文件所在目录) 运行命令为:

hello.exe data.txt //.txt也在.exe所在目录下

 

  注意:调用控制台程序命令行中输入的参数在位置上,并没有与控制台程序main函数中 的两个形参 一 一 对应的。 因为,main的形参只有二个,而命令行中的参数个数原则上未加限制。argc参数表示了命令行中参数的个数(注意:文件名本身也算一个参数),argc的值是在输入命令行时由系统按实际参数的个数自动赋予的,即,argv[0]为命令行中可执行程序名本身,argv[1]为命令行中第二个参数的内容,依次类推

 

  在调用一个可执行程序时,某些情况下需要向程序传递参数。如我们可以在控制台中键入notepad.exe,回车后将执行记事本程序。

  如果我们希望在打开notepad时同时打开一个文本文件,可以在notepad.exe 。后面跟上文件的路径和名字,如notepad.exe   example.txt(文件在当前路径) 

   

   那么程序中如何能得到这些输入参数呢?这个工作是编译器帮我们完成的,编译器将输入参数的信息放入main函数的参数列表中。  

  main函数的参数列表保存了输入参数的信息,第一个参数argc记录了输入参数的个数,  第二个参数是字符串数组的,字符串数组的每个单元是char*类型的,指向一个c风格字符串。  

例子如下:

notepad.exe   example.txt   data.txt   train.txt 
第一个参数    第二个参数   第三个参数  第四个参数
因此:argc = 4

 控制台执行上面程序后,程序读取main函数参数为:   argc是4,就是说argv数组中有四个有效单元  

   argv数组中的第一个单元指向的字符串总是可执行程序的名字,以后的单元指向的字符串依次是程序调用时的参数。

   第一单元argv[0]指向的字符串是"notepad.exe"  
   第二单元argv[1]指向的字符串是"example.txt"  
   第三单元argv[2]指向的字符串是"data.txt"  
   第四单元argv[3]指向的字符串是"train.txt"  

  `上述这个赋值过程是编译器自动完成的,我们只需要利用argc,argv[]读出数据就可以了。

 

3. 简单示例,控制台程序的不同调用方法,及输出结果:

复制代码
int main(int argc, char* argv[])
{
    cout << "参数个数:" << argc << endl;
    cout << "参数内容:";
    for (int i = 0; i < argc; ++i)
    {
        cout << argv[i] << endl;
    }

    //std::cout << "Hello World!\n";
    system("pause");
}
复制代码

(1) 控制台调用:

1、按住Shift键,鼠标右键快捷方式,先打开Powershell窗口。
2、输入 start cmd 回车
3、这样就可以打开cmd窗口了,并且cmd的工作目录就是当前的目录。

输入命令行:

ProjectTest.exe 1111 zhongguo renmin 传见过 中国人民解放拒绝

输出:

 

 

(2)利用VSIDE中的控制台参数进行调用:

 

 程序:

复制代码
#include <iostream>

int main(int argc, char **argv)
{
    while (argc-- > 0)
    {
        //printf("argv[%d]:%s\n", argc, argv[argc]);
        printf("argc:%d,*argv++:%s\n", argc,*argv++);
        //printf("argc:%d,*++argv:%s\n", *++argv);

    }
}
复制代码

在VS中设置设置 comant argument:

不进行设置时:

 

 

 

设置参数时: 

 

 (3)批处理脚本中.bat文件中,调用可执行文件

 

 

 

 

 

  编辑“main测试.bat”文件内容为:

ProjectTest  Jack 中国 boin747 1.234  3.3333 8888 zhongguo
pause

在cmd运行.bat文件

 

 

 

 双击:

 

 

   

  好像识别汉字出现了问题,这里只是测试,能达到示意main函数的传参即可,我就不深因了。

如果把汉字改为数字和字母,则运行效果如预期:

 

 4. 较为复杂的命令行程序,规范化输入,编写规范

  下面摘录一个例程,该程序用于取出在argv中的命令行选项。在例子中,将支持下列用法:

复制代码
//C/C++处理main()函数命令行
#include <iostream>
#include <vector>
#include <string>
#include <ctype.h>//调用atoi函数
using namespace std;

const char* const prog_name = "prog";
const char* const prog_version = "version 1.0 (2011/8/24)";

//退出函数
inline void usage(int exit_value = 0){
    cerr<<prog_name<<"  usage!"<<endl;
    exit(exit_value);
}

int main(int argc,char* argv[]){
    //声明用于记录用户指定选项的变量
    bool debug_on = false;
    bool ofile_on = false;
    bool limit_on = false;

    string ofile_name;//记录出现的输出文件名
    int limit = -1;//限制值
    vector <string> file_names;//记录文件名

    cout<<"argc:"<<argc<<endl;
    for(int i = 1;i < argc; ++i){//读取argv中的每个选项
        //输出第i+1个参量
        cout<<"argv["<<i<<"]:"<<argv[i]<<endl;

        char *pchar = argv[i];
        switch(pchar[0]){//确定选项类型:-h,-d,-v,-l,-o;或者其他
            case '-':{
                cout<<"case \'-\' found"<<endl;
                switch(pchar[1]){//确定用户指定的选项:h,d,v,l,o
                    case 'd'://处理调试:
                        cout<<"-d found:debugging turned on!"<<endl;
                        debug_on = true;
                        break;
                    case 'v'://处理版本请求
                        cout<<"-v found:version info displayed!"<<endl;
                        cout<<prog_name<<":"<<prog_version<<endl;
                        return 0;
                    case 'h'://处理帮助
                        cout<<"-h found:help info!"<<endl;
                        usage();
                    case 'o'://处理输出文件
                        cout<<"-o found:output file!"<<endl;
                        ofile_on = true;
                        break;
                    case 'l'://处理限制量
                        cout<<"-l found:resorce limit!"<<endl;
                        limit_on = true;
                        break;
                    default://无法识别的选项
                        cerr<<prog_name<<":error:unrecognition option -:"<<pchar<<endl;
                        usage(-1);
                }
                break;
            }
            default://不以'-'开头,是文件名
                if(ofile_on){//输出文件名
                    cout<<"file name:"<<pchar<<endl;
                    ofile_name = pchar;
                    ofile_on = false;//复位
                }
                else if(limit_on){//限制值
                    limit_on = false;
                    limit = atoi(pchar);
                    if(limit<0){
                        cerr<<prog_name<<":error:negative value for limit!"<<endl;
                        usage(-2);
                    }
                }
                else{//文件名
                    file_names.push_back(pchar);
                }
                break;
        }
    }
    if(file_names.empty()){
        cerr<<prog_name<<":error:no file for processing!"<<endl;
        usage(3);
    }
    else{
        cout<<(file_names.size() == 1 ? "File":"Files")<<
            " to be processed are the followed:"<<endl;
        for(int i = 0;i < file_names.size();++i){
            cout<<file_names[i]<<"\t"<<endl;
        }
    }
    if(limit != -1){
        cout<<"user-specified limit:"<<limit<<endl;
    }
    if(!ofile_name.empty()){
        cout<<"user-specified ofile:"<<ofile_name<<endl;
    }
    
}
复制代码

 

posted @ 2021-04-13 23:39  China Soft  阅读(3096)  评论(0编辑  收藏  举报