C言語問題 その3

  目次



その1     その2     その3

応用の1





  (1) 記憶クラスとマクロ



グローバル変数を別々のソースで共有するには、一つだけ記憶クラスを省略した
定義を行い、それ以外では extern 記憶クラスを記述します

以下の二つのソースで 変数 int myData を共有する為に、common.h を使用
して記述して下さい

common.h
  
MY_EXTERN int nData;
  

main.cpp
  
#include <stdio.h>

void Add( );

int main()
{
	nData = 10;
	Add( );
	printf( "%d\n", nData );

	return 0;
}
  

sub.cpp
  
void Add( )
{
	nData++;
}
  



  (2) 条件コンパイル

C++ では条件コンパイルは通常、同じヘッダーファイルが複数回インクルードされる
のを防ぐために使います

問題 (1) では main.cpp に common.h を二回インクルードするとエラーになります
エラーとならない為の記述を行なって下さい
#if !defined( マクロキーワード )
#endif

という記述が使用できます



  (3) 関数より文字列を取得時にバッファを動的に確保

  
Win32 API の GetSystemDirectory 関数は、Windows のシステムディレクトリを取得する関数です。

関数の定義は以下のようになります
UINT GetSystemDirectory(
	LPTSTR lpBuffer,
	UINT uSize
);

lpBuffer は十分な領域を用意する必要があり、そのサイズを uSize として渡す
必要があります。Win32 API 関数としては典型的な作りになっています。

また、もし lpBuffer のサイズが足らない場合は、戻り値として実際に必要な
サイズが返されます。成功した場合は書き込まれたサイズが返されます。

但し、サイズが足らない場合は lpBuffer の内容は変化しませんので裏を
返せば uSize に 0 を指定すると必要なサイズが返されます。

メモリを動的に必要なサイズより多く確保してシステムディレクトリを表示して下さい
  

  
#include <windows.h>
#include <stdio.h>

int main()
{
	UINT nSize;

	nSize = GetSystemDirectory( NULL, 0 );

	// ここにコードを記述

	return 0;
}
  



  (4) 同名関数の作成

  
問題 (3) のバッファ確保部分を Win32 APIの 同名の関数として作成して下さい
  

  
#include <windows.h>
#include <stdio.h>

LPTSTR GetSystemDirectory( void );

int main()
{
	LPTSTR lpBuff = GetSystemDirectory();

	printf( "%s\n", lpBuff );

	GlobalFree( lpBuff );

	return 0;
}

LPTSTR GetSystemDirectory( void )
{
	// ここにコードを記述
}
  



  (5) メモリ動的確保に伴うクラスの利用

  
メモリを動的確保すると、必ずどこかで解放する必要があります。
メモリに限らず、Windows API ではそのような場面にしょっちゅう遭遇するので、
プログラマがそのような「解放忘れ」をしないように「クラス」を利用します

以下は、問題 (4) をクラス化したものです。完成させて、さらに、GetWindowsDirectory を追加実装して下さい
  

  
#include <windows.h>
#include <stdio.h>

class MyClass {
	public:
		LPTSTR lpBuff;
		LPTSTR GetSystemDirectory( void );
		MyClass()
		{
			// インスタンスの初期処理
			lpBuff = NULL;
		}
		virtual ~MyClass()
		{
			// インスタンスの終了処理
			if ( lpBuff != NULL ) {
				GlobalFree( lpBuff );
			}
		}
};
LPTSTR MyClass::GetSystemDirectory( void )
{
	// ここにコードを記述
}

int main()
{
	MyClass MyInstance;

	MyInstance.GetSystemDirectory();

	printf( "%s\n", MyInstance.lpBuff );

	return 0;
}
  



  (6) クラスのコピー

MyClass MyInstance,MyInstance2;

で、MyInstance2 = MyInstance; は、単純にメモリのコピーになります。
しかし、MyClass 内ではメモリの動的確保になっている為、片方のインスタンスが消滅すると
もう片方でのメモリの解放が失敗します。

これは、バッファは1つしか無い為で、複写されたのはバッファのアドレスです。

このような問題を回避する為に = 演算子の動作を変更する事ができます。
= 演算子の動作として新しいメモリを確保して下さい

  
#include <windows.h>
#include <stdio.h>

class MyClass {
	public:
		LPTSTR lpBuff;
		LPTSTR GetSystemDirectory( void );
		LPTSTR GetWindowsDirectory( void );
		operator = ( MyClass &MyInstance );
		MyClass()
		{
			// インスタンスの初期処理
			lpBuff = NULL;
		}
		virtual ~MyClass()
		{
			// インスタンスの終了処理
			if ( lpBuff != NULL ) {
				GlobalFree( lpBuff );
			}
		}
};
// = 演算子の動作 (デフォルト動作のオーバーロード)
MyClass::operator = ( MyClass &MyInstance )
{
	// ここにコードを記述
}
LPTSTR MyClass::GetSystemDirectory( void )
{

}
LPTSTR MyClass::GetWindowsDirectory( void )
{

}

int main()
{
	MyClass MyInstance,MyInstance2;

	MyInstance.GetSystemDirectory();

	printf( "%s\n", MyInstance.lpBuff );

	MyInstance2 = MyInstance;
	// この代入は書き換えると以下のようになります
	// MyInstance2.operator = (MyInstance);

	printf( "%s\n", MyInstance2.lpBuff );

	return 0;
}
  



  (7) キャスト演算子のオーバーロード

  
( char * ) というキャストの動作も変更する事がてきるので、以下のような記述が可能になります

これをふまえて、( int ) というキャストした場合に文字列の長さを返すようにして下さい
  

  
#include <windows.h>
#include <stdio.h>

class MyClass {
	public:
		LPTSTR lpBuff;
		LPTSTR GetSystemDirectory( void );
		LPTSTR GetWindowsDirectory( void );
		operator = ( MyClass &MyInstance );
		operator char* ();
		MyClass()
		{
			// インスタンスの初期処理
			lpBuff = NULL;
		}
		virtual ~MyClass()
		{
			// インスタンスの終了処理
			if ( lpBuff != NULL ) {
				GlobalFree( lpBuff );
			}
		}
};
MyClass::operator char* ()
{
	return lpBuff;
}

// 他のメンバ関数の定義を省略

int main()
{
	MyClass MyInstance,MyInstance2;

	MyInstance.GetSystemDirectory();

	printf( "%s\n", (LPTSTR)MyInstance );

	MyInstance2 = MyInstance;
	MyInstance2.operator = (MyInstance);

	printf( "%s\n", (LPTSTR)MyInstance2 );

	return 0;
}
  










  infoboard   管理者用   
このエントリーをはてなブックマークに追加





フリーフォントWEBサービス
SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