プログラミングのメモ帳(C/C++/HSP)

日々のプログラミングで気づいた点や小技集を紹介します。(Windows 10/XP/Vista、VC2017、HSP)

n進文字列と整数値の相互変換

2012年04月22日 10時18分05秒 | アルゴリズム関連

n進文字列と整数値の相互変換を紹介します。(戻る)

アルゴリズム

ここではn進数の文字列と整数値の相互変換する関数を3つ紹介してます。
文字列から整数値に変換する場合は、文字列の先頭から[0]~[9]、[A]~[Z]、[a]~[z]の文字を解読してきます。
桁上がりは引数で指定した nRadix の値をそのまま掛け算します。

整数値から文字列に変換する場合は、整数値の下位桁から[0]~[35]の余りを解読してきます。
余りは普通に36で割って求めます。(%演算)
この余りから[0]~[9]、[A]~[Z]、[a]~[z]の文字に変換して文字列バッファ(lpBuff)にコピーします。
しかし、このままでは文字列が左右反転してるので戻すために左右並びを反転させます。

このときに出力桁数分だけスペース文字などを文字列バッファ(lpBuff)にコピーします。
こうすることで文字列バッファ(lpBuff)の先頭に出力桁数に見合うスペース文字で埋められます。
なお、スペース文字の代わりに[0]の文字で埋めたり、接頭語(0b、0o、0d、0x)もコピーするように改良も可能です。

接頭語(0b、0o、0d、0x)を出力するときには[x][0]の順にコピーしたり、出力桁数から2文字分だけ引いた残りが
スペース文字(ゼロ文字)で埋める出力桁数になることに気をつけましょう。
今回は接頭語(0b、0o、0d、0x)は出力しません。

//------------------------------------------------
// 関数のプロトタイプ宣言
//------------------------------------------------
extern   UINT funcStrToInt( LPCTSTR lpString, UINT nRadix );
extern   UINT funcStrToIntEx( LPCTSTR lpString, UINT nRadix );
extern LPTSTR funcIntToStr( LPTSTR lpBuff, UINT nValue, LONG nRadix );
extern LPTSTR funcIntToStrEx( LPTSTR lpBuff, UINT nValue, LONG nWidth, TCHAR tcSpace, LONG nRadix );

サンプル

//------------------------------------------------------------------------------
// n進文字列と整数値の相互変換
//------------------------------------------------------------------------------
#include <stdio.h>
#include <tchar.h>
#include <ctype.h>
#include <wctype.h>
#include <locale.h>
#include <Windows.h>

//------------------------------------------------
// break 付きのキーワード
//------------------------------------------------
#define CASE        break;case
#define DEFAULT     break;default

//------------------------------------------------
// n進文字列から整数値に変換
//------------------------------------------------
extern UINT funcStrToInt( LPCTSTR lpString, UINT nRadix )
{
    UINT nValue;
    UINT nRet;
    
    for ( nRet = 0 ; _istalnum(*lpString) ; lpString++ ){
        if ( _istdigit(*lpString) ){
            nValue = (*lpString - TEXT('0'));
        }
        else if ( _istupper(*lpString) ){
            nValue = (*lpString - TEXT('A') + 10);
        }
        else{
            nValue = (*lpString - TEXT('a') + 10);
        }
        if ( nValue >= nRadix ){
            break;
        }
        nRet *= nRadix;
        nRet += nValue;
    }
    return nRet;
}

//------------------------------------------------
// 接頭語付き文字列から整数値に変換
//------------------------------------------------
extern UINT funcStrToIntEx( LPCTSTR lpString, UINT nRadix )
{
    if ( nRadix == 0 ){
        if ( *lpString == TEXT('0') ){
            switch ( *(++lpString) ){
                CASE TEXT('b'):     nRadix = 2;
                CASE TEXT('o'):     nRadix = 8;
                CASE TEXT('d'):     nRadix = 10;
                CASE TEXT('x'):     nRadix = 16;
                DEFAULT:            return 0;
            }
            return funcStrToInt( (lpString + 1), nRadix );
        }
        return funcStrToInt( lpString, 10 );
    }
    return funcStrToInt( lpString, nRadix );
}
/*
0b01
0o01234567
0d0123456789
0x0123456789ABCDEF
123456789
*/

//------------------------------------------------
// 文字列の左右並びを反転
//------------------------------------------------
static VOID funcStrReverse( LPTSTR lpHead, LPTSTR lpTail )
{
    TCHAR tcSwap[ 1 ];
    
    for ( *lpTail-- = TEXT('\0') ; lpHead < lpTail ; lpHead++, lpTail-- ){
        tcSwap[ 0 ] = lpHead[ 0 ];
        lpHead[ 0 ] = lpTail[ 0 ];
        lpTail[ 0 ] = tcSwap[ 0 ];
    }
}

