作業中のメモ

よく「計算機」を使って作業をする.知らなかったことを中心にまとめるつもり.

C 言語によるトークン取り出し

どうも,筆者です.

今回は,区切り文字を指定し,文字列を取り出す関数を作成した.ただ単に取り出すだけなら,標準関数の token を使えばよい.しかし,これは,データを破壊しつつ処理を行う.また,区切り文字だけを取り出すことができない. そこで,token を自作することにした.ただ,構成上,余分にメモリが必要となる.致し方なし.

構成

ここでは,以下の項目を満たすものを考える.

  • 文字列を指定した区切り文字で区切り,取り出す.
  • 区切り文字も 1 文字として取り出す.
  • 入力文字は小文字に変換する.
  • 入力する文字は,以下の 4 パターン(処理確認用)
    • 2 進数・・・ b から始まる 0,1 からなる文字列
    • 8 進数・・・ 0 から始まる 0 ~ 7 からなる文字列
    • 10 進数・・・ 0 のみ,または 0 以外から始まる 0 ~ 9 からなる文字列
    • 16 進数・・・ 0x から始まる 0 ~ 9,a ~ f からなる文字列

作成したモジュールの機能一覧

ここでは,以下の 5 つのモジュールを作成した.それぞれのモジュールの働きを示す.

  • checkNum
    • 働き:数値処理
    • 静的領域に確保されている文字列データを初期化する.
    • 静的領域に確保されている文字列データに対象とする文字列を設定する.
    • 2 進数かどうかを判定する.
    • 8 進数かどうかを判定する.
    • 10 進数かどうかを判定する.
    • 16 進数かどうかを判定する.
  • conversion
    • 働き:文字列変換処理
    • 指定した範囲にデータが存在するかどうかを判定する.
    • 大文字を小文字に変換する.
    • 文字列を 10 進数数値に変換する.
    • 10 進数数値を文字列に変換する.
  • splitStr
    • 働き:文字列加工処理
    • 静的領域に確保された構造体の要素を初期化する.
    • 誓敵領域に確保された構造体の要素である,探索文字列と区切り文字列を設定する.
    • 文字列を分割する.
  • stack
    • 働き:スタック制御処理
    • スタック領域を初期化する.
    • データをスタックに格納する.
    • スタックからデータを取り出す.
  • token
    • 働き:文字列分割処理
    • 文字列を区切り文字で分割する.

ヘッダー

以下に,実際に使用するヘッダーを示す.

共通ヘッダー

/* typedef.h */
#ifndef __TYPEDEF_H__
#define __TYPEDEF_H__
#include<stddef.h>

typedef void               VD;
typedef unsigned char      U1;
typedef signed char        I1;
typedef unsigned short int U2;
typedef signed short int   I2;
typedef unsigned long int  U4;
typedef signed long int    I4;
typedef char               CHR;
typedef char *             STR;
typedef int                INTEGER;
typedef enum {
    FALSE = 0,
    TRUE  = 1
} BOOLEAN;

/*
    2  進数は,b010111... のように b  から始まり 0,1       から成る文字列
    8  進数は,0123723... のように 0  から始まり 0~7       から成る文字列
    10 進数は,5387119... のように 数値          0~9       から成る文字列
    16 進数は,0x456ba... のように 0x から始まり 0~9,a~f から成る文字列
*/
#define MAX_STRING   (128)  /* 最大文字数       */
#define NULLSTR      ('\0') /* NULL 文字の定義  */
#define HEX_SIMBOL   ('x')  /* 16 進数の識別子  */
#define BIN_SIMBOL   ('b')  /* 2 進数の識別子   */
#define PLUS_SIGN    ('+')  /* プラスの識別子   */
#define MINUS_SIGN   ('-')  /* マイナスの識別子 */
#define INVBASENUM   (0)    /* 基底の無効値     */
#define BINARY_NUM   (2)    /* 基底 2           */
#define OCTAL_NUM    (8)    /* 基底 8           */
#define DECIMALNUM   (10)   /* 基底 10          */
#define HEXADCMNUM   (16)   /* 基底 16          */
#define POSITIVESIGN (1)    /* 正の符号         */
#define NEGATIVESIGN (-1)   /* 負の符号         */

#endif

数値処理ヘッダー

/* checkNum.h */
#ifndef __CHECKNUM_H__
#define __CHECKNUM_H__
#include"typedef.h"
#define MIN_NUM     ('0') /* 数値の最小値   */
#define BIN_MAX_NUM ('1') /* 2 進数の最大値 */
#define MAX_NUM     ('9') /* 数値の最大値   */
#define OCT_MAX_NUM ('7') /* 8 進数の最大値 */
#define MIN_ASCII   ('a') /* 16 進数の文字  */
#define MAX_ASCII   ('f') /* 16 進数の文字  */

