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
- http://d.hatena.ne.jp/firewood/20050601
- http://alxr.usatlas.bnl.gov/lxr/source/external/boost-1_34_1/boost/config/select_platform_config.hpp?v=head
- http://predef.sourceforge.net/
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
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
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_