月別アーカイブ: 7月 2013

「ハム太と作るC++ライブラリ0 -構文編-」

まだ執筆中なんですが、

C言語のところはそこそこ書けてるので、

退屈しのぎにどうぞ。↓

 

http://p.booklog.jp/book/74354/read

コメントする

カテゴリー: C++

STL::CBitSet

#pragma once
#ifndef _STL_BITSET_H_
#define _STL_BITSET_H_
#include <bitset>
using namespace std;
namespace STL
{
// =====================================================
// ビットセットクラスの定義 ( std::bitsetのラッパー )
//・「ビットセット」は、ビットフラグを扱いやすくしたコンテナ。
//   ( ビット操作に慣れた人には、物足りない内容であり、通常ならマクロで事足りる。 )
//・テンプレート引数には、使用するビット数を指定する。
//  ( たとえば、std::bitset<8> とした場合には、8bitフラグとなり、
//    0~7までの8つのビットを、bool型のフラグ変数のように使用することができる。 )
template<typename T>
class /* _EXPORT */ CBitSet
{
protected: // publicでもOK。
// —————————————————-
// データメンバ
std::bitset<T> bits; // ビットセット 本体。
public:
// —————————————————–<OK><テスト済み>
// コンストラクタ
CBitSet(void) : bits()
{
}
// —————————————————–<OK><テスト済み>
// コンストラクタ
CBitSet( const unsigned __int64 value_ ) : bits( value_ )
{
}
// —————————————————–<OK><テスト済み>
// デストラクタ
~CBitSet(void)
{
}
// —————————————————–<OK><テスト済み>
//【ビットセット】を返す。
   inline std::bitset<T>& GetBitSet(void)
   {
          return bits;
   }
// —————————————————–<OK><テスト済み>
//【ビットセット】を格納する。
   inline void SetBitSet( std::bitset<T>& bits_ )
   {
          bits = bits_;
   }
// —————————————————–<OK><テスト済み>
//【指定indexのビット】を、ONにする。                                  ( set() )
inline std::bitset<T>& SetOnAt( const size_t index_ )
{
                  return bits.set( index_ );
}
// —————————————————–<OK><テスト済み>
//【指定indexのビット】を、OFFにする。                             ( reset() )
inline std::bitset<T>& SetOffAt( const size_t index_ )
{
                  return bits.reset( index_ );
}
// —————————————————–<OK><テスト済み>
//【指定indexのビット】の、フラグ値 ( 0か1 ) を返す。             ( test() )
inline bool GetValue( const size_t index_ )
{
                  return bits.test( index_ );
}
// —————————————————–<OK><テスト済み>
//【指定indexのビット】に、フラグ値 ( 0か1 ) を設定する。         ( set() )
inline std::bitset<T>& SetValue( const size_t index_, const bool value_ )
{
                 return bits.set( index_ );
}
// —————————————————–<OK><テスト済み>
//【すべてのビット】を、OFFにする。                                   ( reset() )
inline std::bitset<T>& SetOffAll(void)
{
                  return bits.reset();
}
// —————————————————–<OK><テスト済み>
//【指定indexのビット】を、反転する。                                   ( flip() )
inline std::bitset<T>& FlipAt( const size_t index_ )
{
                  return bits.flip( index_ );
}
// —————————————————–<OK><テスト済み>
//【すべてのビット】を、反転する。                                         ( flip() )
inline std::bitset<T>& FlipAll(void)
{
                 return bits.flip();
}
// —————————————————–<OK><テスト済み>
//【いずれかのビット】がONなら、TRUEを返す。                     ( any() )
inline bool IsAnyOn(void)
{
                 return bits.any();
}
// —————————————————–<OK><テスト済み>
//【すべてのビット】がONなら、TRUEを返す。                          ( all() )
inline bool IsAllOn(void)
{
                 return bits.all();
}
// —————————————————–<OK><テスト済み>
//【すべてのビット】がOFFなら、TRUEを返す。                    ( none() )
inline bool IsAllOff(void)
{
                  return bits.none();
}
// —————————————————–<OK><テスト済み>
//【ONになっているビットの数】を返す。                            ( count() )
inline size_t GetOnCount(void)
{
                 return bits.count();
}
// —————————————————–<OK><テスト済み>
//【ビットの数】を返す。                                                       ( size() )
inline size_t GetBitCount(void)
{
                 return bits.size();
}
// —————————————————–<OK><テスト済み>
//【符号なし32bit整数値】を返す。                              ( to_ulong() )
inline unsigned int ToUInt32(void)
{
                 return bits.to_ulong();
}
// —————————————————–<OK><テスト済み>
//【符号なし64bit整数値】を返す。                              ( to_ullong() )
inline unsigned __int64 ToUInt64(void)
{
                  return bits.to_ullong();
}
// —————————————————–<OK><テスト済み>
//【文字列】を返す。                     ( to_string() )
// “00101010” といった文字列が返る。
inline std::string ToString(void)
{
                 return bits.to_string();
}
// ————————————————-
// #################################################
// 演算子のオーバーロード
// #################################################
// ————————————————-<OK><テスト済み>
//  指定index_ ビット値を返す。
inline bool operator[]( const size_t index_ )
{
return bits[ index_ ];
}
// ————————————————-<OK><テスト済み>
//  指定index_ 参照を返す。
inline std::bitset::reference operator[]( const size_t index_ )
{
return bits[ index_ ];
}
// ————————————————-<OK><テスト済み>
//  instance = CBitSet
inline CBitSet<T>& operator=( const CBitSet<T>& bits_ )
{
bits = bits_.GetBitSet();
}
// ————————————————-<OK><テスト済み>
//  instance |= CBitSet
inline CBitSet<T>& operator|=( const CBitSet<T>& bits_ )
{
bits |= bits_.GetBitSet();
}
// ————————————————-<OK><テスト済み>
//  instance ^= CBitSet
inline CBitSet<T>& operator^=( const CBitSet<T>& bits_ )
{
bits ^= bits_.GetBitSet();
}
// ————————————————-<OK><テスト済み>
//  ~instance
inline CBitSet<T>& operator~()
{
return ~bits;
}
// ————————————————-<OK><テスト済み>
// instance << shift_bit_count_
inline CBitSet<T> operator<<( const size_t shift_bit_count_ )
{
return ( bits <<  shift_bit_count_);
}
// ————————————————-<OK><テスト済み>
// instance >> shift_bit_count_
inline CBitSet<T> operator>>( const size_t shift_bit_count_ )
{
return ( bits >>  shift_bit_count_);
}
// ————————————————-<OK><テスト済み>
// instance <<= shift_bit_count_
inline CBitSet<T>& operator<<=( const size_t shift_bit_count_ )
{
return ( bits <<= shift_bit_count_);
}
// ————————————————-<OK><テスト済み>
// instance >>= shift_bit_count_
inline CBitSet<T>& operator>>=( const size_t shift_bit_count_ )
{
return ( bits >>= shift_bit_count_);
}
// ————————————————-<OK><テスト済み>
//  bool result = ( instance == CBitSet )
inline bool operator==( CBitSet<T>& bits_ )
{
return ( bits == bits_.GetBitSet() );
}
// ————————————————-<OK><テスト済み>
//  bool result = ( instance != CBitSet )
inline bool operator!=( CBitSet<T>& bits_ )
{
return ( bits != bits_.GetBitSet() );
}
// —————————————————–
}; // end class
}; // end namespace
// —————————————————-
#endif

コメントする

カテゴリー: C++, STL

STL::CStringW

#pragma once