//------------------------------------------------
// 整数値からn進文字列に変換
//------------------------------------------------
extern LPTSTR funcIntToStr( LPTSTR lpBuff, UINT nValue, LONG nRadix )
{
    LPTSTR lpTable;
    LPTSTR lpTail;
    
    if ( nValue == 0 ){
        lpBuff[0] = TEXT('0');
        lpBuff[1] = TEXT('\0');
        return lpBuff;
    }
    if ( nRadix < 0 ){
        nRadix = -nRadix;
        lpTable = TEXT("0123456789abcdefghijklmnopqrstuvwxyz");
    }
    else{
        lpTable = TEXT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    }
    for ( lpTail = lpBuff ; nValue ; nValue /= nRadix ){
        *lpTail++ = lpTable[ nValue % nRadix ];
    }
    funcStrReverse( lpBuff, lpTail );
    return lpBuff;
}

//------------------------------------------------
// 文字列の左右並びを反転
//------------------------------------------------
static VOID funcStrReverseEx( LPTSTR lpHead, LPTSTR lpTail, LONG nWidth, TCHAR tcSpace )
{
    TCHAR tcSwap[ 1 ];
    
    while ( nWidth > 0 ){
        nWidth--; *lpTail++ = tcSpace;
    }
    for ( *lpTail-- = TEXT('\0') ; lpHead < lpTail ; lpHead++, lpTail-- ){
        tcSwap[ 0 ] = lpHead[ 0 ];
        lpHead[ 0 ] = lpTail[ 0 ];
        lpTail[ 0 ] = tcSwap[ 0 ];
    }
}

//------------------------------------------------
// 整数値からn桁n進文字列に変換
//------------------------------------------------
extern LPTSTR funcIntToStrEx( LPTSTR lpBuff, UINT nValue, LONG nWidth, TCHAR tcSpace, LONG nRadix )
{
    LPTSTR lpTable;
    LPTSTR lpTail = lpBuff;
    
    if ( nRadix < 0 ){
        nRadix = -nRadix;
        lpTable = TEXT("0123456789abcdefghijklmnopqrstuvwxyz");
    }
    else{
        lpTable = TEXT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    }
    if ( nValue == 0 ){
        nWidth--; *lpTail++ = TEXT('0');
    }
    else for ( ; nValue ; nValue /= nRadix ){
        nWidth--; *lpTail++ = lpTable[ nValue % nRadix ];
    }
    funcStrReverseEx( lpBuff, lpTail, nWidth, tcSpace );
    return lpBuff;
}

//------------------------------------------------
// メイン関数
//------------------------------------------------
int _tmain( void )
{
    // 接頭語なし
    LPCTSTR     lpBin1 = TEXT("111010110111100110100010101");
    LPCTSTR     lpOct1 = TEXT("726746425");
    LPCTSTR     lpDec1 = TEXT("123456789");
    LPCTSTR     lpHex1 = TEXT("75BCD15");
    // 接頭語あり
    LPCTSTR     lpBin2 = TEXT("0b111010110111100110100010101");
    LPCTSTR     lpOct2 = TEXT("0o726746425");
    LPCTSTR     lpDec2 = TEXT("0d123456789");
    LPCTSTR     lpHex2 = TEXT("0x75BCD15");
    // その他
    TCHAR       szBuff[ 256 ];
    LONG        nValue;
    LONG        nWidth = 8;
    TCHAR       tcSpace = TEXT('0');
    
    // ロケールの設定
    _tsetlocale( LC_ALL, TEXT("") );
    // 文字列→整数値
    _tprintf( TEXT("\n// 接頭語なし\n") );
    _tprintf( TEXT("%-30s = %ld\n"), lpBin1, funcStrToInt(lpBin1,2) );
    _tprintf( TEXT("%-30s = %ld\n"), lpOct1, funcStrToInt(lpOct1,8) );
    _tprintf( TEXT("%-30s = %ld\n"), lpDec1, funcStrToInt(lpDec1,10) );
    _tprintf( TEXT("%-30s = %ld\n"), lpHex1, funcStrToInt(lpHex1,16) );
    _tprintf( TEXT("\n// 接頭語あり\n") );
    _tprintf( TEXT("%-30s = %ld\n"), lpBin2, funcStrToIntEx(lpBin2,0) );
    _tprintf( TEXT("%-30s = %ld\n"), lpOct2, funcStrToIntEx(lpOct2,0) );
    _tprintf( TEXT("%-30s = %ld\n"), lpDec2, funcStrToIntEx(lpDec2,0) );
    _tprintf( TEXT("%-30s = %ld\n"), lpHex2, funcStrToIntEx(lpHex2,0) );
    // 整数値→文字列
    _tprintf( TEXT("\n// 整数値からn進文字列に変換(大文字)\n") );
    for ( nValue = 0 ; nValue < 32 ; nValue++ ){
        _tprintf( TEXT("%2ld = [%s]\n"), nValue, funcIntToStr(szBuff,nValue,+16) );
    }
    _tprintf( TEXT("\n// 整数値からn進文字列に変換(小文字)\n") );
    for ( nValue = 0 ; nValue < 32 ; nValue++ ){
        _tprintf( TEXT("%2ld = [%s]\n"), nValue, funcIntToStr(szBuff,nValue,-16) );
    }
    // 整数値→文字列(n桁)
    _tprintf( TEXT("\n// 整数値からn進文字列に変換(大文字)\n") );
    for ( nValue = 0 ; nValue < 32 ; nValue++ ){
        _tprintf( TEXT("%2ld = [%s]\n"), nValue, funcIntToStrEx(szBuff,nValue,nWidth,tcSpace,+16) );
    }
    _tprintf( TEXT("\n// 整数値からn進文字列に変換(小文字)\n") );
    for ( nValue = 0 ; nValue < 32 ; nValue++ ){
        _tprintf( TEXT("%2ld = [%s]\n"), nValue, funcIntToStrEx(szBuff,nValue,nWidth,tcSpace,-16) );
    }
    return 0;
}