/*
    初期化関数
    VD vdCheckStrInit(VD);
*/
VD vdCheckStrInit(VD);

/*
    文字列の設定

    VD vdSetString(STR szStr);
    (a1i) szStr: 探索対象の文字列
*/
VD vdSetString(STR szStr);

/*
    2 進数であるかどうかを判定
    BOOLEAN bIsBinary(VD);
    return: TRUE -> 2 進数である,FALSE -> 2 進数ではない
*/
BOOLEAN bIsBinary(VD);

/*
    8 進数であるかどうかを判定
    BOOLEAN bIsOctNum(VD);
    return: TRUE -> 8 進数である,FALSE -> 8 進数ではない
*/
BOOLEAN bIsOctNum(VD);

/*
    10 進数であるかどうかを判定
    BOOLEAN bIsDcmNum(VD);
    return: TRUE -> 10 進数である,FALSE -> 10 進数ではない
*/
BOOLEAN bIsDcmNum(VD);

/*
    16 進数であるかどうかを判定
    BOOLEAN bIsHexNum(VD);
    return: TRUE -> 16 進数である,FALSE -> 16 進数ではない
*/
BOOLEAN bIsHexNum(VD);

#endif

文字列変換処理

/* conversion.h */
#ifndef __CONVERSION_H__
#define __CONVERSION_H__
#include"typedef.h"

/*
    指定した範囲にデータが存在するかどうかを確認する関数
    BOOLEAN bExistRange(INTEGER iTargetVal, INTEGER iLowerVal, INTEGER iUpperVal);
    (a1i) iTargetVal: 対象とする値
    (a2i) iLowerVal:  下限値
    (a3i) iUpperVal:  上限値
    return: TRUE -> 範囲内,FALSE -> 範囲外
*/
BOOLEAN bExistRange(INTEGER iTargetVal, INTEGER iLowerVal, INTEGER iUpperVal);

/*
    大文字を小文字に変換
    CHR chCapital2Small(CHR chData);
    (a1i) chData: 対象文字
    return: 変換結果
*/
CHR chCapital2Small(CHR chData);

/*
    10 進数変換
    I4 i4ToDecimal(U1 u1StrLen, STR szStr, U1 u1Basis);
    (a1i) u1StrLen: 入力文字列の長さ
    (a2i) szStr:    入力文字列
    (a3i) u1Basis:  基底
    return: 10 進数の値
*/
I4 i4ToDecimal(U1 u1StrLen, STR szStr, U1 u1Basis);

/*
    10 進数から変換
    VD vdFromDecimal(I4 i4Data, U1 u1Basis, U1 *pu1StrLen, STR szStr);
    (a1i) i4Data:    変換前のデータ
    (a2i) u1Basis:   基底
    (a3o) pu1StrLen: 出力文字列の長さ
    (a4o) szStr:     出力文字列
*/
VD vdFromDecimal(I4 i4Data, U1 u1Basis, U1 *pu1StrLen, STR szStr);

#endif

文字列加工処理

/* splitStr.h */
#ifndef __SPLITSTR_H__
#define __SPLITSTR_H__
#include"typedef.h"

/*
    初期化関数
    VD vdSplitStrInit(VD);
*/
VD vdSplitStrInit(VD);

/*
    対象文字列と区切り文字列の設定
    VD vdSetStrDel(STR szTargetStr, U1 u1NumOfDelimiter, STR szDelimiterList);
    (a1i) szTargetStr:      対象文字列
    (a2i) u1NumOfDelimiter: 区切り文字の数
    (a3i) szDelimiterList:  区切り文字のリスト
*/
VD vdSetStrDel(STR szTargetStr, U1 u1NumOfDelimiter, STR szDelimiterList);

/*
    文字列分割関数
    BOOLEAN bSplitString(STR szSplitStr, U1 *pu1SplitStrLen, BOOLEAN bVartualExecution);
    (a1o) szSplitStr:        分割文字列
    (a2o) *pu1SplitStrLen:   分割文字列の長さ
    (a3i) bVartualExecution: TRUE -> 仮想実行,FALSE -> 実際に実行
    return: TRUE  -> 文字列の終端に達していない
            FALSE -> 文字列を最後まで読んだ
*/
BOOLEAN bSplitString(STR szSplitStr, U1 *pu1SplitStrLen, BOOLEAN bVartualExecution);

#endif

スタック制御処理

/* stack.h */
#ifndef __STACK_H__
#define __STACK_H__
#include"typedef.h"
#define MAX_STACK_SIZE (100)

/*
    スタックの初期化関数
    VD vdInitStack(VD);
*/
VD vdInitStack(VD);

/*
    格納関数
    BOOLEAN bPush(I2 i2Data);
    (a1i) i2Data: 格納する値
    return: TRUE -> 成功,FALSE -> 失敗
*/
BOOLEAN bPush(I2 i2Data);