#ifndef _STL_STRINGW_H_
#define _STL_STRINGW_H_
#include <vector>
#include <string>
using namespace std;
namespace STL
{

// ———————————————————————
// NotFound定数 ( 検索した際に、条件に一致する位置が見つからなかった時に返る値。)

#define NotFound 4294967295 // std::wstring::npos
// ———————————————————————
// ワイド文字列クラスの定義 ( std::wstringのラッパー )

//・UTF-16LE ( Unicode文字列。1文字の文字コードは、2byte固定 )

class /*_EXPORT */ CStringW
{

// ————————————————-
// データメンバ

protected:

std::wstring text; // ワイド文字列の本体。

// マルチバイトを使う場合は、ここを std::string にする。

public:

// —————————————————–<OK><テスト済み>
// イテレーター

typedef std::wstring::iterator Iterator; // 通常のイテレーター (ランダムアクセス)

typedef std::wstring::reverse_iterator RevIterator; // 逆順イテレーター (ランダムアクセス)
// ————————————————-
// コンストラクタ

CStringW(void) : text()
{

}

// ————————————————-
// コンストラクタ

CStringW( CStringW& text_ ) : text( text_.GetString() )
{

}

// ————————————————-
// コンストラクタ

CStringW( const std::wstring& text_ ) : text( text_ )
{

}

// ————————————————-<OK><テスト済み>
// コンストラクタ

CStringW( const WCHAR* p_text_ ) : text( p_text_ )
{

}

// ————————————————-<OK><テスト済み>
// デストラクタ

~CStringW(void)
{

}

// ————————————————-<OK><テスト済み>
//【ワイド文字列】を返す。

inline std::wstring& GetString(void)
{
return text;
}

// ————————————————-<OK><テスト済み>
//【ワイド文字列】を変更する。

inline void SetString( std::wstring& text_ )
{
text = text_;
}

// ————————————————-<OK><テスト済み>
//【指定indexの1文字】を返す。 ( at() )

inline WCHAR GetChar( const size_t index_ )
{
return text.at( index_ );
}

// ————————————————-<OK><テスト済み>
//【ポインタ】を返す。 ( c_str() )

// ※返される文字列は、終端に必ずNULL文字が付加されている。
// ・文字数0の場合、p_result[0]は、NULL文字。
// ・p_result[ length ] は、NULL文字。

inline const WCHAR* GetPtr(void)
{
return text.c_str(); // data() と同じ。
}

// —————————————————–<OK><テスト済み>
//【指定indexのイテレータ】を返す。

// ※戻り値のイテレータを、参照にしていないのには理由がある。
// このクラスがローカル変数として宣言された場合、
// スタック領域のアドレスを返してしまうためコケるからである。

inline Iterator GetItr( const size_t index_ )
{
return ( text.begin() + index_ );

}

// ————————————————-
//【文字数】を返す。 ( length() or size() )

// ※終端のNULL文字を含まない。

inline size_t GetLength()
{
return text.length();
}

// ————————————————-
//【最大文字数】を返す。 ( max_size() )

inline size_t GetMaxLength()
{
return text.max_size();
}

// ————————————————-<OK><テスト済み>
//【文字列】を初期化する。 ( assign() )

// ※ std::wstring::value_type は、wchar_t 。

// STL::CStringW text1;
// text1.Init( L”あいうえお”, 3 ); // text1 は、”あいう” で初期化される。

inline std::wstring& Init( const WCHAR* p_text_ )
{
return text.assign( p_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を初期化する。 ( append() )

// STL::CStringW text1;
// text1.Init( L”あいうえお”, 3 ); // text1 は、”あいう” で初期化される。

inline std::wstring& Init( const WCHAR* p_text_ , const size_t length_ )
{
return text.assign( p_text_, length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】で初期化する。 ( append() )

// STL::CStringW text1;
// std::wstring text2( L”かきくけこ” );
// text1.InitByString( text2 ); // text1 は、”かきくけこ” で初期化される。

inline void InitByString( const std::wstring& text_ )
{
text.assign( text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】で初期化する。 ( append() )

// STL::CStringW text1;
// std::wstring text2( L”かきくけこ” );
// text1.InitByString( text2, 1, 2 ); // text1 は、”きく” で初期化される。

inline std::wstring& InitByString(
const std::wstring& text_, // この文字列中の、部分文字列で初期化される。
const size_t start_index_, // 部分文字列の開始位置。
const size_t length_ // 部分文字列の文字数。
)
{
return text.assign( text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定した文字】で初期化する。 ( append() )

// STL::CStringW text1;
// text1.InitByChar( L’あ’, 3 ); // text1 は、”あああ” で初期化される。

inline std::wstring& InitByChar( const WCHAR char_, const size_t count_ )
{
return text.assign( count_, char_ );
}

// ————————————————-<OK><テスト済み>
//【指定範囲の文字列】で初期化する。( ポインタ版 ) ( append() )

// STL::CStringW text1;
// WCHAR src[] = L”かきくけこ”;
// text1.InitByRange( src + 1, src + 3 ); // text1 は、”きく” で初期化される。

inline std::wstring& InitByRange( const WCHAR* p_src_start_, const WCHAR* p_src_end_ )
{
return text.assign( p_src_start_, p_src_end_ );
}

// ————————————————-<OK><テスト済み>
//【指定範囲の文字列】で初期化する。( イテレータ版 ) ( append() )

// STL::CStringW text1;
// std::wstring src( L”かきくけこ”);
// std::wstring::iterator itr = src.begin();
// text1.InitByRange( itr + 1, itr + 3 ); // text1 は、”きく” で初期化される。

inline std::wstring& InitByRange( const Iterator src_start_itr_, const Iterator src_end_itr_ )
{
return text.assign( src_start_itr_, src_end_itr_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】と比較する。 ( compare() )

// ※この比較では、大文字・小文字は区別される。
// ( ( L”Uma” == L”uma” ) は false )

inline bool Compare( const std::wstring& text_ )
{
return ( text.compare( text_ ) == 0 );
}

// ————————————————-<OK><テスト済み>
//【指定範囲】と【指定文字列】を比較する。( compare() )

// 引数1,2で指定された範囲の部分文字列と、指定された文字列を比較する。

inline bool Compare(
const size_t index_, // 比較する部分のオフセット。 ( この文字列の )
const size_t length_, // 比較する部分の文字数。( この文字列の )
const std::wstring& text_ // 比較する文字列。
)
{
return ( text.compare( index_, length_, text_ ) == 0 );
}

// ————————————————-<OK><テスト済み>
//【指定範囲】と【指定文字列の指定範囲】を比較する。( compare() )

inline bool Compare(
const size_t index_, // 比較する部分のオフセット。 ( この文字列の )
const size_t length_, // 比較する部分の文字数。( この文字列の )
const std::wstring& text_, // 比較する文字列。
const size_t text_offset_, // 比較する部分のオフセット。 ( 指定文字列の )
const size_t text_length_ // 比較する部分の文字数。( 指定文字列の )
)
{
return ( text.compare( index_, length_, text_, text_offset_, text_length_ ) == 0 );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】と比較する。 ( compare() )

inline bool Compare( const WCHAR* p_text_ )
{
return ( text.compare( p_text_ ) == 0 );
}

// ————————————————-<OK><テスト済み>
//【指定範囲】と【指定文字列】を比較する。( compare() )

inline bool Compare(
const size_t index_, // 比較する部分のオフセット。 ( この文字列の )
const size_t length_, // 比較する部分の文字数。( この文字列の )
const WCHAR* p_text_ // 比較する文字列。
)
{
return ( text.compare( index_, length_, p_text_ ) == 0 );
}

// ————————————————-<OK><テスト済み>
//【指定範囲】と【指定文字列の指定範囲】を比較する。( compare() )

inline bool Compare(
const size_t index_, // 比較する部分のオフセット。 ( この文字列の )
const size_t length_, // 比較する部分の文字数。( この文字列の )
const WCHAR* p_text_, // 比較する文字列。
const size_t text_length_ // 比較する部分の文字数。( 指定文字列の )
)
{
return ( text.compare( index_, length_, p_text_, text_length_ ) == 0 );
}

// ————————————————-<OK><テスト済み>
//【指定範囲の部分文字列】を切り出して返す。( substr() )

// ※【戻り値】を参照にすると、【ローカルのアドレス】が返る。

inline std::wstring SubString( const size_t start_index_, const size_t length_ )
{
return text.substr( start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を追加する。 ( append() )

// ※ std::wstring::value_type は、wchar_t 。

inline std::wstring& Add( const WCHAR* p_text_ )
{
return text.append( p_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を追加する。 ( append() )

inline std::wstring& Add( const WCHAR* p_text_ , const size_t length_ )
{
return text.append( p_text_, length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を追加する。 ( append() )

inline std::wstring& Add( const std::wstring& text_ )
{
return text.append( text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を追加する。 ( append() )

inline std::wstring& Add( const std::wstring& text_ , const size_t start_index_, const size_t length_ )
{
return text.append( text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【文字】を末尾に追加する。 ( push_back() )

inline void AddChar( const WCHAR char_ )
{
text.push_back( char_ );
}

// ————————————————-<OK><テスト済み>
//【指定した文字】を指定した文字数だけ追加する。 ( append() )

inline std::wstring& AddChar( const WCHAR char_, const size_t count_ )
{
return text.append( count_, char_ );
}

// ————————————————-<OK><テスト済み>
//【指定範囲の文字列】を追加する。( ポインタ版 ) ( append() )

// WCHAR src_text[] = L”かきくけこ”;
// std::wstring added_text = t1.Add( src_text + 1, src_text + 3 ); // “きく” が追加される。

inline std::wstring& Add( const WCHAR* p_src_start_, const WCHAR* p_src_end_ )
{
return text.append( p_src_start_, p_src_end_ );
}

// ————————————————-<OK><テスト済み>
//【指定範囲の文字列】を追加する。( イテレータ版 ) ( append() )

// std::wstring src_text( L”かきくけこ”);
// std::wstring::iterator itr = src_text.begin();
// std::wstring added_text = t1.Add( itr + 1, itr + 3 ); // “きく” が追加される。

inline std::wstring& Add( const Iterator src_start_itr_, const Iterator src_end_itr_ )
{
return text.append( src_start_itr_, src_end_itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

inline std::wstring& Insert( const size_t index_, const WCHAR* p_text_ )
{
return text.insert( index_, p_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

// text1.Insert( 1, L”かきくけこ”, 3 ); // 2文字目に、”かきく” が挿入される。( 引数3は、挿入する文字数 )

inline std::wstring& Insert( const size_t index_, const WCHAR* p_text_, const size_t text_length_ )
{
return text.insert( index_, p_text_, text_length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

inline std::wstring& Insert( const size_t index_, const std::wstring& text_ )
{
return text.insert( index_, text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

// std::wstring src( L”かきくけこ” );
// text1.InsertByRange( 1, src, 1, 2 ); // 2文字目に、”きく” を挿入する。

inline std::wstring& InsertByRange(
const size_t index_,
const std::wstring& text_,
const size_t text_offset_,
const size_t text_length_
)
{
return text.insert( index_, text_, text_offset_, text_length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

// ※【指定したイテレータの指す位置までの文字列】で初期化される。
//
// text1.Insert( text1.GetFirstItr() + 2 ); // 2文字目までの文字列になる。

// ※他のインスタンスのイテレーターを渡すとコケる。
// ※begin()で取得したイテレータをそのまま渡すとコケる。( 1文字目は、begin() + 1 )

//・使い道がよくわからない。おそらく使うことはない。

inline Iterator Insert( Iterator itr_ )
{
return text.insert( itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字】を挿入する。 ( insert() )

//・【イテレータで指定した位置】に、【指定した文字】を挿入する。

inline Iterator InsertByChar( Iterator itr_, WCHAR char_ )
{
return text.insert( itr_, char_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

//・上記に加えて、さらに【挿入する文字数】を指定できる。

inline void InsertByChar( Iterator itr_, WCHAR char_, const size_t count_ )
{
text.insert( itr_, count_, char_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

// text1.InsertByChar( 1, L’か’, 3 );
//
// ・2文字目から、’か’ が 3文字、挿入される。( “あかかかいうえお” )

inline std::wstring& InsertByChar(
const size_t index_,
const WCHAR char_,
const size_t count_
)
{
return text.insert( index_, count_, char_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

inline void InsertByRange( Iterator itr_, const WCHAR* p_src_start_, const WCHAR* p_src_end_ )
{
text.insert( itr_, p_src_start_, p_src_end_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

inline void InsertByRange( Iterator dest_start_itr_, const Iterator src_start_itr_, const Iterator src_end_itr_ )
{
text.insert( dest_start_itr_, src_start_itr_, src_end_itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を挿入する。 ( insert() )

//・TInputIteratorには、読み取り専用のイテレータ型を指定する。

// STL::stringW t1( L”あいうえお” );
// std::string t2( “かきくけこ” );
// t1.InsertByRange<std::string::iterator>( t1.GetItr(1), t2.begin(), t2.end() );
//
// → “あきいうえお” とはならず、stringの箇所が文字化けしている。
// ( 要するに、挿入は成功したが、文字コードが異なるため、文字化けしている、 )

template<typename TInputIterator>
inline void InsertByRangeEx( Iterator itr_, TInputIterator src_start_itr_, TInputIterator src_end_itr_ )
{
text.insert( itr_, src_start_itr_, src_end_itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字列の指定部分】を削除して返す。 ( erase() )

// text1.RemoveAt( 1, 2 ); // 2文字目以降の2文字が削除される。 ( “あいうえお” → “あえお” )

inline std::wstring& RemoveAt( const size_t index_, const size_t length_ )
{
return text.erase( index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定indexの1文字】を削除し、【次の文字のイテレーター】を返す。( erase() )

// text1.Remove( text1.GetItr( 1 ) ); // 2文字目が削除される。
//
//・2文字目が削除されたので、3文字目が2文字目に移動する。
// 戻り値のイテレーターは、この文字を指している。

inline Iterator RemoveChar( Iterator itr_ )
{
return text.erase( itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字列の指定範囲】を削除し、【次の文字のイテレーター】を返す。 ( erase() )

// text1.RemoveByRange( text1.GetItr(1), text1.GetItr(2) ); // 2文字目から3文字目の範囲 ( 2文字目 ) が削除される。

inline Iterator RemoveByRange( Iterator start_itr_, Iterator end_itr_ )
{
return text.erase( start_itr_, end_itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】をクリアする。 ( clear() )

inline void Clear(void)
{
text.clear();
}

// ————————————————-<OK><テスト済み>
// カラ文字列ならtrueを返す。 ( empty() )

inline bool IsEmpty(void)
{
return text.empty();
}

// ————————————————-<OK><テスト済み>
//【文字列の指定範囲】をコピーする。  ( substr() )

// ※戻り値が参照でないのは、ローカルのアドレスを含んだ参照を返すためである。
// ( 参照にしても動作はするが、コンパイル時に警告が表示される )

inline std::wstring Substring( const size_t index_, const size_t length_ )
{
return text.substr( index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】をコピーする。 (コピーした文字数を返す) ( _Copy_s() )

//・copy()が使いものにならないため、安全性の高い_Copy_s()を使用している。
// ( この手の_s系メソッドで、コピー先とコピー元の要素数を指定しているのは、バッファオーバーランを防止するためである )

inline WCHAR* Copy(void)
{
size_t src_length = text.length(); // コピー元の文字数を取得しておく。

WCHAR* p_dest = new WCHAR[ src_length + 1 ]; // コピー先の文字列バッファを確保する。( +1 は、終端のNULL文字 )

size_t writed_length = text._Copy_s( p_dest, src_length + 1, src_length, 0 ); // コピーする。
//
// p1: コピー先の文字列バッファへのポインタ。
// p2: コピー先の文字列バッファの要素数。( 文字数 )
// p3: コピー元の文字数。
// p4: コピーを開始するオフセット位置。( コピー元のindex )
//
// 戻り値: コピーされた文字数が返る。

p_dest[ src_length ] = NULL; // 終端にNULL文字を入れる。

return p_dest;
}

// ————————————————-<OK><テスト済み>
//【文字列】を交換する。 ( swap() )

inline void Swap( CStringW& text_ )
{
text.swap( text_.GetString() );
}

// ————————————————-<OK><テスト済み>
//【文字数】を変更する。 ( resize() )

// ・追加された要素は、0クリアされている。
// ( “あいうえお” → “あいうえお” )

// ・一般的には、NULL文字までが文字列とみなされるが、
// lengthで返る文字数には、増加分も含まれている。
// ( ただし、NULL文字なので、表示はされない )

inline void Resize( const size_t new_length_ ) // 新しい文字数。
{
text.resize( new_length_ );
}

// ————————————————-<OK><テスト済み>
//【文字数】を変更する。 ( resize() )

// text.ResizeEx( 10, L’無’ ); // → “あいうえお無無無無無”

inline void ResizeEx(
const size_t new_length_, // 新しい文字数。
const WCHAR default_char_ // 新規要素は、この文字で初期化される。
)
{
text.resize( new_length_, default_char_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// 引数1~2の指定範囲を、指定文字列に置き換える。( ※一般的な、「検索→置換」とは別物 )

inline std::wstring& Replace(
const size_t index_, // 置換範囲のオフセット位置。 (置換先)
const size_t length_, // 置換範囲の文字数。 (置換先)
const WCHAR* p_src_text_ // 置き換える文字列。 (置換元)
)
{
return text.replace( index_, length_, p_src_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

inline std::wstring& Replace(
const size_t index_, // 置換範囲のオフセット位置。 (置換先)
const size_t length_, // 置換範囲の文字数。 (置換先)
const std::wstring& src_text_ // 置き換える文字列。 (置換元)
)
{
return text.replace( index_, length_, src_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW text1( L”あいうえお” );
// std::wstring text2( L”かきくけこ” );
// text1.Replace( text1.GetItr(1), text1.GetItr(2), text2 ); // → “あかきくけこうえお”

inline std::wstring& Replace(
const Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
const Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
const std::wstring& src_text_ // 置き換える文字列。 (置換元)
)
{
return text.replace( start_itr_, end_itr_, src_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW text1( L”あいうえお” );
// text1.Replace( 1,2, L’■’, 3 ); // → “あ■■■えお”

inline std::wstring& ReplaceByChar(
const size_t index_, // 置換範囲のオフセット位置。 (置換先)
const size_t length_, // 置換範囲の文字数。 (置換先)
const WCHAR src_char_, // 置き換える文字。 (置換元)
const size_t src_char_count_ // 置き換える文字の文字数。(置換元)
)
{
return text.replace( index_, length_, src_char_count_, src_char_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字】に置換する。 ( replace() )

// STL::stringW text1( L”あいうえお” );
// text1.Replace( text1.GetItr(1), text1.GetItr(2), L’■’ ); // → “あ■■■うえお”

inline std::wstring& ReplaceByChar(
const Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
const Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
const WCHAR src_char_, // 置き換える文字。 (置換元)
const size_t src_char_count_ // 置き換える文字の文字数。(置換元)
)
{
return text.replace( start_itr_, end_itr_, src_char_count_, src_char_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// 指定範囲を、指定文字列の先頭から指定文字数の部分文字列で置き換える。

// STL::CStringW text1( L”あいうえお” );
// std::wstring text2( L”かきくけこ” );
// text1.Replace( 1, 2, L”かきくけこ”, 2 ); // → “あかきえお”

inline std::wstring& ReplaceByRange(
const size_t index_, // 置換範囲のオフセット位置。 (置換先)
const size_t length_, // 置換範囲の文字数。 (置換先)
const WCHAR* p_src_text_, // 置き換える文字列。 (置換元)
const size_t src_length_ // 置換範囲の文字数。 (置換元)
)
{
return text.replace( index_, length_, p_src_text_, src_length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::CStringW text1( L”あいうえお” );
// std::wstring text2( L”かきくけこ” );
// text1.Replace( 1, 2, text2, 1, 2 ); // → “あきくえお”

inline std::wstring& ReplaceByRange(
const size_t index_, // 置換範囲のオフセット位置。 (置換先)
const size_t length_, // 置換範囲の文字数。 (置換先)
const std::wstring& src_text_, // 置き換える文字列。 (置換元)
const size_t src_offset_, // 置換範囲のオフセット位置。 (置換元)
const size_t src_length_ // 置換範囲の文字数。 (置換元)
)
{
return text.replace( index_, length_, src_text_, src_offset_, src_length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW text1( L”あいうえお” );
// text1.Replace( text1.GetItr(1), text1.GetItr(2), L”かきくけこ” ); // → “あかきくけこうえお”

inline std::wstring& ReplaceByRange(
const Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
const Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
const WCHAR* p_src_text_ // 置き換える文字列。 (置換元)
)
{
return text.replace( start_itr_, end_itr_, p_src_text_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW text1( L”あいうえお” );
// text1.Replace( text1.GetItr(1), text1.GetItr(2), L”かきくけこ” ); // → “あかきうえお”

inline std::wstring& ReplaceByRange(
const Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
const Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
const WCHAR* p_src_text_, // 置き換える文字列。 (置換元)
const size_t src_length_ // 置換範囲の先頭からの文字数。(置換元)
)
{
return text.replace( start_itr_, end_itr_, p_src_text_, src_length_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW text1( L”あいうえお” );
// WCHAR src[] = L”らりるれろ”;
// t1.ReplaceByRange( t1.GetItr(1), t1.GetItr(2), src + 1, src + 3 ); // → “あらりうえお”

inline std::wstring& ReplaceByRange(
Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
const WCHAR* p_src_start_, // 置換範囲の始点ポインタ。 (置換元)
const WCHAR* p_src_end_ // 置換範囲の終点ポインタ。 (置換元)
)
{
return text.replace( start_itr_, end_itr_, p_src_start_, p_src_end_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW t1( L”あいうえお” );
// STL::stringW t2( L”かきくけこ” );
// t1.ReplaceByRange( t1.GetItr(1), t1.GetItr(2), t2.GetItr(1), t2.GetItr(2) ); // → “あきうえお”

inline std::wstring& ReplaceByRange(
Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
const Iterator src_start_itr_, // 置換範囲の始点イテレーター。 (置換元)
const Iterator src_end_itr_ // 置換範囲の終点イテレーター。 (置換元)
)
{
return text.replace( start_itr_, end_itr_, src_start_itr_, src_end_itr_ );
}

// ————————————————-<OK><テスト済み>
//【文字列】を置換する。 ( replace() )

// STL::stringW t1( L”あいうえお” );
// STL::stringW t2( L”かきくけこ” );
// t1.ReplaceByRange<std::wstring::iterator>( t1.GetItr(1), t1.GetItr(2), t2.GetItr(1), t2.GetItr(2) ); // → “あきうえお”

template<class TInputIterator>
inline std::wstring& ReplaceByRange(
Iterator start_itr_, // 置換範囲の始点イテレーター。 (置換先)
Iterator end_itr_, // 置換範囲の終点イテレーター。 (置換先)
TInputIterator src_start_itr_, // 置換範囲の始点イテレーター。 (置換元)
TInputIterator src_end_itr_ // 置換範囲の終点イテレーター。 (置換元)
)
{
return text.replace( start_itr_, end_itr_, src_start_itr_, src_end_itr_ );
}
// ————————————————-<OK><テスト済み>
//【指定文字】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find() )

// STL::stringW t1( L”あいうえお” );
//
// size_t result = text1.IndexOf( L’う’, 0 ); // 要素[0]から検索する。
//
// if ( result == wstring::npos ) // 該当indexが無い場合は、trueになる。
// else // 今回は、要素[2]が ‘う’ なので、2 が返る。

inline size_t IndexOf( const WCHAR char_, const size_t start_index_ = 0 )
{
return text.find( char_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find() )

// size_t result = text1.IndexOf( L”えお”, 0 ); // 3 が返る。

inline size_t IndexOf( const WCHAR* p_text_, const size_t start_index_ = 0 )
{
return text.find( p_text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find() )

// size_t result = text1.IndexOf( L”えお”, 0, 4 ); // 4文字目まで判定する。( 結果は npos )
//
// ※ 4文字目の要素[3] には、’え’ があるが、
// 5文字目の要素[4] の ‘お’ が範囲外で判定されないため、nposを返す。

inline size_t IndexOf( const WCHAR* p_text_, const size_t start_index_, const size_t length_ )
{
return text.find( p_text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find() )

inline size_t IndexOf( const std::wstring& text_, const size_t start_index_ = 0 )
{
return text.find( text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字以外】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find_first_not_of() )

inline size_t NotIndexOf( const WCHAR char_, const size_t start_index_ )
{
return text.find_first_not_of( char_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find_first_not_of() )

inline size_t NotIndexOf( const WCHAR* p_text_, const size_t start_index_ )
{
return text.find_first_not_of( p_text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find_first_not_of() )

inline size_t NotIndexOf( const WCHAR* p_text_, const size_t start_index_, const size_t length_ )
{
return text.find_first_not_of( p_text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を検索し、【最初に見つかった箇所の先頭index】を返す。 ( find_first_not_of() )

inline size_t NotIndexOf( const std::wstring& text_, const size_t start_index_ )
{
return text.find_first_not_of( text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字】を検索し、【最後に見つかった箇所の先頭index】を返す。 ( find_last_of() )

inline size_t LastIndexOf( const WCHAR char_, const size_t start_index_ )
{
return text.find_last_of( char_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】を検索し、【最後に見つかった箇所の先頭index】を返す。 ( find_last_of() )

inline size_t LastIndexOf( const WCHAR* p_text_, const size_t start_index_ )
{
return text.find_last_of( p_text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】を検索し、【最後に見つかった箇所の先頭index】を返す。 ( find_last_of() )

inline size_t LastIndexOf( const WCHAR* p_text_, const size_t start_index_, const size_t length_ )
{
return text.find_last_of( p_text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列】を検索し、【最後に見つかった箇所の先頭index】を返す。 ( find_last_of() )

inline size_t LastIndexOf( const std::wstring& text_, const size_t start_index_ )
{
return text.find_last_of( text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字以外】を検索し、【最後に見つかった箇所の先頭index】を返す。( find_last_not_of() )

inline size_t NotLastIndexOf( const WCHAR char_, const size_t start_index_ )
{
return text.find_last_not_of( char_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を検索し、【最後に見つかった箇所の先頭index】を返す。( find_last_not_of() )

inline size_t NotLastIndexOf( const WCHAR* p_text_, const size_t start_index_ )
{
return text.find_last_not_of( p_text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を検索し、【最後に見つかった箇所の先頭index】を返す。( find_last_not_of() )

inline size_t NotLastIndexOf( const WCHAR* p_text_, const size_t start_index_, const size_t length_ )
{
return text.find_last_not_of( p_text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を検索し、【最後に見つかった箇所の先頭index】を返す。( find_last_not_of() )

inline size_t NotLastIndexOf( const std::wstring text_, const size_t start_index_ )
{
return text.find_last_not_of( text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字以外】を逆順に検索し、【最初に見つかった位置】を返す。( rfind() )

inline size_t IndexOf_Reverse( const WCHAR char_, const size_t start_index_ )
{
return text.rfind( char_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を逆順に検索し、【最初に見つかった位置】を返す。( rfind() )

inline size_t IndexOf_Reverse( const WCHAR* p_text_, const size_t start_index_ )
{
return text.rfind( p_text_, start_index_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を逆順に検索し、【最初に見つかった位置】を返す。( rfind() )

inline size_t IndexOf_Reverse( const WCHAR* p_text_, const size_t start_index_, const size_t length_ )
{
return text.rfind( p_text_, start_index_, length_ );
}

// ————————————————-<OK><テスト済み>
//【指定文字列以外】を逆順に検索し、【最初に見つかった位置】を返す。( rfind() )

inline size_t IndexOf_Reverse( const std::wstring& text_, const size_t start_index_ )
{
return text.rfind( text_, start_index_ );
}

// —————————————————–<OK><テスト済み>
//【内部的に確保される要素数】を返す。 ( capacity() )

//・未設定の状態だと、要素数が設定されている。

inline size_t GetCapacity(void)
{
return text.capacity();
}

// —————————————————–<OK><テスト済み>
//【内部的に確保される要素数】を変更する。 ( reserve() )

// ※wstringは、内部的にメモリ領域を多めに確保していて、この値は、その際の要素数。
// 多めに見積もっておけば、要素数が拡張された際の、再確保&コピーをしなくて済む。
//
// ・この値は、wstring::capacity()で取得できる。
// ・多すぎる場合は、wstring::shrink_to_fit()で切り詰めることができる。

inline void SetCapacity( const size_t capacity_ )
{
text.reserve( capacity_ );
}

// ————————————————-<OK><テスト済み>
//【先頭のイテレータ】を返す。 ( begin() )

inline Iterator GetFirstItr(void)
{
return text.begin();
}

// ————————————————-<OK><テスト済み>
//【末尾のイテレータ】を返す。 ( end() )

inline Iterator GetLastItr(void)
{
return text.end();
}

// —————————————————–<OK><テスト済み>
// 逆順ループ時の【最初の要素([count-1])のイテレータ】を返す。( rbegin() )

inline RevIterator GetFirstItr_Rev(void)
{
return text.rbegin();
}

// —————————————————–<OK><テスト済み>
// 逆順ループ時の【最後の要素([0])のイテレータ】を返す。( rend() )

inline RevIterator GetLastItr_Rev(void)
{
return text.rend();
}

// ————————————————-
// #################################################
// 演算子のオーバーロード
// #################################################
// ————————————————-
// CString = instance + CString

inline std::wstring& operator+( std::wstring& text_ )
{
text += text_;

return text;
}

// ————————————————-
// instance += CString

inline void operator+=( std::wstring& text_ )
{
text += text_;
}

// ————————————————-
// instance = CString

inline void operator=( std::wstring& text_ )
{
text = text_;
}

// ————————————————-
// bool result = ( instance == CString )

inline bool operator==( std::wstring& text_ )
{
return (text == text_);
}

// ————————————————-
// #################################################
// static 関数
// #################################################
// ————————————————-
//【ワイド文字列】を、【Int32値】に変換して返す。( stol() )

//static inline int ToInt32(
// const std::wstring text_, // 変換する文字列。
// const size_t start_index_ = 0, // オフセット位置。
// const int base_ = 10 // 基数。規定値は10。( 10進数表記 )
// )
// {
//return std::stol( text_, start_index_, base_ );
// }

//// ————————————————-
////【ワイド文字列】を、【UInt32値】に変換して返す。( stoul() )

//static inline unsigned int ToUInt32(
// const std::wstring text_, // 変換する文字列。
// const size_t start_index_ = 0, // オフセット位置。
// const int base_ = 10 // 基数。規定値は10。( 10進数表記 )
// )
// {
// return std::stoul( text_, start_index_, base_ );
// }

//// ————————————————-
////【ワイド文字列】を、【Int64値】に変換して返す。( stoll() )

//static inline __int64 ToInt64(
// const std::wstring text_, // 変換する文字列。
// const size_t start_index_ = 0, // オフセット位置。
// const int base_ = 10 // 基数。規定値は10。( 10進数表記 )
// )
// {
// return std::stoll( text_, start_index_, base_ );
// }

//// ————————————————-
////【ワイド文字列】を、【UInt64値】に変換して返す。( stoull() )

//static inline unsigned __int64 ToUInt64(
// const std::wstring text_, // 変換する文字列。
// const size_t start_index_ = 0, // オフセット位置。
// const int base_ = 10 // 基数。規定値は10。( 10進数表記 )
// )
// {
// return std::stoull( text_, start_index_, base_ );
// }

//// ————————————————-
////【ワイド文字列】を、【float値】に変換して返す。( stof() )

//static inline float ToFloat(
// const std::wstring text_, // 変換する文字列。
// const size_t start_index_ = 0 // オフセット位置。
// )
// {
// return std::stof( text_, start_index_ );
// }

//// ————————————————-
////【ワイド文字列】を、【double値】に変換して返す。( stod() )

////・「long double」版のstold()には、「long」が付いているが、doubleと同じ64bit。

//static inline double ToDouble(
// const std::wstring text_, // 変換する文字列。
// const size_t start_index_ = 0 // オフセット位置。
// )
// {
// return std::stod( text_, start_index_ );
// }

//// ————————————————-
////【double値】を、【ワイド文字列】に変換して返す。( to_wstring() )

//static inline std::wstring FromDouble( long double value_ )
// {
// return std::to_wstring( value_ );
// }

//// ————————————————-
////【long long値】を、ワイド文字列に変換して返す。( to_wstring() )

//static inline std::wstring FromInt64( __int64 value_ )
// {
// return std::to_wstring( value_ );
// }

//// ————————————————-
////【unsigned long long】値を、ワイド文字列に変換して返す。( to_wstring() )

//static inline std::wstring FromUInt64( unsigned __int64 value_ )
// {
// return std::to_wstring( value_ );
// }

// ————————————————-

}; // end class

}; // end namespace

// ————————————————-
#endif

コメントする

カテゴリー: C++, STL

文字コードの概要

コンピュータ上で文字列を扱う場合は、

.NetJavaには、stringという基本データ型があります。

// ——————————

// string型の文字列変数「namae」に、文字列を代入する。

string namae = “ハム太”;

// ——————————

ネイティブC/C++で書く場合でも、

STLを使っていい場合なら、std::string クラスがあるし、

MFCを使う場合は、CStringクラスを使えば、同じような事ができます。

しかし、WindowsAPI や、その他のCOMライブラリなどでは

これらのクラスは対応しておらず、直接渡すことはできません。

これらの関数引数には、文字配列を渡す必要があります。

// ————————————–

char multi_text [] = “あいうえお”;          // マルチバイト文字の配列。

wchar_t wide_text[] = L“あいうえお”;  // ワイド文字の配列。

// ————————————–

大きく分けて、この二通りがあるんですが、

SJISで書く場合には、char型 (マルチバイト文字) を使い、

Unicodeで書く場合は、wchar_t 型 (ワイド文字) を使います。

あとで決めたい場合は、TCHAR型を使います。

TCHAR型は、_UNICODE定数が#defineされている場合は

wchar_t として解釈され、そうでない場合は、charとして解釈されます。

// ——————————-

// TCHAR型の定義

#ifdef _UNICODE
typedef wchar_t TCHAR
#elseif
  typedef char TCHAR
#endif

// ——————————-

Cランタイムの関数WindowsAPIの関数も、
文字列を扱うものは、2通り定義されていて、

たとえばMessageBox関数には、

ANSI (の日本語拡張のSJISなど、マルチバイト文字)  に対応した MessageBoxA関数と、

Unicode(のUTF-16などワイド文字)に対応したMessageBoxW関数があり、

単に、「MessageBox」と書いた場合には、

渡された引数によって、切り替わるようになっています。

コンピューターの内部では、文字データは、

文字コード」という番号で、記録されています。

顔文字などで有名な「ASCIIコードセット」は、

英数字基本的な記号しか扱わないため、

1文字のコードを、0~127番までの7bitで記録しています。

( 1バイト固定であるので、「シングルバイト文字」という。
日本語版のasciiには、半角カナ文字があって、

161~223番を使用するため、8bit (1バイト) をフルに使う )

しかし、日本語環境では、ひらがなカタカナに加えて、

膨大な数の漢字を使用するため、

1バイト ( 0~255 ) では到底足りません。

そこで登場するのがマルチバイト文字で、

一般的には、「SJISコードセット」が使用されますが、

( 日本語版のWindowsでは、日本語拡張版の「cp932コードセット」が標準。

つまり、特に指定しない場合は、char配列は、

cp932の文字コードの配列」として解釈されるのです。)

これらのコード体系のデータでは、ASCIIコードに加えて、

2byte以上の文字混在して記録されています。

このマルチバイト文字は、全角文字が使用できる一方で、

—————————————–

1文字おおよそ3バイト使用する。

・何文字目か、わかりにくい。( 判定する手間がかかる )

—————————————–

などの難点もあります。

これに対して、ワイド文字では、

1文字を、おおむね2バイトで記録します。

( 半角文字では、未使用の1バイト0で埋められます。)

このワイド文字は、おもにUnicodeで使用されます。

Unicodeは、世界中の文字を

混在して記録できるようにするために制定された

ワールドワイドなコード体系で、正確には

1文字4バイトで記録している文字もあります。

ただし、これらの文字はまだ、API側で未対応のため、

MessageBoxWに渡しても、文字化けしてしまいます。

( 普段は使わないような難解な漢字なので、無視しても無問題 )

これに対応するためなのか、どうかわかりませんが、

1文字4バイトで記録しているファイルフォーマットがあります。

————————————–

UTF-8」 … マルチバイト文字のUnicode。

UTF-16」… 1文字を2バイトで記録しているUnicode。

UTF-32」 … 1文字を4バイトで記録しているUnicode。 ←コレ

————————————–

テキストファイルの場合は、
先頭に「BOM」(ByteOrderMark) が記録されていて、
テキストエディタなどで読み込まれる際には、これに応じて

どの方式で記録されたデータかを判別して表示しています。

しかし、必ずしもBOMが記録されているとは限らないため、

その場合には、エディタがどのコードセットのデータなのか判別できず

文字化けして表示されてしまいます。

Unicodeは本来、「文字化け」を解消しようとして

制定された統一規格だったのですが、

あとで追加された文字によって、

2バイト ( 0~65535 ) では足りなくなり、

前述の、ファイルへの記録方式のこともあって、

完全な問題解決には至っていません。

UNIXMacではUTF32BEが使用されているようで、

将来的にはUTF32BEで統一されるのかも知りません。

( 「BE」は、「ビックエンディアン」の略。

Windowsは、「LE」(リトルエンディアン)方式でファイルに記録するので、

2バイト以上の値をファイルに書き込んだり読み込む際には、

1バイト単位逆順に並べなおして複合する。)

Windowsでは、SJIS(cp932)が標準であるため、

char配列でSJISを使うことが多かったのですが、

現在では、Unicodeの使用が推奨されています。

ちなみに、wchar_t ( ワイド文字 ) を使用する場合は、

「Unicodeの配列である」と解釈されるようです。

コメントする

カテゴリー: C++, STL

ハム太と作るC++ライブラリ STL編

 

ここまでの内容が本になりました。↓

http://p.booklog.jp/book/74234

 

出版記念パーティーでもしょうかな。^^

文字列は、文字コードと含めて一緒に出します。

一応予告をしておくと、

KFCのコアな部分は後回しにして、

WIC MME MSXML など、オマケ部分から書いていきます。

コメントする

カテゴリー: C++, STL

STL::CAllocator

#pragma once
#ifndef _STL_ALLOCATOR_H_
#define _STL_ALLOCATOR_H_
#include<memory>
using namespace std;
namespace STL
{
// =====================================================
// アロケータ‐クラスの定義 ( std::allocatorのカスタムクラス )
//・ベクターなどのメモリを確保する処理には、汎用化するための処理が含まれている。
//  これをカスタマイズすると、インスタンス化時の実行速度が向上する。
//・効果的なのは、ベクターとデキューだけであり、それ以外のコンテナクラスでは意味が無い。
// 詳細はこちら↓
//http://msdn.microsoft.com/ja-jp/library/vstudio/5fk3e8ek.aspx
// ※要素が存在しないindexやイテレーターを渡した場合はコケる。
//   ( 速度を優先するため、STL側でも範囲判定はあまり行なっていない )
template <typename T>
class /* _EXPORT */ CAllocator : public std::allocator<T>
{
public:
// ————————————————<OK><テスト済み>
// コンストラクタ
CAllocator() : std::allocator<T>::allocator()
{
}
// ————————————————<OK><テスト済み>
// コンストラクタ
CAllocator( const STL::CAllocator<T>& a_ ) : std::allocator<T>::allocator( a_ )
{
}
// ————————————————<OK><テスト済み>
// メモリを動的に確保する。
// n:      確保する数
// hint:   確保する際のヒント ( 使用される保証はない )
// 戻り値: 確保した先頭アドレス
T* allocate( size_t n, const void* hint = 0 ) 
{
       return new T[ sizeof(T) * n ];
       // return (T*) operator new( n * sizeof(T) );
}
// ————————————————<OK><テスト済み>
// メモリを解放する。
    // p: 解放するポインタ
    // n: 開放するサイズ
    void deallocate( T* p, size_t n 
{
      delete [] p;
         // ::operator delete(p);
}
// ————————————————<OK><テスト済み>
// 最長シーケンスの長さを返す。 ( ※max_size() で返される値。これを越えてリサイズはできない )
size_t max_size() const
{
        return (size_t) -1 / sizeof(T);
}
// ————————————————<OK><テスト済み>
// コンストラクタの初期化処理
    //p:    初期化するポインタ
    //val:  初期化する値
   void construct( T* p, const T& val ) 
   {
           new ((void*)p) T(val);
   }
//————————————————<OK><テスト済み>
// デストラクタを呼ぶ。
   void destroy( T* p 
   {
          (p)->~T();
   }
// —————————————————–
}; // end class
// ====================================================
}; // end namespace
// —————————————————-
#endif

コメントする

カテゴリー: C++, STL

STL::CAutoPtr

#pragma once
#ifndef _STL_AUTO_PTR_H_
#define _STL_AUTO_PTR_H_
#include <memory>
using namespace std;
namespace STL
{
// =====================================================
// 自動ポインタクラスの定義 ( std::auto_ptrのラッパー )
//・コンストラクタで渡したポインタを、自動的に解放してくれる。     std::auto_ptr<CObject> ap1( new CObject() );
//・->演算子(上書き)を使って、ポインタのメンバにアクセスできる。  CObject* p_obj = ap1->GetValue();
// ※配列のポインタは、格納できない。
// ※同じポインタを、複数のオートポインタに格納することはできない。
// ※オートポインタを、コンテナの要素にはできない。
// std::auto_ptr     … ローカル変数として使用する場合は軽くていい。
// boost::shared_ptr … コンテナを使う場合や関数に渡す場合に使用する。
// ※要素が存在しないindexやイテレーターを渡した場合はコケる。
//   ( 速度を優先するため、STL側でも範囲判定はあまり行なっていない )
template<typename T>
class /* _EXPORT */ CAutoPtr
{
protected: // publicでもOK。
// —————————————————-
// データメンバ
std::auto_ptr<T> ptr; // 自動ポインタ本体。
public:
// —————————————————–<OK><テスト済み>
// オートポインタ本体の型
    typedef typename std::auto_ptr<T> InsideType; // オートポインタ本体の型
// —————————————————–<OK><テスト済み>
// コンストラクタ
CAutoPtr() : ptr()
{
}
// —————————————————–<OK><テスト済み>
// コンストラクタ
CAutoPtr( T* p_ ) : ptr( p_ )
{
}
// —————————————————–<OK><テスト済み>
// デストラクタ
~CAutoPtr( void )
{
}
// —————————————————–<OK><テスト済み>
//【オートポインタ】を返す。
inline InsideType& GetAutoPtr( void )
{
                  return ptr;
}
// —————————————————–<OK><テスト済み>
//【オートポインタ】を格納する。
inline void SetAutoPtr( InsideType& ptr_ )
{
                  ptr = ptr_;
}
// —————————————————–<OK><テスト済み>
//【ポインタ】を返す。                                                            ( get() )
inline T* GetPtr( void )
{
                   return ptr.get();
}
// —————————————————–<OK><テスト済み>
//【ポインタ】を変更する。                                                   ( reset() )
inline void SetPtr( T* p_ = NULL )
{
                 ptr.reset( p_ );
}
// —————————————————–<OK><テスト済み>
//【ポインタ】を明示的に解放する。                                   ( release() )
inline void Release( void )
{
                  ptr.release();
}
// ————————————————-
// #################################################
// 演算子のオーバーロード
// #################################################
// ————————————————-<OK><テスト済み>
//  T* p = ap1.get(); // auto_ptrにも -> がオーバーロードされているので、
//                          // それを使ってポインタのメンバにアクセスすることもできる。
inline T* operator->()
{
return ptr.get();
}
// ————————————————-<OK><テスト済み>
//  T value = *ap1; // ポインタの値を取り出す。
inline T operator*()
{
return *ptr;
}
// ————————————————-<OK><テスト済み>
//  instance = ap2
inline void operator=( CAutoPtr<T>& ptr_ )
{
ptr = ptr_.GetAutoPtr();
}
// —————————————————–
}; // end class
}; // end namespace
// —————————————————-
#endif

コメントする

カテゴリー: C++, STL

STL::CDeque

#pragma once
#ifndef _STL_DEQUE_H_
#define _STL_DEQUE_H_
// アロケータクラスのヘッダファイルをインクルードしておく。
#include “STL_Allocator.h”
#include <deque>
using namespace std;
namespace STL
{
// —————————————————-
//【使用例】
// =====================================================
// デキュークラスの定義 ( std::dequeのラッパー )
//・キューとの違いは、両端に値を追加できること。
//・メソッドの構成は、std::vector とほぼ同じ。( キャパシティの取得・設定ができない )
//※追加、削除、リサイズなどを行うと、要素のアドレスが変更されるため、以前のイテレータが使用できなくなる。
template<typename TValue>
class /* _EXPORT */ CDeque
{
protected: // publicでもOK。
// —————————————————-<OK><テスト済み>
// メンバ
std::deque<TValue,CAllocator<TValue>deque; // デキュー本体。
public:
// —————————————————–<OK><テスト済み>
// デキュー本体の型
    typedef typename std::deque<TValue,CAllocator<TValue>> InsideType; // デキュー本体の型
// —————————————————–<OK><テスト済み>
// イテレーター
         // 通常のイテレーター (ランダムアクセス)
typedef typename std::deque<TValue,CAllocator<TValue>>::iterator Iterator;
        // 逆順イテレーター (ランダムアクセス)
typedef typename std::deque<TValue,CAllocator<TValue>>::reverse_iterator RevIterator;
// —————————————————–<OK><テスト済み>
// コンストラクタ
 CDeque( void )
 {
 }
// —————————————————–<OK><テスト済み>
// デストラクタ
 ~CDeque( void )
 {
 }
// —————————————————–<OK><テスト済み>
//【指定値で初期化された指定数の要素】で初期化する。( assign() )
   inline void InitByValue( TValue value_, const size_t count_ )
   {
          deque.assign( count_, value_ );
   }
// —————————————————–<OK><テスト済み>
//【指定範囲の要素値】で初期化する。        ( assign() )
// dest_deque を、src_deque[5]、[6]、[7] で初期化する場合は、
//
// dest_deque.InitRange( src_deque.GetItr(5), src_deque.GetItr(8) );
   inline void InitByRange( Iterator src_start_itr_, Iterator src_end_itr_ )
   {
           deque.assign( src_start_itr_, src_end_itr_ );
   }
// —————————————————–<OK><テスト済み>
//【指定indexのイテレータ】を返す。
// ※戻り値のイテレータを、参照にしていないのには理由がある。
//   このクラスがローカル変数として宣言された場合、
//   スタック領域のアドレスを返してしまうため、コケるからである。
inline Iterator GetItr( const size_t index_ )
{
 return ( deque.begin() + index_ );
}
// —————————————————–<OK><テスト済み>
//【デキュー】を返す。
inline InsideType& GetDeque( void )
{
                 return deque;
}
// —————————————————–<OK><テスト済み>
//【デキュー】を格納する。
inline void SetDeque( InsideType& deque_ )
{
                deque = deque_;
}
// —————————————————–<OK><テスト済み>
//【要素数】を返す。                                                          ( size() )
inline size_t GetCount( void )
{
                return deque.size();
}
// —————————————————–<OK><テスト済み>
//【最大要素数】を返す。                                            ( max_size() )
// ※「size_t」の最大値。 (「size_t」は、32bitシステムでは「unsigned int」)
inline size_t GetMaxCount( void )
{
                 return deque.max_size();
}
// —————————————————–<OK><テスト済み>
//【要素数】を変更する。                                                ( resize() )
//・新しく追加された要素は、0クリアされている。
inline void Resize( const size_t length_ )
{
                 deque.resize( length_ );
}
// —————————————————–<OK><テスト済み>
//【要素数】を変更し、【追加された要素】を、【指定値】で初期化する。 ( resize() )
inline void ResizeEx( const unsigned int length_, TValue value_ )
{
                   deque.resize( length_, value_ );
}
// —————————————————–<OK><テスト済み>
//【最初の要素の値】を返す。                                          ( front() )
inline TValue GetFirstValue( void )
{
                 return deque.front();
}
// —————————————————–<OK><テスト済み>
//【最後の要素の値】を返す。                                           ( back() )
inline TValue GetLastValue( void )
{
                 return deque.back();
}
// —————————————————–<OK><テスト済み>
//【指定indexの要素値】を返す。                             ( 値 = deque[i] )
inline TValue GetValue( const size_t index_ )
{
return deque[ index_ ];
// deque.at( index_ ) の場合は、範囲外のindexに対して、out_of_range例外スローする。
}
// —————————————————–<OK><テスト済み>
//【指定indexに要素値】を格納する。                       ( deque[i] = 値 )
inline void SetValue( const size_t index_, TValue value_ )
{
                 deque[ index_ ] = value_;
}
// —————————————————–<OK><テスト済み>
//【要素】を末尾に追加する。                                    ( push_back() )
inline void Add( TValue value_ )
{
 return deque.push_back( value_ ); // 追加する。
}
// —————————————————–<OK><テスト済み>
//【指定イテレーターの要素】に、【要素】を挿入し、【挿入位置のイテレーター】を返す。( insert() )
// ※指定したイテレーターの要素に、指定値が格納される。
// ※指定するindexは、AddやResizeで拡張された範囲を超えるとコケる。
// ※逆順イテレータは受け付けない。
inline Iterator Insert( Iterator itr_, TValue value_ )
{
 return deque.insert( itr_, value_ ); // 挿入する。
}
// —————————————————–<OK><テスト済み>
//【指定イテレーターの要素】に、【指定数の要素】を挿入する。 ( insert() )
// ※逆順イテレータは受け付けない。
inline void InsertByValue( Iterator itr_, TValue value_, const size_t count_ )
{
 deque.insert( itr_, count_, value_ ); // 挿入する。
}
// —————————————————–<OK><テスト済み>
//【指定index】に、【指定範囲の要素】を挿入する。 ( insert() )
// ※逆順イテレータは受け付けない。
// deque1 の [1] に、deque2 の [5]、[6]、[7] を挿入する場合は、
//
// deque1.InsertByRange( deque1.GetItr(1), deque2.GetItr(5), deque2.GetItr(8) );
inline void InsertByRange( Iterator dest_itr_, Iterator src_start_itr_, Iterator src_end_itr_ )
{
 deque.insert( dest_itr_, src_start_itr_, src_end_itr_ ); // 挿入する。
}
// —————————————————–<OK><テスト済み>
//【指定index】に、【要素】を挿入し、【挿入位置のイテレーター】を返す。 ( insert() )
// ※指定したindexの要素に、指定値が格納される。
// ※指定するindexは、AddやResizeで拡張された範囲を超えるとコケる。
inline Iterator InsertAt( const size_t index_, TValue value_ )
{
 return deque.insert( deque.begin() + index_, value_ ); // 挿入する。
}
// —————————————————–<OK><テスト済み>
//【指定イテレータ-の指す要素】を削除し、【その次の要素のイテレーター】を返す。( erase() )
inline Iterator Remove( Iterator itr_ )
{
                 return deque.erase( itr_ );
}
// —————————————————–<OK><テスト済み>
//【指定範囲の要素】を削除し、【その次の要素のイテレーター】を返す。( erase() )
// ※逆順イテレータは受け付けない。
// deque1 の [5]、[6]、[7] を削除する場合は、
//
// deque1.RemoveByRange( deque1.GetItr(5), deque1.GetItr(8) );
inline Iterator RemoveByRange( Iterator start_itr_, Iterator end_itr_ )
{
                 return deque.erase( start_itr_, end_itr_ ); // 削除する。
}
// —————————————————–<OK><テスト済み>
//【指定indexの要素】を削除する。                                 ( erase() )
inline Iterator RemoveAt( const size_t index_ )
{
                  return deque.erase( deque.begin() + index_ );
}
// —————————————————–<OK><テスト済み>
//【最後の要素】を削除する。                                      ( pop_back() )
inline void RemoveLast( void )
{
                  deque.pop_back();
}
// —————————————————–<OK><テスト済み>
// クリアする。                                                                   ( clear() )
inline void Clear( void )
{
                deque.clear();
}
// —————————————————–<OK><テスト済み>
//【最初の要素のイテレータ】を返す。                                    ( begin() )
// int value = *itr; // ふつうに最初の要素の値が返る。
inline Iterator GetFirstItr( void )
{
                  return deque.begin();
}
// —————————————————–<OK><テスト済み>
//【最後の要素のイテレータ】を返す。                                      ( end() )
// int value = *itr;     // ※範囲外のポインタなのでアクセス違反エラーが出る。
// int value = *(itr-1); // ※これが最後の要素の値。( なぜか逆方向に進めてしまう )
inline Iterator GetLastItr( void )
{
                    return deque.end();
}
// —————————————————–<OK><テスト済み>
// 逆順ループ時の、【最初の要素([count-1])のイテレータ】を返す。 ( rbegin() )
// for ( RevIterator itr = deque1.rbegin() ; itr != deque1.rend(); itr++ )
// {
        //       int value = *(itr);
// }
// 要素数が3の場合、
//
// int value = *( itr );      // 要素[2]の値が返る。
// int value = *( itr – 1 ); // 要素[1]の値が返る。
// int value = *( itr – 2 ); // 要素[0]の値が返る。
inline RevIterator GetFirstItr_Rev( void )
{
                return deque.rbegin();
}
// —————————————————–<OK><テスト済み>
// 逆順ループ時の、【最後の要素([0])のイテレータ】を返す。     ( rend() )
// 要素数が3の場合、
//
// int value = *( itr – 1 ); // 要素[0]の値が返る。
// int value = *( itr – 2 ); // 要素[1]の値が返る。
// int value = *( itr – 3 ); // 要素[2]の値が返る。
        // ※ *itr は構文エラー。
// ※ *(itr) は範囲外のポインタなのでアクセス違反エラーが出る。
inline RevIterator GetLastItr_Rev( void )
{
                 return deque.rend();
}
// ————————————————-
// #################################################
// 演算子のオーバーロード
// #################################################
// ————————————————-<OK><テスト済み>
//  TValue value = instance[ index_ ]
// ※ int v1 = (*p_deque)[0];  これはできるが、(*p_deque)[0] = 10: これはできない。  *p1 = *p2; これはOK。
inline TValue operator[]( const size_t index_ )
{
return deque[ index_ ];
}
// ————————————————-<OK><テスト済み>
//  instance = CDeque
inline void operator=( CDeque<TValue>& deque_ )
{
deque = deque_.GetDeque();
}
// ————————————————-<OK><テスト済み>
//  bool result = ( instance == CDeque )
// ※要素値の総和が同値ならTRUE。
inline bool operator==( CDeque<TValue>& deque_ )
{
return ( deque == deque_.GetDeque() );
}
// ————————————————-<OK><テスト済み>
//  bool result = ( instance != CDeque )
inline bool operator!=( CDeque<TValue>& deque_ )
{
return ( deque != deque_.GetDeque() );
}
// —————————————————–
}; // end class
}; // end namespace
// —————————————————-
#endif

コメントする

カテゴリー: C++, STL

STL::Queue

#pragma once
#ifndef _STL_QUEUE_H_
#define _STL_QUEUE_H_
#include <queue>
using namespace std;
namespace STL
{
// =====================================================
// キュークラスの定義 ( std::queueのラッパー )
//・キューは、トンネルを詰めていくタイプのコンテナ。
//・新しい要素末尾追加し、先頭の要素を取り出しては削除していく。
//  [3] add→ [2][1] remove→ [0]
// push ( 押しこむ ) → pop ( 取り出す )
template<typename T>
class /* _EXPORT */ CQueue
{
protected: // publicでもOK。
// —————————————————-
// データメンバ
std::queue<T> queue; // キュー 本体。
public:
// —————————————————–<OK><テスト済み>
// キュー本体の型
    typedef typename std::queue<T> InsideType; // キュー本体の型
// —————————————————–
// コンストラクタ
   CQueue( void )
   {
   }
// —————————————————–
// デストラクタ
   ~CQueue( void )
   {
   }
// —————————————————–
//【キュー】を返す。
inline InsideType& GetQueue( void )
{
                 return queue;
}
// —————————————————–
//【キュー】を格納する。
   inline void SetQueue( InsideType& queue_ )
   {
          queue = queue_;
   }
// —————————————————–
//【要素数】を返す。                                                         ( size() )
inline size_t GetCount( void )
{
                return queue.size();
}
// —————————————————–
//【要素数】が0ならTRUEを返す。                                   ( empty() )
inline bool IsEmpty( void )
{
                 return queue.empty();
}
// —————————————————–
// 末尾に【要素】を追加する。                                          ( push() )
// [3] add→ [2][1][0]
inline void Add( T value_ )
{
                 queue.push( value_ );
}
// —————————————————–
// 先頭の【要素】を削除する。( 値を処理した後、削除する )     ( pop() )
// [2][1] remove→ [0]
inline void Remove( void )
{
                  queue.pop();
}
// —————————————————–
//【要素】を返す。 ( 削除はしない )                                    ( front() )
// [2][1][0] get→ [0]
inline T GetFrontValue( void )
{
                  return queue.front();
}
// —————————————————–
// 終端の【要素】を返す。( 取り出して削除はしない )            ( back() )
// [2] ←get [2][1][0]
inline T GetBackValue( void )
{
                 return queue.back();
}
// —————————————————–
}; // end class
}; // end namespace
// —————————————————-
#endif

コメントする

カテゴリー: C++, STL

STL::CStack

#pragma once
#ifndef _STL_STACK_H_
#define _STL_STACK_H_
#include <stack>
using namespace std;
namespace STL
{
// =====================================================
// スタッククラスの定義 ( std::stackのラッパー )
//・スタックは、要素を積み上げていくコンテナ。
//・最上段の要素に対して、Add()メソッドで要素を積み、Remove()で削除する。
//・値も、最上段の要素のものしか取得できない。( GetValue()で取得する )
//  [2] add →        [1][0]
//  [2] ← get&remove [1][0]
template<typename T>
class /* _EXPORT */ CStack
{
protected: // publicでもOK。
// —————————————————-
// データメンバ
std::stack<T> stack; // スタック 本体。
public:
// —————————————————–<OK><テスト済み>
// スタック本体の型
    typedef typename std::stack<T> InsideType; // スタック本体の型
// —————————————————–<OK><テスト済み>
// コンストラクタ
   CStack( void )
   {
   }
// —————————————————–<OK><テスト済み>
// デストラクタ
~CStack( void )
{
}
// —————————————————–<OK><テスト済み>
//【スタック】を返す。
   inline InsideType& GetStack( void )
   {
           return stack;
   }
// —————————————————–<OK><テスト済み>
//【スタック】を格納する。
   inline void SetStack( InsideType& stack_ )
   {
            stack = stack_;
   }
// —————————————————–<OK><テスト済み>
//【要素数】を返す。                                                          ( size() )
inline size_t GetCount( void )
{
                 return stack.size();
}
// —————————————————–<OK><テスト済み>
//【要素数】が0ならTRUEを返す。                                   ( empty() )
inline bool IsEmpty( void )
{
                return stack.empty();
}
// —————————————————–<OK><テスト済み>
// 最上段に【要素】を追加する。                                         ( push() )
// [3] add→   [2][1][0]
inline void Add( T value_ )
{
                 stack.push( value_ );
}
// —————————————————–<OK><テスト済み>
//【最上段の要素】を削除する。                                          ( pop() )
// [2] ←remove [1][0]
inline void Remove( void )
{
                 stack.pop();
}
// —————————————————–<OK><テスト済み>
//【最上段の要素値】を返す。                                             ( top() )
// [2]  ←get    [2][1][0]
inline T GetValue( void )
{
                 return stack.top();
}
// —————————————————–
}; // end class
}; // end namespace
// —————————————————-
#endif

コメントする

カテゴリー: C++, STL