このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com ロゴ
作成日 October 12, 2018、微調整 July 15, 2022
トップページ > Android 開発トップ > C/C++ による文字列操作 CString を代用
line
Android 開発
line

ここでは、C/C++ で、MFC の CString を代用するクラスについて、記録しています。

Windows 開発で、 MFC ( Microsoft Foundation Class、マイクロソフト提供の高機能クラス群 ) には、文字列を簡単に操作できる CString クラスが用意されています。 char 型のサイズを気にせず、代入や結合が簡単にでき、フォーマットも文字列比較もできるものです。

Android ネイティブアプリ開発では、画面表示には文字列は(今のところ)使いませんが、 ログ記録では使いたかったので、とりあえず最低限欲しかった機能を持ったクラスを作成しました。

ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
また、本サイトが初めての方は、まずこのページの注意事項をご覧ください。

▼ セクション一覧

MFC の CString クラスの使用例
CmxString クラスのヘッダー
【実装】 コンストラクター
【実装】 デストラクター
【実装】 Empty 関数(確保したメモリを解放)
【実装】 代入演算(operator =)
【実装】 自身に対する和演算(operator +=)
【実装】 比較演算(==、!=、<、>)


MFC の CString クラスの使用例

投稿 October 12, 2018

すでにご存じの方は、このセクションは飛ばしていただいて構いません。

文字列の代入や結合は、C/C++ では次のようになるかと思います。

char text[256];
strcpy(text, "hello,");
strcat(text, "developers.");

text に入れる文字列のサイズにより、バッファーオーバーランが起きたりしますから、危険もあります。 上記の例では、char text[8]; と定義した場合などです。

MFC の CString クラスを使うと、次のように書けます。

CString strText;
strText = "hello,";
strText += "developers.";

sprintf のような機能も持っています。

sprintf(text, "The value is %d.", 150);
strText.Format("The value is %d.", 150);

アイコン _sprintf でリンクエラーを回避する
古い Visual C++ プロジェクトを新しい Visual C++ プロジェクトに変換したとき、_sprintf 関数がエラーになる場合の回避方法について書いています。



文字列比較や部分取り出し、文字列検索など、ほかにもたくさんの機能がありますが、 今はログ出力する文字列を作成するのに便利に使えそうな機能を、代用のクラスで使えるようにしました。

▲ページ先頭へ

CmxString クラスのヘッダー

投稿 October 12, 2018

まずは、今回実装したクラスのヘッダーを記載します。 実際には、このようなクラスを集められるよう、また念のためクラス名が重ならないよう、ネームスペースに追加しています。

class CmxString
{
public:

	// コンストラクター  詳細 
	CmxString();
	CmxString(const char* text);

	// デストラクター  詳細 
	~CmxString();

	/**
	* 確保したメモリを解放します。  詳細 
	*/
	void Empty(void);

	/**
	* 代入演算  詳細 
	*   指定の文字列のサイズだけメモリを確保して、保持します。
	*/
	CmxString& operator = (const char* text);

	/**
	* 自身に対する和差積商演算(+=、-=、*=、/=)  詳細 
	*   CmxString を引数としても、char* にキャストされればこれで対応できます。
	*/
	CmxString& operator += (const char* text);

	/**
	* 比較演算(==、!=、<、>)  詳細 
	*   == オペレーターで、Compare と同じ働きを期待できます。
	*/
	bool operator == (const char* text) const;

	/**
	* char* へのキャスト演算子
	*/
	operator char*() const
	{
		if (m_text) {
			return m_text;
		}
		return NULL;
	}

	protected:

	// 内部管理メモリ
	char* m_text;
};

クラス名は、CmxString としていますが、もちろん何でも構いません。

▲ページ先頭へ

【実装】 コンストラクター

投稿 October 12, 2018

CmxString();
CmxString(char* text);
の2種類を用意しました。

使い方としては、
CmxString str;
str = "hello";

としてもいいし、
CmxString str("hello");
としてもいい、という具合です。

いずれも、char* m_text に NULL を設定して、メモリを確保していない状態とします。

最初から値を設定するコンストラクターとしては、operator = 演算子で、自身に文字列を設定しています。 この設定については、operator = 演算子の定義をご覧ください。

CmxString::CmxString()
	: m_text(NULL)
{
}

CmxString::CmxString(const char* text)
	: m_text(NULL)
{
	*this = text;
}
▲ページ先頭へ

【実装】 デストラクター

投稿 October 12, 2018

デストラクターでは、char* m_text にメモリが確保されている場合には解放する、 Empty 関数を呼び出しています。 この関数については、後述の Empty 関数をご参照ください。

CmxString::~CmxString()
{
	Empty();
}
▲ページ先頭へ

【実装】 Empty 関数(確保したメモリを解放)

投稿 October 12, 2018

確保したメモリを解放する関数です。 CString::Empty() と同じイメージです。

使用者が明示的にメモリを解放したい場合にも使えますが、 通常は、デストラクターから自動的に呼び出されますので、気にする必要はありません。

void CmxString::Empty(void)
{
	if (m_text) {
		free(m_text);
		m_text = NULL;
	}
}
▲ページ先頭へ

【実装】 代入演算(operator =)

投稿 October 12, 2018

CmxString str;
str = "hello";

のように、文字列をイコールで代入できるようにしています。

CmxString& CmxString::operator = (const char* text)
{
	size_t length;

	Empty();

	// 引数が NULL のとき
	if (!text) {
		return *this;
	}

	// 指定文字列のサイズだけメモリを確保します。
	length = strlen(text) + 1;		// 終端 NULL 用の1バイトを追加
	if (!(m_text = (char*)malloc(length))) {
		return *this;
	}

	// 文字列をコピーします。
	memset(m_text, 0, length);
	memcpy(m_text, text, length - 1);

	return *this;
}
▲ページ先頭へ

【実装】 自身に対する和演算(operator +=)

投稿 October 12, 2018

引数で指定された文字列を自身に結合します。

str = "hello, ";
str += "world!";

のように使います。

ヘッダーに char* へのキャストを記述していますので、
str = "hello,";
str1 = "world!";
str += str1;

のようにも使えます。

CmxString& CmxString::operator += (const char* text)
{
	size_t length, newLength;
	void* data;
	char* ptr;

	// 引数が NULL のときは、何もしません。
	if (!text) {
		return *this;
	}

	// 追加する文字列がなければ、何もしません。
	length = strlen(text);
	if (length < 1) {
		return *this;
	}

	// 自身が NULL であるなら、単なる設定になります。
	if (!m_text) {
		*this = text;
		return *this;
	}

	// 必要なサイズの新しいメモリを確保します。
	newLength = strlen(m_text) + length + 1;
	if (!(data = malloc(newLength))) {
		return *this;				// メモリを確保できず、追加せず終了します
	}

	// 新しく確保したメモリにコピーします。
	memset(data, 0, newLength);
	memcpy(data, m_text, strlen(m_text));		// もとのテキストをコピーします
	ptr = ((char*)data) + strlen(m_text);
	memcpy(ptr, text, length);			// 追加するテキストをコピーします

	// もとのメモリを解放して、新しいメモリをポイントします。
	Empty();
	m_text = (char*)data;

	return *this;
}
▲ページ先頭へ

【実装】 比較演算(==、!=、<、>)

投稿 October 12, 2018

CString::Compare 関数と同じイメージです。 戻り値は int 値ではなく、true または false です。

if (str == "option1"){
// オプション1の処理
}

のように比較できます。
CString::CompareNoCase 関数とは異なり、アルファベットの大文字・小文字も区別されます。

bool CmxString::operator == (const char* text) const
{

	// 自身に文字列が設定されていないときは、一致にはなりません。
	if (!m_text) {
		return false;
	}

	// 引数を検査しておきます。
	if (!text) {
		return false;
	}

	// サイズが異なれば、一致にはなりません。
	size_t size1 = strlen(m_text);
	size_t size2 = strlen(text);
	if (size1 != size2) {
		return false;
	}

	// 1文字づつ比較します。
	for (size_t i = 0; i < size1; i++) {
		if (m_text[i] != text[i]) {
			return false;
		}
	}

	// すべての文字が一致すれば、一致と判断します。
	return true;
}
▲ページ先頭へ
line
関連トピックス
line

C/C++ によるログ出力

C/C++ でファイルにログを出力する方法を検討しています。

C/C++ による数値のフォーマット

C/C++ で数値3桁ごとにカンマを入れる方法を検討しています。

C/C++ による現在日時の取得

C/C++ で現在時刻を取得する方法を検討しています。

C/C++ による経過時間の検査

C/C++ で、ある時点からの経過時間を計測する方法について検討しています。

リンクリストでファイルを列挙

開発環境は Windows ですが、双方向線形リンクリストを使えば開発が楽になるケースがあります。 ここでは例として、指定フォルダ内にある全サブフォルダとファイルを列挙できるコードを扱っています。

line
その他のおすすめ
line

Android 開発に関する記事をまとめた Android 開発トップ もご覧ください。

JavaScriptが無効です
▲ページ先頭へ


© 2017-2022 StraightApps.com 無断転載を禁じます。No reproduction without permission.