/*
    取り出し関数
    BOOLEAN bPop(I2 *pi2Val);
    (aio) pi2Val: 取り出す値
    return: TRUE -> 成功,FALSE -> 失敗
*/
BOOLEAN bPop(I2 *pi2Val);

#endif

文字列分割処理

/* token.h */
#ifndef __TOKEN_H__
#define __TOKEN_H__
#include"typedef.h"

/*
    トークン分割する関数
    VD vdToken(STR szStr, U1 u1NumOfDelimiters, STR szDelimiterList)
    (a1i) szStr:             対象文字列
    (a2i) u1NumOfDelimiters: 区切り文字数
    (a3i) szDelimiterList:   区切り文字
*/
VD vdToken(STR szStr, U1 u1NumOfDelimiters, STR szDelimiterList);

#endif

ソースファイル

以下に,作成した C ファイルを示す.

check.c

#include"typedef.h"
#include"checkNum.h"

/* 計算対象の文字列 */
static CHR st_szString[MAX_STRING + 1];
/* 文字列の長さ */
static U1 st_u1StrLen;

/* プロトタイプ宣言(conversion.h) */
extern BOOLEAN bExistRange(INTEGER iTargetVal, INTEGER iLowerVal, INTEGER iUpperVal);
extern CHR chCapital2Small(CHR chData);

/*
    初期化関数
    VD vdCheckStrInit(VD);
*/
VD vdCheckStrInit(VD)
{
    U1 u1Cnt;

    st_u1StrLen = 0;

    for ( u1Cnt = 0 ; u1Cnt <= (U1)MAX_STRING ; u1Cnt++ )
    {
        st_szString[u1Cnt] = (CHR)NULLSTR;
    }

    return;
}

/*
    文字列の設定

    VD vdSetString(STR szStr);
    (a1i) szStr: 探索対象の文字列
*/
VD vdSetString(STR szStr)
{
    U1 u1Cnt = 0;

    if ( NULL != szStr )
    {
        /* ループを抜ける条件:終端文字に到達する,もしくは,カウントが配列サイズを超える */
        while ( (u1Cnt < (U1)MAX_STRING) && ((CHR)NULLSTR != szStr[u1Cnt]) )
        {
            st_szString[u1Cnt] = chCapital2Small(szStr[u1Cnt]);
            u1Cnt++;
        }
    }
    /* 終端文字を代入 */
    st_szString[u1Cnt] = (CHR)NULLSTR;
    /* 文字列の長さを保存 */
    st_u1StrLen = u1Cnt;

    return;
}

/*
    2 進数であるかどうかを判定
    BOOLEAN bIsBinary(VD);
    return: TRUE -> 2 進数である,FALSE -> 2 進数ではない
*/
BOOLEAN bIsBinary(VD)
{
    BOOLEAN bRetVal;
    U1 u1Cnt;

    /* 先頭が 2 進数のシンボルでない,若しくは 1 文字だけの場合 */
    if ( ((CHR)BIN_SIMBOL != st_szString[0]) || (st_u1StrLen < 2) )
    {
        bRetVal = FALSE;
    }
    else
    {
        bRetVal = TRUE;
        for ( u1Cnt = 1 ; u1Cnt < st_u1StrLen ; u1Cnt++ )
        {
            /* 0,1 のデータでない場合 */
            if ( FALSE == bExistRange((INTEGER)st_szString[u1Cnt], (INTEGER)MIN_NUM, (INTEGER)BIN_MAX_NUM) )
            {
                bRetVal = FALSE;
                break;
            }
        }
    }

    return bRetVal;
}

/*
    8 進数であるかどうかを判定
    BOOLEAN bIsOctNum(VD);
    return: TRUE -> 8 進数である,FALSE -> 8 進数ではない
*/
BOOLEAN bIsOctNum(VD)
{
    BOOLEAN bRetVal;
    U1 u1Cnt;

    /* 先頭が 0 ではない,もしくは 1 文字もない場合 */
    if ( ((CHR)MIN_NUM != st_szString[0]) || (st_u1StrLen < 1) )
    {
        bRetVal = FALSE;
    }
    /* 0 だけの場合 */
    else if ( (CHR)NULLSTR == st_szString[1] )
    {
        bRetVal = FALSE;
    }
    /* 8 進数の可能性がある場合 */
    else
    {
        bRetVal = TRUE;
        for ( u1Cnt = 1 ; u1Cnt < st_u1StrLen ; u1Cnt++ )
        {
            /* 0~7 の数値でない場合 */
            if (FALSE == bExistRange((INTEGER)st_szString[u1Cnt], (INTEGER)MIN_NUM, (INTEGER)OCT_MAX_NUM))
            {
                bRetVal = FALSE;
                break;
            }
        }
    }

    return bRetVal;
}

