1. 程式人生 > >一個命令列引數解析器

一個命令列引數解析器

    因工作需要寫一個console工具程式,執行引數很多,記得linux下有一個系統函式getopt可以很好得幫助程式設計師解析命令列引數,但是在VC中沒有這個函式,研究了下linux中對該函式的幫助資訊和標頭檔案getopt.h,重新實現了getopt和getopt_long這兩個函式,因為沒有讀過linux下getopt這個函式的原始碼,所以這個函式肯定不夠完善,不過經過試用,還是能夠滿足我個人需求的,這裡把原始碼貼出來,也請熟悉或者讀過getopt原始碼的朋友指正。 GetOpt.h
/******************************************************************************

* 

*   Filename:           GetOpt.h

* 

*   Description:       命令列引數解析器 

* 

*   Date:              2008-06-19

* 

*   Author:            常海龍          (Email:[email protected]) 

*

*                             Copyright (c) 2008 常海龍

* 

*******************************************************************************/ 





#ifdef __cplusplus

extern"C" {

#endif



extern int optind;               //再次再次呼叫 getopt() 時的下一個 argv 指標的索引

extern int optopt;              //最後一個已知選項

extern char* optarg;         //指向當前選項引數(如果有)的指標



extern int getopt( int argc, char *const argv[], const char *shortopts);



#ifdef __cplusplus

}

#endif



#ifdef __cplusplus

extern"C" {

#endif



struct option 

{

    char *name;                 //指向長選項名稱的指標   

    int has_arg;                 //表示選項是否有引數

    int *flag;               

    int val;                        //表示選項的短引數

};



extern int getopt_long (int argc, char *const argv[],

						const char *shortopts, const struct option *longopts, 

						int *longind);



#ifdef __cplusplus

}

#endif





#define     no_argument         0

#define     required_argument   1

#define     optional_argument   2







#define CASE_SENSITIVE		//定義引數處理器是否大小寫敏感
GetOpt.c
/******************************************************************************

* 

*   Filename:		GetOpt.c 

* 

*   Description:	命令列引數解析器 

* 

*   Date:                  2008-06-19

* 

*   Author:               常海龍      (Email:[email protected]) 

*

*			         Copyright (c) 2008 常海龍

* 

*******************************************************************************/ 



#include"GetOpt.h"

#include"string.h"



int optind = 1;             //即將進行掃描的引數在argv[]中的索引



//存放解析後返回值如果某一個argument無效,返回'?',該值存放argument

int optopt;					



char* optarg;               //如果當前引數有後續引數,該值指向這個後續引數



///////////////////////////////////////////////////////////////////////////////



int paser_shotops(int argc,char *const argv[],

                  size_t length,                //欲解析的argument項的長度

                  char *item_cont,              //存放欲解析的argument

                  const char *shortopts         

                  )

{

	char *pos = NULL;                           



	if(length == 2 && item_cont[0] == '-')      //如果符合  -h  這樣的條件就可進行解析

	{

		pos = strchr(shortopts,item_cont[1]);   //當前argument在shortopts中出現的起始位置



		if(NULL == pos)

		{

			optind++;                           //如果在shortopts中找不到,則返回'?'

			optopt = item_cont[1];

			return '?';

		}

		else

		{

			if(*(++pos) == ':')                 //如果該項帶有後續引數,用optarg儲存

				optarg = argv[++optind];



			optind++;

			return item_cont[1];

		}   

	}

	else                                        //如果不符合解析的條件,返回'?'

	{

		optopt = item_cont[0];

		optind = argc;

		return '?';

	}

}



///////////////////////////////////////////////////////////////////////////////



int paser_longopts(int argc, char *const argv[],

				   size_t length,                   //欲解析的argument項的長度

				   char *item_cont,             //存放欲解析的argument

				   const char *shortopts,

				   const struct option *longopts

                   )