//------------------------------------------------------------------------------
// End of funcStrToInt.cpp
//------------------------------------------------------------------------------

実行結果

// 接頭語なし
111010110111100110100010101    = 123456789
726746425                      = 123456789
123456789                      = 123456789
75BCD15                        = 123456789

// 接頭語あり
0b111010110111100110100010101  = 123456789
0o726746425                    = 123456789
0d123456789                    = 123456789
0x75BCD15                      = 123456789

// 整数値からn進文字列に変換(大文字)
 0 = [0]
 1 = [1]
 2 = [2]
 3 = [3]
 4 = [4]
 5 = [5]
 6 = [6]
 7 = [7]
 8 = [8]
 9 = [9]
10 = [A]
11 = [B]
12 = [C]
13 = [D]
14 = [E]
15 = [F]
16 = [10]
17 = [11]
18 = [12]
19 = [13]
20 = [14]
21 = [15]
22 = [16]
23 = [17]
24 = [18]
25 = [19]
26 = [1A]
27 = [1B]
28 = [1C]
29 = [1D]
30 = [1E]
31 = [1F]

// 整数値からn進文字列に変換(小文字)
 0 = [0]
 1 = [1]
 2 = [2]
 3 = [3]
 4 = [4]
 5 = [5]
 6 = [6]
 7 = [7]
 8 = [8]
 9 = [9]
10 = [a]
11 = [b]
12 = [c]
13 = [d]
14 = [e]
15 = [f]
16 = [10]
17 = [11]
18 = [12]
19 = [13]
20 = [14]
21 = [15]
22 = [16]
23 = [17]
24 = [18]
25 = [19]
26 = [1a]
27 = [1b]
28 = [1c]
29 = [1d]
30 = [1e]
31 = [1f]

// 整数値からn進文字列に変換(大文字)
 0 = [00000000]
 1 = [00000001]
 2 = [00000002]
 3 = [00000003]
 4 = [00000004]
 5 = [00000005]
 6 = [00000006]
 7 = [00000007]
 8 = [00000008]
 9 = [00000009]
10 = [0000000A]
11 = [0000000B]
12 = [0000000C]
13 = [0000000D]
14 = [0000000E]
15 = [0000000F]
16 = [00000010]
17 = [00000011]
18 = [00000012]
19 = [00000013]
20 = [00000014]
21 = [00000015]
22 = [00000016]
23 = [00000017]
24 = [00000018]
25 = [00000019]
26 = [0000001A]
27 = [0000001B]
28 = [0000001C]
29 = [0000001D]
30 = [0000001E]
31 = [0000001F]

// 整数値からn進文字列に変換(小文字)
 0 = [00000000]
 1 = [00000001]
 2 = [00000002]
 3 = [00000003]
 4 = [00000004]
 5 = [00000005]
 6 = [00000006]
 7 = [00000007]
 8 = [00000008]
 9 = [00000009]
10 = [0000000a]
11 = [0000000b]
12 = [0000000c]
13 = [0000000d]
14 = [0000000e]
15 = [0000000f]
16 = [00000010]
17 = [00000011]
18 = [00000012]
19 = [00000013]
20 = [00000014]
21 = [00000015]
22 = [00000016]
23 = [00000017]
24 = [00000018]
25 = [00000019]
26 = [0000001a]
27 = [0000001b]
28 = [0000001c]
29 = [0000001d]
30 = [0000001e]
31 = [0000001f]
  • funcStrToInt 関数は接頭語(0b、0o、0d、0x)を解釈しないので付けると 0 になります。(仕様)
  • funcStrToIntEx 関数は接頭語(0b、0o、0d、0x)を解釈するので nRadix は 0 にします。
    なお nRadix が 0 以外では接頭語(0b、0o、0d、0x)を解釈しません。(注意)
  • funcIntToStr 関数は単純に整数値から2進文字列に変換してます。
    なお nRadix にマイナス値を指定すると小文字で変換されます。
  • funcIntToStrEx 関数は出力桁数と出力文字を指定して2進文字列に変換してます。
    実はこの関数が本命で funcIntToStr 関数は理解しやすいように載せたものです。
←前へ] [目次] [次へ→

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 16進文字列と整数値の相互変換 | トップ | 文字列から整数値に変換(まとめ) »
最新の画像もっと見る

コメントを投稿

アルゴリズム関連」カテゴリの最新記事