/*
    10 進数であるかどうかを判定
    BOOLEAN bIsDcmNum(VD);
    return: TRUE -> 10 進数である,FALSE -> 10 進数ではない
*/
BOOLEAN bIsDcmNum(VD)
{
    BOOLEAN bRetVal;
    U1 u1Cnt;

    /* 1 文字もない場合 */
    if ( st_u1StrLen < 1 )
    {
        bRetVal = FALSE;
    }
    else
    {
        bRetVal = TRUE;
        for ( u1Cnt = 0 ; u1Cnt < st_u1StrLen ; u1Cnt++ )
        {
            /* 0~9 の数値でない場合 */
            if (FALSE == bExistRange((INTEGER)st_szString[u1Cnt], (INTEGER)MIN_NUM, (INTEGER)MAX_NUM))
            {
                bRetVal = FALSE;
                break;
            }
        }
    }

    return bRetVal;
}

/*
    16 進数であるかどうかを判定
    BOOLEAN bIsHexNum(VD);
    return: TRUE -> 16 進数である,FALSE -> 16 進数ではない
*/
BOOLEAN bIsHexNum(VD)
{
    BOOLEAN bRetVal;
    U1 u1Cnt;

    /* 3 文字未満の場合 */
    if ( st_u1StrLen < 3 )
    {
        bRetVal = FALSE;
    }
    /* 先頭 2 文字が 0x 出ない場合 */
    else if ( ((CHR)MIN_NUM != st_szString[0]) && ((CHR)HEX_SIMBOL != st_szString[1]))
    {
        bRetVal = FALSE;
    }
    else
    {
        /* 16 進数の可能性がある場合 */
        bRetVal = TRUE;
        for ( u1Cnt = 2 ; u1Cnt < st_u1StrLen ; u1Cnt++ )
        {
            /* 0~9,a~f の数値でない場合 */
            if (     (FALSE == bExistRange((INTEGER)st_szString[u1Cnt], (INTEGER)MIN_NUM,   (INTEGER)MAX_NUM))
                  && (FALSE == bExistRange((INTEGER)st_szString[u1Cnt], (INTEGER)MIN_ASCII, (INTEGER)MAX_ASCII))
            ) {
                bRetVal = FALSE;
                break;
            }
        }
    }

    return bRetVal;
}

conversion.c

#include"typedef.h"
#include"conversion.h"
#define SIMBOL_ZERO     ('0')
#define SIMBOL_A        ('A')
#define SIMBOL_Z        ('Z')
#define NUM_OF_DATALIST (16)
static const CHR g_stc_szDataList[NUM_OF_DATALIST] = "0123456789abcdef";

/*
    指定した範囲にデータが存在するかどうかを確認する関数
    BOOLEAN bExistRange(INTEGER iTargetVal, INTEGER iLowerVal, INTEGER iUpperVal);
    (a1i) iTargetVal: 対象とする値
    (a2i) iLowerVal:  下限値
    (a3i) iUpperVal:  上限値
    return: TRUE -> 範囲内,FALSE -> 範囲外
*/
BOOLEAN bExistRange(INTEGER iTargetVal, INTEGER iLowerVal, INTEGER iUpperVal)
{
    BOOLEAN bRetVal;

    if ( (iLowerVal <= iTargetVal) && (iTargetVal <= iUpperVal) )
    {
        /* 範囲内 */
        bRetVal = TRUE;
    }
    else
    {
        /* 範囲外 */
        bRetVal = FALSE;
    }

    return bRetVal;
}

/*
    大文字を小文字に変換
    CHR chCapital2Small(CHR chData);
    (a1i) chData: 対象文字
    return: 変換結果
*/
CHR chCapital2Small(CHR chData)
{
    CHR chOutData;

    if ( TRUE == bExistRange((INTEGER)chData, (INTEGER)SIMBOL_A, (INTEGER)SIMBOL_Z) )
    {
        chOutData = (CHR)((INTEGER)chData + 32);
    }
    else
    {
        chOutData = chData;
    }

    return chOutData;
}

/*
    10 進数変換
    I4 i4ToDecimal(U1 u1StrLen, STR szStr, U1 u1Basis);
    (a1i) u1StrLen: 入力文字列の長さ
    (a2i) szStr:    入力文字列
    (a3i) u1Basis:  基底
    return: 10 進数の値
*/
I4 i4ToDecimal(U1 u1StrLen, STR szStr, U1 u1Basis)
{
    I4 i4RetVal = 0;
    U1 u1Cnt, u1Data;

    if ( (NULL != szStr) && (u1Basis <= (U1)NUM_OF_DATALIST) )
    {
        for ( u1Cnt = 0 ; u1Cnt < u1StrLen ; u1Cnt++ )
        {
            i4RetVal *= (I4)u1Basis;

            /* 対応する数値をリストから探索 */
            for ( u1Data = 0 ; u1Data < NUM_OF_DATALIST ; u1Data++ )
            {
                if ( g_stc_szDataList[u1Data] == szStr[u1Cnt] )
                {
                    break;
                }
            }
            i4RetVal += (I4)u1Data;
        }
    }

    return i4RetVal;
}