{

	char *assist_arg = NULL;                          //輔助字串



    int long_index = 0;                                        //longopts的索引



    //如果欲解析的argument長度大於2,並且第一,二個字元都是'-'

	if( (length > 2) && (item_cont[0] == '-') && (item_cont[1] == '-'))

	{



        //迴圈longopts,查詢和當前引數匹配的專案

		while(longopts[long_index].name != NULL)

		{

			if(strcmp(item_cont+2,longopts[long_index].name) == 0)

			{

				if(longopts[long_index].has_arg == required_argument)

					optarg = argv[++optind];



				if(longopts[long_index].has_arg == optional_argument)

				{

                    //因為是可選後續引數,首先取得後續引數,然後判斷

					assist_arg = argv[optind + 1];



					if(assist_arg[0] != '-')

					{

						optarg = assist_arg;

						++optind;

					}

				}



                //在longopts中找到匹配項後,返回val值

				optopt = longopts[long_index].val;

				optind++;



				return optopt;

			}

			else

				long_index++;

		}

        //如果在longopts中沒有匹配項,則進行提示並繼續解析後面的引數

        optopt = item_cont[2];

        ++optind;

		return '?';

	}

	else 

        //對短引數項進行解析

		return paser_shotops(argc,argv,length,item_cont,shortopts);

}



///////////////////////////////////////////////////////////////////////////////



int getopt( int argc, char *const argv[], const char *shortopts )

{   



	char *arg_item = NULL;



	size_t len = 0;



	if(argc == 1)

		return -1;

	else

	{

		for(; optind < argc; optind++)

		{

			arg_item = argv[optind];



			len = strlen(arg_item);



#ifndef CASE_SENSITIVE



			arg_item = strlwr(arg_item);



#endif

			return paser_shotops(argc,argv,len,arg_item,shortopts);



		}



        optind = 1;                   //如果解析完畢,在最後將optind重置為1

		return -1;

	}

}



///////////////////////////////////////////////////////////////////////////////



int getopt_long (int argc, char *const argv[],

				 const char *shortopts, const struct option *longopts, 

				 int *longind)

{

    char *pos = NULL;



    char *arg_item = NULL;



	size_t len = 0;



    if(argc == 1)

        return -1;

    else

    {

        for(; optind < argc; optind++)

        {

            arg_item = argv[optind];



			len = strlen(arg_item);



#ifndef CASE_SENSITIVE

			

			arg_item = strlwr(arg_item);



#endif

                        //在與解析的引數項後面加0,方便字串的操作

			*(arg_item+len) = 0;



			return paser_longopts(argc,argv,len,arg_item,shortopts,longopts);



        }



            optind = 1;                     //如果解析完畢,在最後將optind重置為1

	    return -1;

    }

}



///////////////////////////////////////////////////////////////////////////////

相關推薦

一個命令引數解析

    因工作需要寫一個console工具程式,執行引數很多,記得linux下有一個系統函式getopt可以很好得幫助程式設計師解析命令列引數,但是在VC中沒有這個函式,研究了下linux中對該函式的幫助資訊和標頭檔案g

C++ 命令引數解析

文章目錄 說明 短引數之 getopt() 長引數之 getopt_long() 長引數之 getopt_long_only() 說明 主要參考以下部落格: 部落格一:getopt和g

【tensorflow】命令引數解析

1. tf.app.flags,用於支援接受命令列傳遞引數 import tensorflow as tf #第一個是引數名稱,第二個引數是預設值,第三個是引數描述 tf.app.flags.DEFINE_string('str_name', 'def_v_1',"descrip1")

golang命令引數解析

