C/C++

コマンドライン文字列を解析(C, C++)

CommandLineToArgvW関数をUnicodeだけでなく、マルチバイト・プロジェクトでも使う。

Download: tCommandLineArgv.zip

書式

LPTSTR* _tCommandLineToArgv(
         __in   LPCTSTR  lpCmdLine,
         __out  int*     pNumArgs
);

lpCmdLine(入力)
NULLで終わるコマンドライン文字列へのポインタを指定する。GetCommandLine関数が返す値を直接渡す。
pNumArgs(出力)
解析した引数の数を受け取る整数変数へのポインタを指定する。

解説

CommandLineToArgvW関数を参照。引数リストが不要になったとき、その引数リストに使っているメモリを解放するには、LocalFree関数を一度呼び出す。

コード

#pragma once

#include <WinNls.h>
#include <WinBase.h>
#include <ShellAPI.h>

/*
// コマンドライン文字列を解析
//   CommandLineToArgvW関数をUnicodeだけでなく、マルチバイト・プロジェクトでも
//   使う。
//
// LPTSTR* _tCommandLineToArgv(
//        __in   LPCTSTR lpCmdLine,
//        __out  int*    pNumArgs
// );
//
// パラメータ:
//     CommandLineToArgvW関数と同様
// 戻り値:
//     CommandLineToArgvW関数と同様
//       ※CommandLineToArgvW関数と同様に、戻り値のLPTSTR*は、不要になれば
//         LocalFree関数でメモリを解放しなければならない。
*/
#ifdef _UNICODE  /* Unicode   */
#define _tCommandLineToArgv CommandLineToArgvW
#else            /* MultiByte */
#define _tCommandLineToArgv CommandLineToArgvA
LPTSTR* CommandLineToArgvA(
        __in   LPCSTR  lpCmdLine,
        __out  int*    pNumArgs
)
{
    int     iWCmdLineLength;
    LPWSTR  lpWCmdLine;
    LPWSTR* lpwszArgv;
    int     i, iMaxByte, iTempByte;
    LPSTR*  lpszArgv;

    /* MultiByte to WideChar */
    iWCmdLineLength = MultiByteToWideChar(
            CP_ACP,
            MB_PRECOMPOSED,
            (LPCSTR)lpCmdLine,
            -1,
            NULL,
            0
            );
    if (iWCmdLineLength == 0)
        goto ERROR1;
    lpWCmdLine = (LPWSTR)LocalAlloc(
            LPTR,
            iWCmdLineLength * sizeof(WCHAR)
            );
    if (lpWCmdLine == NULL)
        goto ERROR1;
    iWCmdLineLength = MultiByteToWideChar(
            CP_ACP,
            MB_PRECOMPOSED,
            lpCmdLine,
            -1,
            lpWCmdLine,
            iWCmdLineLength
            );
    if (iWCmdLineLength == 0)
        goto ERROR2;

    /* Exec CommandLineToArgvW() */
    lpwszArgv = CommandLineToArgvW(
            lpWCmdLine,
            pNumArgs
            );
    if (lpwszArgv == NULL)
        goto ERROR2;

    /* WideChar to MultiByte */
    iMaxByte = 0;
    for (i = 0; i < *pNumArgs; i++)
    {
        iTempByte = WideCharToMultiByte(
                CP_ACP,
                WC_NO_BEST_FIT_CHARS,
                lpwszArgv[i],
                -1,
                NULL,
                0,
                NULL,
                NULL
                );
        if (iTempByte == 0)
            goto ERROR3;
        if (iMaxByte < iTempByte)
            iMaxByte = iTempByte;
    }

    lpszArgv = (LPSTR*)LocalAlloc(
            LPTR,
            (*pNumArgs) * sizeof(LPSTR) + (*pNumArgs) * iMaxByte // Byte
            );
    if (lpszArgv == NULL)
        goto ERROR3;
    for (i = 0; i < *pNumArgs; i++)
    {
        lpszArgv[i] = (LPSTR)(
                ((LONG_PTR)lpszArgv) + (*pNumArgs) * sizeof(LPSTR) + i * iMaxByte
                );
        iTempByte = WideCharToMultiByte(
                CP_ACP,
                WC_NO_BEST_FIT_CHARS,
                lpwszArgv[i],
                -1,
                lpszArgv[i],
                iMaxByte,
                NULL,
                NULL
                );
        if (iTempByte == 0)
            goto ERROR3;
    }

    LocalFree(lpWCmdLine);
    LocalFree(lpwszArgv);
    return lpszArgv;


/*
// error
*/
ERROR3:
    LocalFree(lpwszArgv);
ERROR2:
    LocalFree(lpWCmdLine);
ERROR1:
    return NULL;
}
#endif