/*
    10 進数から変換
    VD vdFromDecimal(I4 i4Data, U1 u1Basis, U1 *pu1StrLen, STR szStr);
    (a1i) i4Data:    変換前のデータ
    (a2i) u1Basis:   基底
    (a3o) pu1StrLen: 出力文字列の長さ
    (a4o) szStr:     出力文字列
*/
VD vdFromDecimal(I4 i4Data, U1 u1Basis, U1 *pu1StrLen, STR szStr)
{
    U1 u1LoopCnt;
    I1 i1Sign, i1Cnt;
    CHR szReverseStr[MAX_STRING + 1];
    U4 u4CalcData;

    /* 負の数 */
    if ( i4Data < 0 )
    {
        u4CalcData = (U4)(-i4Data);
        i1Sign = (I1)NEGATIVESIGN;
    }
    /* 正の数 */
    else
    {
        u4CalcData = (U4)i4Data;
        i1Sign = (I1)POSITIVESIGN;
    }

    u1LoopCnt = 0;
    if ( (NULL != pu1StrLen) && (NULL != szStr) )
    {
        if ( ((U1)INVBASENUM < u1Basis) && (u1Basis <= (U1)NUM_OF_DATALIST) )
        {
            /* 余りをインデックスとし,データを格納する */
            i1Cnt = 0;
            while ( u4CalcData > 0 )
            {
                szReverseStr[i1Cnt++] = g_stc_szDataList[u4CalcData % (U4)u1Basis];
                u4CalcData /= (U4)u1Basis;
            }

            if ( (I1)NEGATIVESIGN == i1Sign )
            {
                szStr[u1LoopCnt++] = (CHR)MINUS_SIGN;
            }

            /* シンボルの付加 */
            switch ( u1Basis )
            {
                /* 2 進数の場合 */
                case BINARY_NUM:
                    szStr[u1LoopCnt++] = (CHR)BIN_SIMBOL;
                    break;

                /* 8 進数の場合 */
                case OCTAL_NUM:
                    szStr[u1LoopCnt++] = (CHR)SIMBOL_ZERO;
                    break;

                /* 16 進数の場合 */
                case HEXADCMNUM:
                    szStr[u1LoopCnt++] = (CHR)SIMBOL_ZERO;
                    szStr[u1LoopCnt++] = (CHR)HEX_SIMBOL;
                    break;

                /* その他の場合 */
                default:
                    break;
            }

            /* 逆順のデータを順に格納していく */
            while ( i1Cnt > 0 )
            {
                szStr[u1LoopCnt++] = szReverseStr[--i1Cnt];
            }
        }
        szStr[u1LoopCnt] = (CHR)NULLSTR;
        *pu1StrLen = u1LoopCnt;
    }

    return;
}

splitStr.c

#include"typedef.h"
#include"splitStr.h"

typedef struct __split_param_t {
    U1  u1CurrentPos;                    /* 現在の文字列の位置 */
    U1  u1StrLen;                        /* 文字列の長さ       */
    U1  u1NumOfDelimiter;                /* 区切り文字の数     */
    CHR szTargetStr[MAX_STRING + 2];     /* 対象とする文字列   */
    CHR szDelimiterList[MAX_STRING];     /* 区切り文字のリスト */
} SPLIT_PARAM;

static SPLIT_PARAM st_rSplitParam;

/*
    初期化関数
    VD vdSplitStrInit(VD);
*/
VD vdSplitStrInit(VD)
{
    U1 u1Cnt;
    st_rSplitParam.u1CurrentPos = 0;
    st_rSplitParam.u1StrLen = 0;
    st_rSplitParam.u1NumOfDelimiter = 0;

    for ( u1Cnt = 0 ; u1Cnt < (U1)MAX_STRING ; u1Cnt++ )
    {
        st_rSplitParam.szTargetStr[u1Cnt] = (CHR)NULLSTR;
        st_rSplitParam.szDelimiterList[u1Cnt] = (CHR)NULLSTR;
    }
    st_rSplitParam.szTargetStr[MAX_STRING] = (CHR)NULLSTR;

    return;
}

