程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++: Command Line Processing,lineprocessing

C++: Command Line Processing,lineprocessing

編輯:C++入門知識

C++: Command Line Processing,lineprocessing


Save this code here for studying and using it. 

Surce code is here. 

CmdLine.h File

#pragma once
#include "unicodemacro.h"
#include <vector>
#include <map>


namespace Utility 
{

    // handy little container for our argument vector
    struct   CmdParam {
        std::vector<tstring> strings_;
    };

    /**
    A utility for parsing command lines.

    This was originally written by Chris Losinger, changes were simply
    removing the inheritance from std::map<>, and adding a map as a member
    variable instead. then all the VCF related String was replaced with 
    tstring and can suite both unicode and non-unicode string

    Example :

    Our example application uses a command line that has two
    required switches and two optional switches. The app should abort
    if the required switches are not present and continue with default
    values if the optional switches are not present.

    Sample command line :
    MyApp.exe -p1 text1 text2 -p2 "this is a big argument" -opt1 -55 -opt2

    Switches -p1 and -p2 are required.
    p1 has two arguments and p2 has one.

    Switches -opt1 and -opt2 are optional.
    opt1 requires a numeric argument.
    opt2 has no arguments.

    Also, assume that the app displays a 'help' screen if the '-h' switch
    is present on the command line.

    \code
#include "cmdline.h"
using namespace Utility;
using namespace std;
void show_help()
{
    tcout<< _T("This is a help string") <<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    CommandLine cmdLine;
    // parse argc,argv
    if (cmdLine.SplitLine(argc, argv) < 1)
    {
        // no switches were given on the command line, abort
        ASSERT(0);
        exit(-1);
    }

    // test for the 'help' case
    if (cmdLine.HasSwitch( _T("-h") ) )
    {
        show_help();
        exit(0);
    }

    // get the required arguments
    tstring p1_1, p1_2, p2_1;
    try
    {
        // if any of these fail, we'll end up in the catch() block
        p1_1 = cmdLine.GetArgument( _T("-p1") , 0);
        p1_2 = cmdLine.GetArgument( _T("-p1") , 1);
        p2_1 = cmdLine.GetArgument( _T("-p2") , 0);

    }
    catch (...)
    {
        // one of the required arguments was missing, abort
        ASSERT(0);
        exit(-1);
    }

    // get the optional parameters

    // convert to an int, default to '-1'
    int iOpt1Val =    tstoi( cmdLine.GetSafeArgument( _T("-optInt"), 0, _T("-1") ).c_str() );
    tcout<<iOpt1Val<<endl;
    return 0;
}
    \endcode
    @version 1.0 Chris Losinger
    @version 2.0 Jim Crafton
    @version 3.0 Marshall Wei
    */
    class   CommandLine 
    {
    public:
        typedef std::map<tstring, CmdParam> CommandLineMap;
        typedef std::vector<tstring> CommandLineVector;

        CommandLine() {}
        virtual ~CommandLine() {}
        /**
        parse the command line into switches and arguments.
        @return int number of switches found
        */
        int SplitLine( int argc, TCHAR **argv );

        int SplitLine( const tstring& commandLine );

        int SplitLine( const std::vector<tstring>& commandLine );

        /**
        was the switch found on the command line ?
        \code
        ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5

        call                          return
        ----                          ------
        cmdLine.HasSwitch("-a")       true
        cmdLine.HasSwitch("-z")       false
        \endcode
        @return bool true if it has the swith, otherwise false
        */
        bool HasSwitch( const tstring& aSwitch ) const ;

        /**
        fetch an argument associated with a switch . if the parameter at
        index iIdx is not found, this will return the default that you
        provide.

        example :
        \code
        command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5

        call                                      return
        ----                                      ------
        cmdLine.GetSafeArgument("-a", 0, "zz")    p1
        cmdLine.GetSafeArgument("-a", 1, "zz")    p2
        cmdLine.GetSafeArgument("-b", 0, "zz")    p4
        cmdLine.GetSafeArgument("-b", 1, "zz")    zz
        \endcode
        */

        tstring GetSafeArgument(const tstring& aSwitch, size_t iIdx, const tstring& aDefault) const;

        /**
        fetch a argument associated with a switch. throws an exception
        of (int)0, if the parameter at index iIdx is not found.

        example :
        \code
        command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5

        call                             return
        ----                             ------
        cmdLine.GetArgument("-a", 0)     p1
        cmdLine.GetArgument("-b", 1)     throws (int)0, returns an empty string
        \endcode
        */
        tstring GetArgument( const tstring& aSwitch, size_t iIdx ) const;

        tstring GetArgument( size_t index ) const;

        /**
        @return the number of arguments found for a given switch. -1 if the
        switch was not found
        */
        int GetArgumentCount(const tstring& aSwitch) const;

        size_t GetArgCount() const {
            return m_originalCommandLine.size();
        }

        const std::vector<tstring>& GetOriginalCommandLine() const 
        {
            return m_originalCommandLine;
        }
    protected:
        /**
        protected member function
        test a parameter to see if it's a switch :
        switches are of the form : -x
        where 'x' is one or more characters.
        the first character of a switch must be non-numeric!
        */
        bool IsSwitch(const tstring& param) const;

        CommandLineMap            m_commandLine;
        CommandLineVector         m_originalCommandLine;
    };
    
}

 

CmdLine.cpp file

#include "stdafx.h"
#include "cmdline.h"


using namespace std;

