Announce

PukiWiki contents have been moved into SONOTS Plugin (20070703)

cpp

C++のTips

Table of Contents

int isdigit(int c)

bool isdigit(文字) の引数は 0 ~ 255 (unsigned char) と -1 (EOF)。

  • 1 も受け取れるように unsigned char ではなく int が引数となっている。

char と unsigned char の違い

unsigned char uc = 255;
char c = uc; // char は -128 - 127
printf("%d %d\n", uc, c); // 255 -1 (どちらも 0xff には違いない)
printf("%c %c\n", uc, c); // なんという字かはわからないが同じもの

16進数として同じなら、unsinged でも singed でも同じ文字を意味する。

fatal_error

/*
fatal_error() prints the error message contained in format then exits with
exit code 1.
*/
void fatal_error(char* format, ...)
{
    va_list ap;  // format argument list

    fprintf( stderr, "Error: ");

    // assemble argument list and print format using it
    va_start( ap, format );
    vfprintf( stderr, format, ap );
    va_end(ap);

    fprintf( stderr, "\n");
    exit(1);
}

MIN/MAX/ABS

#ifndef MIN
#define MIN(x,y) ( ( x < y )? x : y )
#endif
#ifndef MAX
#define MAX(x,y) ( ( x > y )? x : y )
#endif
#ifndef ABS
#define ABS(x) ( ( x < 0 )? -x : x )
#endif

std::min だったり、そもそもなかったり。 abs は fabs だったりするため。

M_PI

#define _USE_MATH_DEFINES
#include <math.h>

FLT_MAX/DBL_MAX

#include <float.h>

INT_MAX

#include <limits.h>

ファイル一覧

Windows

_findfirst(*.txt), _findnext

linux

glob(*.txt)

#ifdef platform

#if defined(_WIN32) || defined(_WIN64)
#elif
#else
#endif
    *  メモ
          o プリプロセッサは、未定義の識別子を0として扱う。
          o 従って、#if __GNUC__ >= 3はGCC3以上として使えるが、GCC2系かどうかを#if __GNUC__ < 3で判定しようとすると、GCCでないものも含まれるので注意が必要。

    * コンパイラ
          o GCCかどうか
            #ifdef __GNUC__
                + #if __GNUC__ >= 3 // GCC3.0以上
          o Visual C++かどうか
            #ifdef _MSC_VER(VC++以外でも定義されている場合あり)
                + #if _MSC_VER >=1000 // VC++4.0以降
                + #if _MSC_VER >=1100 // VC++5.0以降
                + #if _MSC_VER >=1200 // VC++6.0以降
                + #if _MSC_VER >=1300 // VC2003以降
                + #if _MSC_VER >=1400 // VC2005以降
          o Borland C++かどうか
            #ifdef __BORLANDC__
    * UNIX
          o UNIXかどうか
            #ifdef __unix
            or
            #ifdef __unix__
          o Linuxかどうか
            #ifdef __linux
            or
            #ifdef __linux__
          o FreeBSDかどうか
            #ifdef __FreeBSD__
          o NetBSDかどうか
            #ifdef __NetBSD__
    * Windows
          o 32bitかどうか
            #ifdef _WIN32(これはよく使う、WIN32でもよい)
          o 64bitかどうか
            #ifdef _WIN64
          o GUIアプリかどうか
            #ifdef _WINDOWS
          o CUIアプリかどうか
            #ifdef _CONSOLE
          o Windowsのバージョン … WINVER
            ※ PC向けWindows(95/98/Me/NT/2000/XP/Vista)とWindows CEの両方で定義される
                + #if (WINVER >= 0x030a) // Windows 3.1以降
                + #if (WINVER >= 0x0400) // Windows 95/NT4.0以降
                + #if (WINVER >= 0x0410) // Windows 98以降
                + #if (WINVER >= 0x0500) // Windows Me/2000以降
                + #if (WINVER >= 0x0501) // Windows XP以降
                + #if (WINVER >= 0x0600) // Windows Vista以降
          o Windows 95/98/Meのバージョン … _WIN32_WINDOWS
                + MFCアプリケーションで、PC向けWindowsかどうか(Windows CEでは定義されないため)
                  #ifdef _WIN32_WINDOWS
                + #if (_WIN32_WINDOWS >= 0x0400) // Windows 95以降
                + #if (_WIN32_WINDOWS >= 0x0410) // Windows 98以降
                + #if (_WIN32_WINDOWS >= 0x0500) // Windows Me以降
          o Windows NTのバージョン … _WIN32_WINNT
                + #if (_WIN32_WINNT >= 0x0500) // Windows 2000以降
                + #if (_WIN32_WINNT >= 0x0501) // Windows XP以降
                + #if (_WIN32_WINNT >= 0x0600) // Windows Vista以降
          o Windows CE(PocketPC)かどうか
            #ifdef _WIN32_WCE
          o Windows CEのバージョン … WINCEOSVER
          o Windows CEなら以下実行
            WCE_IF(CEのとき, 非CEのとき)
          o Internet Explorerのバージョン … _WIN32_IE
    * Cygwin
          o Cygwinかどうか
            #ifdef __CYGWIN__
          o 32bit版Cygwinかどうか(64bit版はまだないが)
            #ifdef __CYGWIN32__
          o MinGW(-mno-cygwin指定)かどうか
            #ifdef __MINGW32__

reference

class 定義時のカンマを忘れるな

class Test{
};

コンストラクタの再利用はできない。

class Test{
public:
   int num;
   Test(int i){
      num=i;
   }
   Test(){
      Test(10);
      //ここで結局値がなくなる。
   }
};

可変引数

#include <stdio.h>
#include <stdarg.h>

int sprintf(char *s, const char *format, ...)
{
 va_list ap;
 int result;

 va_start(ap, format);
 result = vsprintf(s, format, ap);
 va_end(ap);
 return result;
}

可変長引数の仮引数は格上げされてしまう。

int arg = va_arg(ap, int);
char, short --> int
float       --> double 

format を解析して、次は double のはずだ、と va_arg(ap, double) にしたり、 %s なら、\0 まで読み込んで文字列にしたりする?いや、 char* が渡されるのかな? va_arg(ap, char*);

つまり、va_arg(ap, string) とかはできないのか?&string で渡してやれば string* で受け取ったりできないのかな?

http://program.station.ez-net.jp/special/vc/basic/function/stdarg.asp

Simple Sudo

Infinite length of arguments, chmod +s

Compile this as root user. Then,

chmod +s a.out

as root user. All users can execute any commands with root privilege as

./a.out rm -rf /
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
 char *com;
 int size = 1024;
 int i;
 com = malloc(size);
 for(i = 1; i < argc; i++) {
   if(strlen(com) + strlen(argv[i]) > size) {
     size *= 2;
     com = realloc(com, size);
   }
   strcat(com, "\"");
   strcat(com, argv[i]);
   strcat(com, "\"");
   strcat(com, " ");
 }
 //real user id, getuid() -> real user
 //effective user id, geteuid() -> s-bit user
 setreuid(geteuid(),geteuid()); 
 setregid(getegid(),getegid()); 
 //execvp(argv[1],&argv[2]); // if argc == 1,,,,
 system(com);
 free(com);
 return(1);
}

Network

client on windows

/////////////////////////////////////////////////////////////////////////////
// client.cpp
// client side program on Windows
//
// Naotoshi Seo masc0990, Sep 21 2005
// Last modified: Sep 22 2005
//
// This program is a practice for implementation of client side program 
// on Windows. This client requests two integers input for user and
// sends message to server and receives the addition of those two from server.
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdlib.h>
#include <stdio.h> 
#include <iostream.h>
#include <time.h>
#include <winsock.h>
//#define DEST_IP "127.0.0.1"	// Loopback connection to the local machine
#define DEST_IP "130.191.3.100" // rohan.sdsu.edu
#define PORT 9990				// Port number
#define NO_FLAGS_SET 0			// No flag for send and recv function

int main()
{
	int m;

	//Initialize the dll for socket API
	WSADATA wdata;
	int wstatus = WSAStartup(MAKEWORD(1,1), &wdata);
	if (wstatus != 0) // error occurs
	{
		cout << "Client failed to initialize winsock." << endl;
		exit(1);
	}
	else
	{
		cout << "Client successfully initialized winsock." << endl;
	}

	SOCKADDR_IN ca;								// Client socket address structure
	ca.sin_family = AF_INET;					// TCP Protocol
	ca.sin_port = htons(PORT);					// Supply the port number
	ca.sin_addr.s_addr = inet_addr(DEST_IP);	// Destination IP address
	
	SOCKET cs = socket(		// Create socket
		AF_INET,			// Internet address family (
		SOCK_STREAM,		// Connection-oriented (stream) socket type
							// which uses TCP packets (reliable, duplex)
							// Can also be: SOCK_DGRAM - uses UDP packets
		0);					// Protocol (0 - system picks approp. protocol
							// Returns client's socket descriptor (cs)

	if(cs == INVALID_SOCKET)	// error
	{
		cout << "Client failed to create a socket. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else
	{
		cout << "Client successfully created a socket. " << endl;
	}
	
	m = connect(			// Request connection with the server
		cs,					// Client's socket (returned by socket())
		(LPSOCKADDR)&ca,	// Pointer to the server's socket address str.
		sizeof(ca));		// Length of the address structure
							// Returns 0 (no error) or SOCKET_ERROR

	if (m == SOCKET_ERROR)	// error
	{
		cout << "Client failed to connect." << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	} 
	else if (m == 0)
	{
		cout << "Client successfully connected with server, " << DEST_IP << ":" << PORT << endl;
	}

	int in1, in2;
	char input[256];
	char tmp[256];
	char msg[256];
	while(1)
	{
		cout << "Please enter two integers" << endl;
		gets(input); // retrive inputs from user
		cout << "[Input] " << input << endl;

		if (sscanf(input, "%d %d%s", &in1, &in2, tmp) == 2)
		// Two valid numbers are entered
		// Memo: Thanks to last tmp, it can reject e.g. 5 5.6, 4 5 6 also. 
		{
			// construct message
			sprintf(msg, "Please add the follwing two numbers for me: %d and %d",in1,in2);

			m = send(cs, msg, strlen(msg)+1, NO_FLAGS_SET); // Send message to server
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Client failed to send message. " << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Client successfully sent message. " << endl;
				cout << "[Sent] " << msg << endl;
			}
			
			m = recv(cs, msg, sizeof(msg), NO_FLAGS_SET);	// Wait message from server
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Client failed to receive message. " << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}			
			else
			{
				cout << "Client successfully received message. " << endl;
				cout << "[Received] " << msg << endl;
			}
		} 
		else 
		{ // Invalid numbers // Terminate the loop
			strcpy(msg,input);
		
			send(cs, msg, strlen(msg)+1, NO_FLAGS_SET); // Send message to server
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Client failed to send message for termination. " << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Client successfully sent message. " << endl;
				cout << "[Sent] " << msg << endl;
			}

			recv(cs, msg, sizeof(msg), NO_FLAGS_SET);	// Wait message from server
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Client failed to receive message for termination. " << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Client successfully received message. " << endl;
				cout << "[Received] " << msg << endl;
			}
			break;					// Terminate the loop
		}	
	}

	m = closesocket(cs);	// Release the socket descriptor cs
							// and delete all underlying structures
							// (address info, queue and queued requests
							// if any.)
							// Returns 0 (success) or SOCKET_ERROR

	if (m == SOCKET_ERROR)
	{
		cout << "Client failed to close connection. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else if (m == 0)
	{
		cout << "Client successfully closed connection." << endl;
	}

	wstatus = WSACleanup();	// Cleanup socket API
	if (wstatus != 0)
	{
		cout << "Client failed to cleanup winsock. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else
	{
		cout << "Client successfully cleaned winsock up." << endl;
	}
	return 0;
}

server on windows

///////////////////////////////////////////////////////////////////////////
// server.cpp
// Multi threading server on Windows
//
// Naotoshi Seo masc0990, Sep 21 2005
// Last modified: Sep 22 2005
//
// This program is a practice for implementation of server side program 
// on Windows. This has multi threading function. This server receives two
// integers from a client and sends addition of those two to the client. 
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include <time.h>
#include <winsock.h>
#include <string.h>
#define PORT 9990			// Port number
#define NO_FLAGS_SET 0		// No flag for send and recv function
#define MAX_CONNECTION 100

// Server creates this thread to serve a client
// return: nothing
// parameter: pointer of socket descripter. 
void ClientThread(void *csock)
{
	int m;
	char msg[256];
	char msg_template[] = "Please add the follwing two numbers for me: ";
	char tmp[256];
	int in1, in2;
	SOCKET* cs = (SOCKET*)csock;
	while(1) // Infinite loop
	{
		m = recv(*cs, msg, sizeof(msg), NO_FLAGS_SET); // Wait for a message from the client
		if (m == SOCKET_ERROR) // error occurs
		{ 
			cout << "Server failed to receive message. Client ID: " << *cs << endl;
			cout << "Error code: " << WSAGetLastError() << endl;
			break;
		} 
		else
		{
			cout << "Server successfully received message. Client ID: " << *cs << endl;
			cout << "[Received] " << msg << endl;
		}

		// Extract numbers from message
		if(strncmp(msg, msg_template, sizeof(msg_template)-1) == 0 &&
			sscanf(&msg[sizeof(msg_template)-1], "%d%s%d%s" ,&in1, tmp, &in2, tmp) == 3)
		{
			// the numbers are valid integers
			sprintf(msg, "The sum of your numbers is: %d", in1 + in2);
			m = send(*cs, msg, strlen(msg)+1, NO_FLAGS_SET); // Send message to the client
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Server failed to send message. Client ID: " << *cs << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Server successfully sent message. Client ID: " << *cs << endl;
				cout << "[Sent] " << msg << endl;
			}
		}
		else // Invalid numbers
		{
			strcpy(msg, "We appreciated the business with you, bye\0");
			m = send(*cs, msg, strlen(msg)+1, NO_FLAGS_SET); // Send message to the client
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Server failed to send termination message. Client ID: " << *cs << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Server successfully sent message. Client ID: " << *cs << endl;
				cout << "[Sent] " << msg << endl;
			}
			break; // Terminate the loop
		}
	}
	m = closesocket(*cs);	// Release the socket descriptor cs
							// and delete all underlying structures
							// (address info, queue and queued requests
							// if any.)
							// Returns 0 or SOCKET_ERROR

	if (m == SOCKET_ERROR)
	{
		cout << "Server failed to close connection. Client ID: " << *cs << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else if (m == 0)
	{
		cout << "Server successfully closed connection. Client ID: " << *cs << endl;
	}
} // End of client therad

int main() // The primary thread of the server
{
	int m;
	//Initialize the dll for socket API
	WSADATA wdata;
	int wstatus = WSAStartup(MAKEWORD(1,1), &wdata);
	if (wstatus != 0) {
		cout << "Failed to initialize winsock. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}

	SOCKET s = socket(	// Create socket
		AF_INET,		// Internet address family
		SOCK_STREAM,	// Connection-oriented (stream) socket type
						// which uses TCP packets (reliable, duplex)
						// Can also be: SOCK_DGRAM - uses UDP packets
						// (see chapter 10)
		0);				// Protocol (0 - system picks approp. protocol
						// Returns socket descriptor (s)

	if(s == INVALID_SOCKET)
	{
		cout << "Server failed to create a socket. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else
	{
		cout << "Server successfully created a socket. " << endl;
	}

	SOCKADDR_IN sa;				// Server socket address structure
	sa.sin_family = AF_INET;	// TCP Protocol
	sa.sin_port = htons(PORT);	// Supply the port number
	sa.sin_addr.s_addr = htonl(INADDR_ANY);

	m = bind(				// Associate the local address with the socket
		s,				// Socket descriptor (returned by socket())
		(LPSOCKADDR)&sa,	// Pointer to the socket address structure
		sizeof(sa));	// Length of the address structure

	if (m == SOCKET_ERROR)
	{
		cout << "Server failed to bind. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else if (m == 0)
	{
		cout << "Server successfully binded." << endl;
	}

	m = listen(			// Allow socket to take connections
		s,				// Socket descriptor (returned by socket())
		MAX_CONNECTION);// Maximal number of requests allowed
	
	if (m == SOCKET_ERROR)
	{
		cout << "Server failed to listen connection. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else if (m == 0)
	{
		cout << "Server is listening connection." << endl;
	}

	SOCKET cs[MAX_CONNECTION];
	HANDLE hThread[MAX_CONNECTION];
	DWORD dwID[MAX_CONNECTION];
	int i;
	for(i = 0; i < MAX_CONNECTION; i++) // Connection request loop
	{
		int length = sizeof(sa);
		cs[i] = accept(		// Accept a connection from a client
			s,				// Socket descriptor (returned by socket())
							// (s identifies the socket which listens
							// and accepts connection requests)
			(LPSOCKADDR)&sa,// Socket address structure received from
							// connecting entity (client)
			&length);		// Length of sa
							// Returns new socket descriptor (ns)
		
		if(cs[i] == INVALID_SOCKET)
		{
			cout << "Server failed to accept connection. " << endl;
			cout << "Error code: " << WSAGetLastError() << endl;
			break;
		}
		else
		{
			cout << "Server successfully accepted connection. Client ID: " << cs[i] << endl;
		}

		// Create Thread
		hThread[i] = CreateThread(
			NULL,			// Pointer to a SECURITY_ATTRIBUTES structure 
							// that determines whether the returned handle 
							// can be inherited by child processes. 
							// If lpThreadAttributes is NULL, 
							// the handle cannot be inherited.
			0,				// Initial size of the stack, in bytes.
			(LPTHREAD_START_ROUTINE)ClientThread,	
							// Pointer to the application-defined 
							//function to be executed by the thread
			&cs[i],			// Pointer to a variable to be passed to the thread.
			0,				// Flags that control the creation of the thread. 
							// If the CREATE_SUSPENDED flag is specified, 
							// the thread is created in a suspended state, 
							// and will not run until the ResumeThread 
							// function is called. If this value is zero, 
							// the thread runs immediately after creation.
			&dwID[i]);		// Pointer to a variable that receives the 
							// thread identifier. 

		if (hThread == NULL)
		{
			cout << "Server failed to create a thread. " << endl;
			cout << "Error code: " << GetLastError() << endl;
			break;
		}
		else
		{
			cout << "Server successfully created a thread. Thread ID: " << dwID[i] << endl;
		}
	}

	// Release thread objects (close handles)
	for(int j = 0; j < i; j++)
	{
		m = CloseHandle(hThread[j]);
		if(m == 0)
		{
			cout << "Server failed to release a thread. Thread ID: " << dwID[j] << endl;
			cout << "Error code: " << GetLastError() << endl;
		}
		else
		{
			cout << "Server successfully released a thread. Thread ID: " << dwID[j] << endl;
		}
	}

	m = closesocket(s);		// Release the socket descriptor s
							// and delete all underlying structures
							// (address info, queue and queued requests
							// if any.)
							// Returns 0 or SOCKET_ERROR

	if (m == SOCKET_ERROR)
	{
		cout << "Server failed to close server socket. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else if (m == 0)
	{
		cout << "Server successfully closed server socket." << endl;
	}

	wstatus = WSACleanup();	// Cleanup socket API
	if (wstatus != 0)
	{
		cout << "Server failed to cleanup winsock. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else
	{
		cout << "Server successfully cleaned winsock up." << endl;
	}
	return 0;

}// End of server

server on UNIX

////////////////////////////////////////////////////////////////////////////
// posix_server.c
// Multi threading server on Solaris
//
// Naotoshi Seo masc0990, Sep 22 2005
// Last modified: Sep 22 2005
//
// This program is a practice for implementation of server side program 
// on Solaris. This has multi threading function. This server receives two
// integers from a client and sends addition of those two to the client. 
//
// Memo: I checked each API error,  
// not only check if the API returns nonnegative value. 
// I printed out 'errno' which will be stored error code also. 
/////////////////////////////////////////////////////////////////////////////
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stddef.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream.h>
#include <pthread.h>
#include <thread.h>
#define PORT 9990		// Port number
#define NO_FLAGS_SET 0		// No flag for send and recv function
#define MAX_CONNECTION 100
// Cushion to abosorb difference with winsock
#include <errno.h>
#define WSAGetLastError() errno
#define SOCKET int
#define LPSOCKADDR  struct sockaddr *
#define SOCKADDR  struct sockaddr
#define SOCKADDR_IN sockaddr_in
#define SOCKET_ERROR -1
#define closesocket close
#define INVALID_SOCKET -1

// Server creates this thread to serve a client
// return: 0
// parameter: pointer of socket descripter. 
extern "C" void * ClientThread(void *csock)
{
	int m;
	char msg[256];
	char msg_template[] = "Please add the follwing two numbers for me: ";
	char tmp[256];
	int in1, in2;
	SOCKET* cs = (SOCKET*)csock;
	while(1) // Infinite loop
	{
		m = recv(*cs, msg, sizeof(msg), NO_FLAGS_SET); // Wait for a message from the client
		if (m == SOCKET_ERROR) // error occurs
		{ 
			cout << "Server failed to receive message. Client ID: " << *cs << endl;
			cout << "Error code: " << WSAGetLastError() << endl;
			break;
		} 
		else
		{
			cout << "Server successfully received message. Client ID: " << *cs << endl;
			cout << "[Received] " << msg << endl;
		}

		// Extract numbers from message
		if(strncmp(msg, msg_template, sizeof(msg_template)-1) == 0 &&
			sscanf(&msg[sizeof(msg_template)-1], "%d%s%d%s" ,&in1, tmp, &in2, tmp) == 3)
		{
			// the numbers are valid integers
			sprintf(msg, "The sum of your numbers is: %d", in1 + in2);
			m = send(*cs, msg, strlen(msg)+1, NO_FLAGS_SET); // Send message to the client
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Server failed to send message. Client ID: " << *cs << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Server successfully sent message. Client ID: " << *cs << endl;
				cout << "[Sent] " << msg << endl;
			}
		}
		else // Invalid numbers
		{
			strcpy(msg, "We appreciated the business with you, bye\0");
			m = send(*cs, msg, strlen(msg)+1, NO_FLAGS_SET); // Send message to the client
			if (m == SOCKET_ERROR) // error occurs
			{ 
				cout << "Server failed to send termination message. Client ID: " << *cs << endl;
				cout << "Error code: " << WSAGetLastError() << endl;
				break;
			}
			else
			{
				cout << "Server successfully sent message. Client ID: " << *cs << endl;
				cout << "[Sent] " << msg << endl;
			}
			break; // Terminate the loop
		}
	}
	m = closesocket(*cs);	// Release the socket descriptor cs
							// and delete all underlying structures
							// (address info, queue and queued requests
							// if any.)
							// Returns 0 or SOCKET_ERROR

	if (m == SOCKET_ERROR)
	{
		cout << "Server failed to close connection. Client ID: " << *cs << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		pthread_exit((void *)1);
	}
	else if (m == 0)
	{
		cout << "Server successfully closed connection. Client ID: " << *cs << endl;
	}
	return 0;
	//Memo: return retval equals to pthread_exit((void *)retval)
	//Memo: automatically handlers are closed after exit
} // End of client therad

int main() // The primary thread of the server
{
	int m = 0;
	SOCKET s = socket(	// Create socket
		AF_INET,		// Internet address family
		SOCK_STREAM,	// Connection-oriented (stream) socket type
						// which uses TCP packets (reliable, duplex)
						// Can also be: SOCK_DGRAM - uses UDP packets
						// (see chapter 10)
		0);				// Protocol (0 - system picks approp. protocol
						// Returns socket descriptor (s)

	if(s == INVALID_SOCKET)
	{
		cout << "Server failed to create a socket. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	}
	else
	{
		cout << "Server successfully created a socket. " << endl;
	}

	SOCKADDR_IN sa;				// Server socket address structure
	sa.sin_family = AF_INET;	// TCP Protocol
	sa.sin_port = htons(PORT);	// Supply the port number
	sa.sin_addr.s_addr = htonl(INADDR_ANY);

	m = bind(				// Associate the local address with the socket
		s,					// Socket descriptor (returned by socket())
		(LPSOCKADDR)&sa,	// Pointer to the socket address structure
		sizeof(sa));		// Length of the address structure

	if (m == SOCKET_ERROR) {
		cout << "Server failed to bind. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	} else if (m == 0) {
		cout << "Server successfully binded." << endl;
	}

	m = listen(			// Allow socket to take connections
		s,				// Socket descriptor (returned by socket())
		MAX_CONNECTION);// Maximal number of requests allowed
	
	if (m == SOCKET_ERROR) {
		cout << "Server failed to listen connection. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	} else if (m == 0) {
		cout << "Server is listening connection." << endl;
	}

	SOCKET cs[MAX_CONNECTION];
	pthread_t thread[MAX_CONNECTION];
	for(int i = 0; i < MAX_CONNECTION; i++) // Connection request loop
	{
		int length = sizeof(sa);
		cs[i] = accept(		// Accept a connection from a client
			s,				// Socket descriptor (returned by socket())
							// (s identifies the socket which listens
							// and accepts connection requests)
			(LPSOCKADDR)&sa,// Socket address structure received from
							// connecting entity (client)
			&length);		// Length of sa
							// Returns new socket descriptor (ns)
		
		if(cs[i] == INVALID_SOCKET)
		{
			cout << "Server failed to accept connection. " << endl;
			cout << "Error code: " << WSAGetLastError() << endl;
			break;
		}
		else
		{
			cout << "Server successfully accepted connection. Client ID: " << cs[i] << endl;
		}

		// Create Thread
	        m = pthread_create(
			&thread[i],		// thread id will be stored
			NULL,			// Thread's attributes. 
							// If attr is NULL, the default attributes are used.
			ClientThread,	// Pointer to the application-defined 
							// function to be executed by the thread
			&cs[i]			// Pointer to a variable to be passed to the thread.
		);

		if(m == 0)
		{
			cout << "Server successfully created a thread. Thread ID: " << thread[i] << endl;
		}
		else
		{
			cout << "Server failed to create a thread. " << endl;
			cout << "Error code: " << m << endl;
			break;
		}
	}
	
	m = closesocket(s);		// Release the socket descriptor s
							// and delete all underlying structures
							// (address info, queue and queued requests
							// if any.)
							// Returns 0 or SOCKET_ERROR

	if (m == SOCKET_ERROR) {
		cout << "Server failed to close server socket. " << endl;
		cout << "Error code: " << WSAGetLastError() << endl;
		exit(1);
	} else if (m == 0) {
		cout << "Server successfully closed server socket. " << endl;
	}

	return 0;
}// End of server

compile

cl -o server server.cpp -link wsock32.lib
CC -mt -o pserver posix_server.c -lpthread -lsocket -lxnet

MyLib

getopt

./getopt

ltrim/rtrim

char *ltrim(char *str) {
	char *start = str;

	while ((*start == ' ') || (*start == '\n'))
		start++;

	memmove(str, start, strlen(start) + 1);

	return str;
}

char *rtrim(char *str) {
	char *end = str;

	while (*end)
		end++;

	end--;

	while ((end >= str) && ((*end == ' ') || (*end == '\n')))
		end--;

	end[1] = '\0';

	return str;
}

String *ltrimString(String *str) {
	int i = 0;

	while ((i < str->length) && (str->string[i] == ' '))
		i++;

	if (i == 0)	/* nothing to trim */
		return str;

	str->length -= i;
	memmove(str->string, &str->string[i], str->length + 1);
	/* str->string = realloc(str->string, str->length); */

	return str;
}

String *rtrimString(String *str) {
	int i = str->length - 1;

	while ((i >= 0) && (str->string[i] == ' '))
		i--;

	if (i == str->length - 1)	/* nothing to trim */
		return str;

	str->length = i + 1;
	str->string[i + 1] = '\0';
	/* str->string = realloc(str->string, i + 1); */

	return str;
}

basename/dirname

basename, dirname exists on unix. avoid these name. we can use them as

#if defined(_WIN32) || defined(_WIN64)
   // create by own
#else
    return dirname(filename);
#end

maybe, win does not have similar funcs.

#include <string.h>
char* get_basename(char* filename)
{
    char* basename;
#if defined(_WIN32) || defined(_WIN64)
    basename = strrchr(filename, '\\');
#else
    basename = strrchr(filename, '/');
#endif
    if (basename) {
        basename = basename + 1;
    } else {
        basename = filename;
    }
    return basename;
}
#Include <stdlib.h>
#include <string.h>
char* get_dirname(char *filename)
{
    char *dirname = NULL;
    char *pch;
    int pos;
#if defined(_WIN32) || defined(_WIN64)
    pch = strrchr(filename, '\\');
#else
    pch = strrchr(filename, '/');
#endif
    if (pch) {
        pos = pch - filename;
        dirname = (char*) malloc(sizeof(char) * (pos + 1));
        strncpy(dirname, filename, pos);
        dirname[pos] = '\0';
    }
    return dirname;
}

boost basename/dirname

namespace fs = boost::filesystem;
fs::path filename( "<path>" );

basename

std::string basename = filename.leaf();

dirname

std::string dirname = filename.branch_path().native_file_string();

/ を \ として展開したかったりするので、native_file_string() が付くのはわかるが、branch_path っつーのはいったいどんなセンスだ?

extension

std::string extension = boost::filesystem::extension( filename );

basename without extension

std::string stem = boost::filesystem::basename( filename );

phpstring

./phpstring

template

template は すべて #include でなければならない。コンパイルしてリンクではだめ。

サンプル - RingBuffer

#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_

#include "boost/scoped_array.hpp"

/**
 * Ring Buffer Data Structure.
 */
template <class T>
class RingBuffer
{
public:
    /**
     * Default buffer length
     */
    static const unsigned int DEFAULT_LENGTH = 256;
protected:
    /**
     * Smart pointer for Buffer
     */
    boost::scoped_array<T> buffer_ptr;
    /**
     * Pointer to point the newest one's index
     */
    unsigned int newest;
    /**
     * Buffer length
     */
    const unsigned int LENGTH;
public:
    /**
     * Constructor.
     *
     * @param length Buffer length.
     * @param defaultValue Default value of contents of the buffer.
     * @return -
     */
    RingBuffer(
        unsigned long length = DEFAULT_LENGTH, 
        T defaultValue = 0)
        :
        LENGTH(length)
    {
        this->buffer_ptr.reset(new T[this->LENGTH]);
        T *buffer = this->buffer_ptr.get();
        for (unsigned int i = 0; i < this->LENGTH; i++) {
            buffer[i] = defaultValue;
        }
        this->initializeNewest();
    }

    /**
     * Destructor.
     *
     * @param -
     * @return -
     */
	~RingBuffer(void)
    {
    }
public:
    /**
     * Get a direct memory access for a buffered array
     *
     * @return pointer for an array
     */
    inline T* getArray(void) const
    {
        return this->buffer_ptr.get();
    }
protected:
    /**
     * Convert the ring buffer index to the physical memory index.
     *
     * @param i Ring buffer index (0 denotes the newest value)
     * @return Physical memory index (index of buffer[] array)
     */
    inline unsigned int getIndex(unsigned int i) const
    {
         return (i + this->newest) % this->LENGTH;
    };
    /**
     * Initialize the newest  pointer. 
     *
     * @param -
     * @return -
     */
    inline void initializeNewest()
    {
         this->newest = 0;
    }
    /**
     * Forward the newest pointer.
     *
     * @param -
     * @return -
     */
    inline void forwardNewest()
    {
         this->newest = (this->newest == 0 ? this->LENGTH - 1 : this->newest - 1);
    }
public:
    /**
     * Get the length of the buffer
     *
     * @param -
     * @return length
     */
    inline unsigned int getLength() const
    {
        return this->LENGTH;
    }
    /**
     * Get the value at index i 
     * where 0 denotes the newest one and 
     * obj->getLength()-1 denotes the oldest one. 
     *
     * @param i index
     * @return value
     */
    inline T get(unsigned int i = 0) const
    {
        T* buffer = this->buffer_ptr.get();
        return buffer[this->getIndex(i)];
    }
    /**
     * Push the new value and remove the oldest value.
     *
     * @param newValue New value
     * @return Removed oldest value
     */
    T push(T newValue)
    {
        printf("hoge\n");
        this->forwardNewest();
        T *buffer = this->buffer_ptr.get();
        T oldestValue = buffer[this->newest];
        buffer[this->newest] = newValue;
        return oldestValue;
    }
};

#endif // RINGBUFFER_H_
#include <stdio.h>
#include "RingBuffer.hpp"
#include "boost/scoped_ptr.hpp"

// /usr/bin/g++ -I/usr/include/boost-1_33_1 TestRingBuffer.cpp
int main() {
    int num = 3;
    boost::scoped_ptr< RingBuffer<int> > buf_ptr(new RingBuffer<int>(num));
    RingBuffer<int> *buffer = buf_ptr.get();
    buffer->push(1);
    buffer->push(2);
    buffer->push(3);
    for (int i = 0; i < num; i++) {
        printf("%d\n", buffer->get(i));
        // 3 2 1
    }
    buffer->push(4);
    for (int i = 0; i < num; i++) {
        printf("%d\n", buffer->get(i));
        // 4 3 2
    }
    //delete buffer;
}

継承

virtual

継承すなわちvirtual ということはない。

ポリモーフィズム(dynamic binding)を使いたい場合は、親クラスのそのメソッドに virtual をつけておく。

static binding (ただの機能拡張)でよいのならば、別にいらない。

parent

C++ に parent ポインタはない(多重継承のため)

ただし、

    MathRingBuffer(
        unsigned long length = RingBuffer<T>::DEFAULT_LENGTH, 
        T defaultValue = 0)
        :
        RingBuffer<T>(length, defaultValue)
    {
        this->sum = defaultValue * length;
        this->avg = defaultValue;
    }

のように親のコンストラクタを呼ぶことはできる。#コンストラクタ、デストラクタは何もしなくても親のものも呼ばれる(virtual であろうがなかろうが)。型が違う場合に意図的に呼ぶのに便利。

他にもセッターぐらいなら呼べるが getter は返り値があるのできびしい。

template の継承

#ifndef MATHRINGBUFFER_H_
#define MATHRINGBUFFER_H_

#include "boost/scoped_array.hpp"
#include "RingBuffer.hpp"

/**
 * Ring Buffer Data Structure extending statistical functions
 */
template <class T>
class MathRingBuffer : public RingBuffer<T>
{
protected:
    /**
     * Sum of elements.
     */
    double sum;
    /**
     * Average of elements.
     */
    double avg;
    /**
     * Difference between the newest and the oldest element.
     */
    double diff;
public:
    /**
     * Constructor.
     *
     * @param length Buffer length.
     * @param defaultValue Default value of contents of the buffer.
     * @return -
     */
    MathRingBuffer(
        unsigned long length = RingBuffer<T>::DEFAULT_LENGTH, 
        T defaultValue = 0)
        :
        RingBuffer<T>(length, defaultValue)
    {
        this->sum = defaultValue * length;
        this->avg = defaultValue;
    }

    /**
     * Destructor.
     *
     * @param -
     * @return -
     */
	~MathRingBuffer(void)
    {
    }
public:
    /**
     * Get the sum of elements.
     * 
     * @return sum of elements
     */
    inline double getSum(void)
    {
        return this->sum;
    }
    /**
     * Get the average of elements.
     * 
     * @return average of elements
     */
    inline double getAvg(void)
    {
        return this->avg;
    }
    /**
     * Get the difference between the newest and the oldest element.
     * 
     * @return difference between the newest and the oldest
     */
    inline double getDiff(void)
    {
        return this->diff;
    }
public:
    /**
     * Push the new value and remove the oldest value.
     *
     * @param newValue New value
     * @return Removed oldest value
     */
    T push(T newValue)
    {
        this->forwardNewest();
        T *buffer = this->buffer_ptr.get();
        T oldestValue = buffer[this->newest];
        buffer[this->newest] = newValue;

        this->diff = newValue - oldestValue;
        this->sum += diff;
        this->avg += diff / (double)this->LENGTH;

        return oldestValue;
    }
};

#endif // MATHRINGBUFFER_H_