/*
    対象文字列と区切り文字列の設定
    VD vdSetStrDel(STR szTargetStr, U1 u1NumOfDelimiter, STR szDelimiterList);
    (a1i) szTargetStr:      対象文字列
    (a2i) u1NumOfDelimiter: 区切り文字の数
    (a3i) szDelimiterList:  区切り文字のリスト
*/
VD vdSetStrDel(STR szTargetStr, U1 u1NumOfDelimiter, STR szDelimiterList)
{
    U1 u1Cnt;

    u1Cnt = 0;
    /* 対象文字列の設定 */
    if ( NULL != szTargetStr )
    {
        while ( (u1Cnt < (U1)MAX_STRING) && ((CHR)NULLSTR != szTargetStr[u1Cnt]) )
        {
            st_rSplitParam.szTargetStr[u1Cnt] = szTargetStr[u1Cnt];
            u1Cnt++;
        }
    }
    st_rSplitParam.u1CurrentPos = 0;
    st_rSplitParam.u1StrLen = u1Cnt + 1;

    /* 区切り文字の設定 */
    if ( (NULL != szDelimiterList) && (0 < u1NumOfDelimiter) )
    {
        st_rSplitParam.u1NumOfDelimiter = u1NumOfDelimiter;
        for ( u1Cnt = 0 ; (u1Cnt < u1NumOfDelimiter) && (u1Cnt < (U1)MAX_STRING) ; u1Cnt++ )
        {
            st_rSplitParam.szDelimiterList[u1Cnt] = szDelimiterList[u1Cnt];
        }
        u1Cnt = st_rSplitParam.u1StrLen - 1;
        st_rSplitParam.szTargetStr[u1Cnt++] = szDelimiterList[0];
        st_rSplitParam.szTargetStr[u1Cnt] = szDelimiterList[0];
    }
    else
    {
        st_rSplitParam.u1NumOfDelimiter = 0;
        st_rSplitParam.szDelimiterList[0] = (CHR)NULLSTR;
        u1Cnt = st_rSplitParam.u1StrLen - 1;
        st_rSplitParam.szTargetStr[u1Cnt++] = (CHR)NULLSTR;
        st_rSplitParam.szTargetStr[u1Cnt] = (CHR)NULLSTR;
    }

    return;
}

/*
    文字列分割関数
    BOOLEAN bSplitString(STR szSplitStr, U1 *pu1SplitStrLen, BOOLEAN bVartualExecution);
    (a1o) szSplitStr:        分割文字列
    (a2o) *pu1SplitStrLen:   分割文字列の長さ
    (a3i) bVartualExecution: TRUE -> 仮想実行,FALSE -> 実際に実行
    return: TRUE  -> 文字列の終端に達していない
            FALSE -> 文字列を最後まで読んだ
*/
BOOLEAN bSplitString(STR szSplitStr, U1 *pu1SplitStrLen, BOOLEAN bVartualExecution)
{
    BOOLEAN bExeFlag;  /* 実行フラグ           */
    BOOLEAN bRetVal;   /* 戻り値               */
    U1 u1DelCnt;       /* 区切り文字のカウント */
    U1 u1MaxCntOfList; /* 区切り文字の数       */
    U1 u1StrPos;       /* 文字列の位置         */
    U1 u1StrLen;       /* 文字列の長さ         */
    CHR chData;        /* 対象とする文字列     */
    u1StrPos = st_rSplitParam.u1CurrentPos;
    u1MaxCntOfList = st_rSplitParam.u1NumOfDelimiter;
    u1StrLen = st_rSplitParam.u1StrLen;
    bExeFlag = TRUE;

    if ( (NULL == szSplitStr) || (NULL == pu1SplitStrLen) )
    {
        bRetVal = FALSE;
    }
    else
    {
        *pu1SplitStrLen = 0;
        /* 文字列の終端に到達する,若しくはフラグが降りるまでループ */
        while ( (u1StrPos < u1StrLen) && (TRUE == bExeFlag) )
        {
            chData = st_rSplitParam.szTargetStr[u1StrPos];
            szSplitStr[*pu1SplitStrLen] = chData;
            (*pu1SplitStrLen)++;

            /* 今見ている文字が区切り文字かどうか確認 */
            for ( u1DelCnt = 0 ; u1DelCnt < u1MaxCntOfList ; u1DelCnt++ )
            {
                /* 区切り文字と一致した場合 */
                if ( chData == st_rSplitParam.szDelimiterList[u1DelCnt] )
                {
                    bExeFlag = FALSE;
                    break;
                }
            }
            u1StrPos++;
        }

        /* 上のループに入った場合 */
        if ( 0 < (*pu1SplitStrLen) )
        {
            bRetVal = TRUE;

            /* 区切り文字以外がある場合 */
            if ( 1 < (*pu1SplitStrLen) )
            {
                (*pu1SplitStrLen)--;
                u1StrPos--;
            }
        }
        /* 終了条件に達した場合 */
        else
        {
            bRetVal = FALSE;
        }
        szSplitStr[*pu1SplitStrLen] = (CHR)NULLSTR;

        /* 仮想実行の場合は,次のトークンに移動しない */
        if ( FALSE == bVartualExecution )
        {
            st_rSplitParam.u1CurrentPos = u1StrPos;
        }
    }

    return bRetVal;
}

stack.c

#include"typedef.h"
#include"stack.h"

static I2 st_i2Stack[MAX_STACK_SIZE];
static I2 st_i2IdxOfStack;

/*
    スタックの初期化関数
    VD vdInitStack(VD);
*/
VD vdInitStack(VD)
{
    st_i2IdxOfStack = 0;

    return;
}

/*
    格納関数
    BOOLEAN bPush(I2 i2Data);
    (a1i) i2Data: 格納する値
    return: TRUE -> 成功,FALSE -> 失敗
*/
BOOLEAN bPush(I2 i2Data)
{
    BOOLEAN bRetVal;

    /* スタックサイズを超えている場合 */
    if ( st_i2IdxOfStack >= (I2)MAX_STACK_SIZE )
    {
        bRetVal = FALSE;
    }
    else
    {
        st_i2Stack[st_i2IdxOfStack++] = i2Data;
        bRetVal = TRUE;
    }

    return bRetVal;
}

/*
    取り出し関数
    BOOLEAN bPop(I2 *pi2Val);
    (aio) pi2Val: 取り出す値
    return: TRUE -> 成功,FALSE -> 失敗
*/
BOOLEAN bPop(I2 *pi2Val)
{
    BOOLEAN bRetVal;

    /* スタックが空の場合 */
    if ( (st_i2IdxOfStack <= 0) || (NULL == pi2Val) )
    {
        bRetVal = FALSE;
    }
    else
    {
        *pi2Val = st_i2Stack[--st_i2IdxOfStack];
        bRetVal = TRUE;
    }

    return bRetVal;
}

token.c

#include"typedef.h"
#include"checkNum.h"
#include"conversion.h"
#include"splitStr.h"
#include"token.h"
#include"stack.h"
#define I2_MINVAL (-32768)
#define I2_MAxVAL (32767)

/*
    符号の確認
    I1 i1ChkSign(STR *pszStr, U1 *pu1StrLen);
    (a1io) pszStr:    文字列の先頭アドレスへのポインタ
    (a2o)  pu1StrLen: 文字列の長さ
    return: PLUS_SIGN -> POSITIVESIGN,MINUS_SIGN -> NEGATIVESIGN
*/
I1 i1ChkSign(STR *pszStr, U1 *pu1StrLen);

/*
    基底の取得
    VD vdGetBaseNumber(U1 *pu1Basis, U1 *pu1Idx);
    (a1o) pu1Basis: 基底
    (a2o) pu1Idx:   計算対象の文字列のインデックス
*/
VD vdGetBaseNumber(U1 *pu1Basis, U1 *pu1Idx);

/*
    トークン分割する関数
    VD vdToken(STR szStr, U1 u1NumOfDelimiters, STR szDelimiterList);
    (a1i) szStr:             対象文字列
    (a2i) u1NumOfDelimiters: 区切り文字数
    (a3i) szDelimiterList:   区切り文字
*/
VD vdToken(STR szStr, U1 u1NumOfDelimiters, STR szDelimiterList)
{
    /* 区切り文字の設定 */
    CHR szSplitStr[MAX_STRING + 1];
    STR pszSplitData;
    U1 u1SplitStrLen, u1Basis, u1StartIdx;
    I1 i1Sign;
    I4 i4Data;

    if ( (NULL != szStr) && (NULL != szDelimiterList) )
    {
        /* 文字列分割の初期化 */
        vdSplitStrInit();
        /* 文字列の設定 */
        vdSetStrDel(szStr, (U1)u1NumOfDelimiters, szDelimiterList);

        /* 対象文字列の終端に到達するまでループ */
        while ( TRUE == bSplitString(szSplitStr, &u1SplitStrLen, FALSE) )
        {
            /* 符号の決定 */
            pszSplitData = &szSplitStr[0];
            i1Sign = i1ChkSign(&pszSplitData, &u1SplitStrLen);

            /* 数値チェックの初期化 */
            vdCheckStrInit();
            /* 文字列の設定 */
            vdSetString(pszSplitData);
            /* 基底を得る */
            vdGetBaseNumber(&u1Basis, &u1StartIdx);

            if ( u1Basis > 0 )
            {
                i4Data = (I4)i1Sign * i4ToDecimal(u1SplitStrLen - u1StartIdx, &pszSplitData[u1StartIdx], u1Basis);

                if ( ((I4)I2_MINVAL < i4Data) && (i4Data < (I4)I2_MAxVAL) )
                {
                    (VD)bPush((I2)i4Data);
                }
            }
        }
    }

    return;
}

/*
    符号の確認
    I1 i1ChkSign(STR *pszStr, U1 *pu1StrLen);
    (a1io) pszStr:    文字列の先頭アドレスへのポインタ
    (a2o)  pu1StrLen: 文字列の長さ
    return: PLUS_SIGN -> POSITIVESIGN,MINUS_SIGN -> NEGATIVESIGN
*/
I1 i1ChkSign(STR *pszStr, U1 *pu1StrLen)
{
    I1 i1Sign = 0;

    if ( (NULL != pszStr) && (NULL != (*pszStr)) && (NULL != pu1StrLen) )
    {
        switch ( **pszStr )
        {
            /* プラスの場合 */
            case PLUS_SIGN:
                i1Sign = (I1)POSITIVESIGN;
                (*pszStr)++;
                (*pu1StrLen)--;
                break;

            /* マイナスの場合 */
            case MINUS_SIGN:
                i1Sign = (I1)NEGATIVESIGN;
                (*pszStr)++;
                (*pu1StrLen)--;
                break;

            /* 符号がない場合 */
            default:
                i1Sign = (I1)POSITIVESIGN;
                break;
        }
    }

    return i1Sign;
}

/*
    基底の取得
    VD vdGetBaseNumber(U1 *pu1Basis, U1 *pu1Idx);
    (a1o) pu1Basis: 基底
    (a2o) pu1Idx:   計算対象の文字列のインデックス
*/
VD vdGetBaseNumber(U1 *pu1Basis, U1 *pu1Idx)
{
    *pu1Idx = 0;

    /* 2 進数の場合 */
    if ( TRUE == bIsBinary() )
    {
        *pu1Basis = (U1)BINARY_NUM;
        *pu1Idx = 1;
    }
    /* 8 進数の場合 */
    else if ( TRUE == bIsOctNum() )
    {
        *pu1Basis = (U1)OCTAL_NUM;
    }
    /* 10 進数の場合 */
    else if ( TRUE == bIsDcmNum() )
    {
        *pu1Basis = (U1)DECIMALNUM;
    }
    /* 16 進数の場合 */
    else if ( TRUE == bIsHexNum() )
    {
        *pu1Basis = (U1)HEXADCMNUM;
        *pu1Idx = 2;
    }
    /* 上記以外の場合 */
    else
    {
        *pu1Basis = (U1)INVBASENUM;
    }

    return;
}

最後に礼として作成した main 関数を示す.

#include<stdio.h>
#include"typedef.h"
#include"token.h"
#include"stack.h"
#define NUM_OF_DELIMITERS (4)

VD vdStrnCpy(STR szOutputStr, const STR szInputStr, INTEGER iMaxNum);

INTEGER main(INTEGER iArgCnt, STR szArgVec[])
{
    I2 i2Data;
    /* 入力文字列 */
    CHR szInputStr[MAX_STRING + 1];
    /* 区切り文字リスト */
    CHR szDelimiterList[NUM_OF_DELIMITERS] = " ,:;";

    if ( iArgCnt < 2 )
    {
        szInputStr[0] = '1';
        szInputStr[1] = '\0';
    }
    else
    {
        vdStrnCpy(szInputStr, szArgVec[1], MAX_STRING);
    }
    vdToken(szInputStr, NUM_OF_DELIMITERS, szDelimiterList);

    while ( TRUE == bPop(&i2Data) )
    {
        printf("%d\n", i2Data);
    }

    return 0;
}

VD vdStrnCpy(STR szOutputStr, const STR szInputStr, INTEGER iMaxNum)
{
    INTEGER iCnt;
    CHR chData;

    for ( iCnt = 0 ; iCnt < iMaxNum - 1; iCnt++ )
    {
        chData = szInputStr[iCnt];
        szOutputStr[iCnt] = chData;

        if ( (CHR)NULLSTR == chData )
        {
            break;
        }
    }
    szOutputStr[iCnt] = (CHR)NULLSTR;

    return;
}

Makefile

CC     := gcc
CLIBS  := -O2 -Wall -Wextra
PROG   := execute
INCDIR := include
SRCDIR := src
OUTDIR := objdep
SRCS   := $(shell ls $(SRCDIR))
OBJS   := $(SRCS:%.c=$(OUTDIR)/%.o)
DEPS   := $(SRCS:%.c=$(OUTDIR)/%.d)

all: $(PROG)
-include $(DEPS)

$(PROG): $(OBJS)
  $(CC) -o $@ $^

$(OUTDIR)/%.o: $(SRCDIR)/%.c
   @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
  $(CC) -o $@ -c -MP -MMD -MF $(@:%.o=%.d) $(CLIBS) -I$(INCDIR) $<

.PHONY: clean
clean:
  rm -f $(PROG) $(OBJS) $(DEPS)