namespace Utility
{
    int CommandLine::SplitLine( const std::vector<tstring>& commandLine )
    {
        m_commandLine.clear();
        m_originalCommandLine.clear();

        m_originalCommandLine = commandLine;

        tstring curParam; // current argv[x]
        size_t argc = m_originalCommandLine.size();
        // skip the exe name (start with i = 1)
        for (size_t i = 1; i < argc; i++)  {
            // if it's a switch, start a new CommandLine
            if ( IsSwitch(m_originalCommandLine[i]))  {
                curParam = m_originalCommandLine[i];

                tstring arg;

                // look at next input tstring to see if it's a switch or an argument
                if (i + 1 < argc)  {
                    if (!IsSwitch(m_originalCommandLine[i + 1])) {
                        // it's an argument, not a switch
                        arg = m_originalCommandLine[i + 1];

                        // skip to next
                        i++;
                    }
                    else {
                        arg = _T("");
                    }
                }

                // add it
                CmdParam cmd;

                // only add non-empty args
                if (arg != _T("") )  {
                    cmd.strings_.push_back(arg);
                }

                // add the CmdParam to 'this'
                std::pair<CommandLineMap::iterator, bool> res = m_commandLine.insert(CommandLineMap::value_type(curParam, cmd));

            }
            else  {
                // it's not a new switch, so it must be more stuff for the last switch

                // ...let's add it
                CommandLineMap::iterator theIterator;

                // get an iterator for the current param
                theIterator = m_commandLine.find(curParam);
                if (theIterator!=m_commandLine.end())  {
                    (*theIterator).second.strings_.push_back(m_originalCommandLine[i]);
                }
                else  {
                    // ??
                }
            }
        }

        return static_cast<int>( m_commandLine.size() );
    }


    int CommandLine::SplitLine( int argc, TCHAR **argv )
    {
        std::vector<tstring> args;

        for ( int j=0;j<argc;j++ ) {
            args.push_back( tstring(argv[j]) );
        }

        return SplitLine( args );
    }

    int CommandLine::SplitLine( const tstring& commandLine )
    {
        std::vector<tstring> args;
        const TCHAR* P = commandLine.c_str();
        const TCHAR* start = P;
        const TCHAR* argStart = P;

        int sz = static_cast<int>( commandLine.size() );
        while ( (P - start) < sz ) {
            if ( *P == '\"' ) {
                P++;
                while ( ((P - start) < sz) && (*P != '\"' ) ) {
                    P++;
                }
                P++;
            }

            if ( *P == '\"' ) {
                continue; //loop again
            }

            if ( *P == ' ' ) {
                //argument
                //strip out begin/end quotes

                tstring arg;
                const TCHAR* tmpArgStart = argStart;
                const TCHAR* tmpArgEnd = tmpArgStart;
                while ( tmpArgEnd < P ) {
                    if ( *tmpArgEnd == '\"' ) {
                        if ( tmpArgStart != tmpArgEnd ) {
                            arg.append( tmpArgStart, tmpArgEnd - tmpArgStart );
                            tmpArgStart = tmpArgEnd;
                        }
                        tmpArgStart++;                    
                    }

                    tmpArgEnd ++;
                }

                if ( arg.empty() ) {
                    arg.append( tmpArgStart, tmpArgEnd - tmpArgStart );
                }

                args.push_back( arg );

                while ( (*P == ' ') && ((P - start) < sz) ) {
                    P++;
                }
                argStart = P;
                P--;
            }

            P++;
        }
        if ( argStart < P ) {
            tstring arg;
            arg.assign( argStart, P-argStart );
            args.push_back( arg );
        }

        return SplitLine( args );
    }


    bool CommandLine::IsSwitch(const tstring& aParam) const
    {
        if (aParam.empty())
            return false;

        // switches must non-empty
        // must have at least one character after the '-'

        if (aParam.size() <= 1)  {
            return false;
        }

        // switches always start with '-'
        if (aParam[0]=='-')   {
            // allow negative numbers as arguments.
            // ie., don't count them as switches
            return (!isdigit(aParam[1]));
        }
        else   {
            return false;
        }
    }


    bool CommandLine::HasSwitch(const tstring& aSwitch) const
    {
        CommandLineMap::const_iterator theIterator;
        theIterator = m_commandLine.find(aSwitch);
        return (theIterator != m_commandLine.end());
    }


    tstring CommandLine::GetSafeArgument(const tstring& aSwitch, size_t index, const tstring& defaultVal) const
    {
        tstring result;

        if ( !defaultVal.empty() ) {
            result = defaultVal;
        }

        try
        {
            result = GetArgument(aSwitch, index);
        }
        catch (...)
        {
        }

        return result;
    }


    tstring CommandLine::GetArgument( size_t index ) const
    {
        tstring result;
        if ( (index >= 0) && (index < m_originalCommandLine.size()) ) {
            result = m_originalCommandLine[index];
        }
        return result;
    }

    tstring CommandLine::GetArgument( const tstring& aSwitch, size_t index )const 
    {
        if ( HasSwitch( aSwitch ) )
        {
            CommandLineMap::const_iterator theIterator = m_commandLine.find(aSwitch);
            if (theIterator!=m_commandLine.end())
            {
                if ((*theIterator).second.strings_.size() > index)
                {
                    return (*theIterator).second.strings_[index];
                }
            }
        }

        throw (int)0;

        return _T("");
    }


    int CommandLine::GetArgumentCount(const tstring& aSwitch) const
    {
        int result = -1;

        if ( HasSwitch(aSwitch) )  {
            CommandLineMap::const_iterator theIterator = m_commandLine.find( aSwitch );
            if (theIterator!=m_commandLine.end())      {
                result = static_cast<int>( (*theIterator).second.strings_.size() );
            }
        }

        return result;
    }
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved