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;
}
  




yahoo  google  MSDN  MSDN(us)  WinFAQ  Win Howto  tohoho  ie_DHTML  vector  wdic  辞書  天気 


[PROc]
claudebot
24/03/30 00:56:14
InfoBoard Version 1.00 : Language=Perl

1 BatchHelper COMprog CommonSpec Cprog CprogBase CprogSAMPLE CprogSTD CprogSTD2 CprogWinsock Cygwin GameScript HTML HTMLcss InstallShield InstallShieldFunc JScript JScriptSAMPLE Jsfuncs LLINK OldProg OracleGold OracleSilver PRO PRObrowser PROc PROconePOINT PROcontrol PROftpclient PROjscript PROmailer PROperl PROperlCHAT PROphp PROphpLesson PROphpLesson2 PROphpLesson3 PROphpfunction PROphpfunctionArray PROphpfunctionMisc PROphpfunctionString PROsql PROvb PROvbFunction PROvbString PROvbdbmtn PROvbonepoint PROwebapp PROwin1POINT PROwinSYSTEM PROwinYOROZU PROwindows ProjectBoard RealPHP ScriptAPP ScriptMaster VBRealtime Vsfuncs a1root access accreq adsi ajax amazon argus asp aspSample aspVarious aspdotnet aw2kinst cappvariety centura ckeyword classStyle cmaterial cmbin cmdbapp cmenum cmlang cmlistbox cmstd cmstdseed cmtxt cs daz3d db dbCommon dbaccess dnettool dos download flex2 flex3 flex4 framemtn framereq freeWorld freesoft gimp ginpro giodownload google hdml home hta htmlDom ie9svg install java javaSwing javascript jetsql jquery jsp jspTest jspVarious lightbox listasp listmsapi listmsie listmsiis listmsnt listmspatch listmsscript listmsvb listmsvc memo ms msde mysql netbeans oraPlsql oracle oracleWiper oraclehelper orafunc other panoramio pear perl personal pgdojo pgdojo_cal pgdojo_holiday pgdojo_idx pgdojo_ref pgdojo_req php phpVarious phpguide plsql postgres ps r205 realC realwebapp regex rgaki ruby rule sboard sc scprint scquest sdb sdbquest seesaa setup sh_Imagick sh_canvas sh_dotnet sh_google sh_tool sh_web shadowbox shgm shjquery shvbs shweb sjscript skadai skywalker smalltech sperl sqlq src systemdoc tcpip tegaki three toolbox twitter typeface usb useXML vb vbdb vbsfunc vbsguide vbsrc vpc wcsignup webanymind webappgen webclass webparts webtool webwsh win8 winofsql wmi work wp youtube