package main import ( "fmt" "os" ) func main(){ s:= os.Args fmt.Println(s) }   直接執行 輸出結果:[C:\Users\Administrator\AppData\Local\Temp\___go_bui

python命令引數解析

一、getopt模組  getopt.getopt(args, options[, long_options]) args為需要解析的命令列引數列表,一般為sys.argv[1:],這是因為argv[0]為指令碼的路徑。 options為希望識別的引數,如果該命令列引數

python 命令引數解析 argparse簡單分析

在python 2.7 後,不推薦使用 optparse, 而推薦使用 argparse. 其它的不多說,簡單的分析下我遇到的問題:我是想用 argparse 來解析不定長的命令列引數 例如: import argparse import sys parser = ar

命令引數解析

對這種主函式形式一直不是很瞭解,今天研究了一下,所得如下: 當我們成功執行一個程式時,在Windows環境下會生成一個exe檔案,我們可以再命令列中開啟並執行這個程式。 比如說如下程式碼。 #

Golang: 使用flag包進行命令引數解析

最近在使用go開發cli(command-line-interface)時,通過對於官方文件以及他人部落格的學習,在此寫下個人認為更適合自己往後回顧的關於flag的使用說明。 工欲善其事必先利其器,先奉上flag官方文件解析 Demo0: pack

ffmpeg 原始碼學習 -- 之命令引數解析

ffmpeg 原始碼學習 -- 之ffmpeg命令列引數解析 大家通過git在安裝好cygwin之後,下載原始碼到(cygwin)home目錄,通過./configure  ...... ,可以新增一堆引數選項,執行可以生成config.mk等編譯使用的檔案,通過命令對工

Tensorflow:tf.app.run()與命令引數解析

首先給出一段常見的程式碼: if __name__ == '__main__': tf.app.run()12 它是函式入口,通過處理flag解析,然後執行main函式(或者接下來提到的xxx())(最後含有tf.app.run()的檔案,在此行之前肯定能找到def main

Python命令引數解析模組argparse

當寫一個Python指令碼時經常會遇到不同引數不同功能的情況,如何做一個更好看的命令幫助資訊以及對命令引數解析呢? 這就需要使用argparse模組 #!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os impor

命令引數解析函式getopt_long() 使用詳解

當一個用C語言編寫的Linux或UNIX程式執行時,它是從main函式開始的。對這些程式而言,main函式的宣告如下所示: int main(int argc, char *argv[]) 其中argc是程式引數的個數(int),argv是一個代表引數自身的

getopt(win32) -- 命令引數解析函式

GNU libc提供了getopt和getopt_long用於解析命令列引數,很好用,想在windows下使用,就google了幾個win32下的C/C++寫得getopt,並作了一些比較。 程式裡往往會有許多開關的,執行時就要傳入許多引數值來開啟或關閉這些開關。以前

命令引數解析函式--getopt

原型: #include <unistd.h> int getopt(int argc, char * const argv[], const char *optstring); 該函式的argc和argv引數通常直接從main()的引數直接傳遞而來。opt

C 語言命令引數解析

C語言原始碼必須有且只有一個的函式是main函式,我們知道函式可以有引數,那麼main函式有沒有引數呢? 顯然是有的,而且它是固定的,只有兩個,第一個是整型變數(argc),第二個是字元型指標陣列(a

gflags(google開源的一套命令引數解析工具)

gflags是google開源的一套命令列引數解析工具,比getopt()函式功能要強大,使用起來更加方便,gflags還支援從環境變數和配置檔案中讀取引數。目前有C++和Python版本。本文就來詳細介紹C++版本gflags的使用,主要分如下兩個部分 Cont

使用Apache commons-cli包進行命令引數解析

Apache的commons-cli包是專門用於解析命令列引數格式的包。 依賴: <dependency> <groupId>commons-cli</groupId> <artifactId&g

linux命令引數解析學習心得

轉載出處:blog.csdn.net/bailyzheng/article/details/8048733 最近用到一個命令列工具,之前也一直說想把命令列引數解析看一下,今天算是做一個小的總結。 命令列引數解析分類:單個字元的引數(-a -b),還有字串引數(--vide

linux命令引數解析函式 getopt

在學習開原始碼過程中,經常遇到命令列解析函式 getopt,網上查閱了一些資料,總結一下。 說到命令列解析,最簡單的方式就是利用c語言main函式的兩個引數argc和argv來實現,當 C 執行時庫程式啟動程式碼呼叫 main() 時,會將命令列的引數傳過來,引數個數放在a

java命令引數解析

import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.Options; import