Archive

Archive for the ‘C++’ Category

ว่าด้วยเรื่อง Memory Static , Stack , Heap ในมุมของโปรแกรมเมอร์

การเป็นโปรแกรมเมอร์ที่ดี นั้นจำเป็นจะต้องเข้าใจ “What goes where” หรือ อะไรไปทางไหน ครับสิ่งที่จะกล่าวนั้น อยู่บนพื้นฐานการใช้งาน Memory ของ C programming  เพื่อให้การเขียนโปรแกรมเป็นไปได้อย่างมีประสิทธิภาพสูงสุด ในบทความนี้ก็เลยจะพูดถึง Memory ที่ถูกใช้งานระหว่างการเขียนโปรแกรม ครับ

( ในบทความนี้ อยู่บนพื้นฐานของ C programming นะครับ )

ใน C programming นั้นจะมีการใช้ Memory อยู่ 3 ชนิดคือ

  • static : เก็บค่าตัวแปรชนิด global  ซึ่งจะอยุ่ฐาวรจนกว่าจะจบโปรแกรม
  • stack : เก็บค่าตัวแปรที่เป็น local หรือตัวแปรที่ประกาศใน function
  • heap : dynamic storage (เป็นพื้นที่ความจำขนาดใหญ่การแบ่งใช้ไม่เป็นลำดับ) 


picture form https://craftofcoding.wordpress.com

STATIC Memory

จากที่ได้กล่าวไว้ตั้งแต่เบื้องต้นนะครับ  static memory จะอยู่ถาวรจนกว่าจะจบโปรแกรม ซึ่งโดยมากจะใช้เก็บค่าตัวแปร global หรือ ตัวแปรที่ประกาศนำด้วย static เช่น

int val ;

ในหลายๆ ระบบ ตัวแปรนี้จะใช้พื้นที่ในหน่วยความจำ จำนวน 4 bytes  หน่วยความจำดังกล่าวนี้อาจมาได้จาก 2 ที่  ถ้า ตัวแปรนี้ประกาศ นอก function ก็จะพิจารณาว่าเป็น global  หมายถึง สามารถเข้าถึงจากที่ไหนก็ได้ในโปรแกรม  และ ตัวแปร global  เป็น static ซึ่งมีชุดเดียวตลอดในโปรแกรม

ตัวแปรใน function เป็น local  ซึ่งจะใช้พื้นที่ของ stack แต่ก็สามารถที่จะบังคับให้เป็น ตัวแปร static ได้โดยการนำหน้าด้วย static cluse. เช่นตัวแปรตัวเดียวกันหากประกาศใน function แต่ถ้านำหน้าด้วย static ก็จะทำให้ถูก ใช้ในพื้นที่ ใน static memory ได้

static int val;

STACK MEMORY

หน่วยความจำstack ใช้เก็บค่าตัวแปรใช้ภายใน function (รวมถึงใน main() function ด้วย )   หน่วยความจำ stack มีโครงสร้างเป็นแบบ LIFO “Last-In-First-Out” ทุกครั้งที่มีการประกาศตัวแปรใน function 9 ตัวแปรจะถูก Push ลงบนstack และเมื่อ function นั้นจบการทำงานตัวแปรทั้งหมด ที่อยู่ใน function จะถูกลบออกและหน่วยความจำนั้นก็จะว่างลง

Stack เป็นพื้นที่ของ หน่วยความจำที่พิเศษ ถูกจัดการด้วย CPU ดังนั้นเราไม่จำเป็นจะต้องทำการ จอง (allocate) หรือ คืน (deallocate) พื้นที่หน่วยความจำ

Stack ถูกแบ่งออกเป็น frame ต่อเนื่องกัน ในขณะที่ function ถูกเรียกนั้น stack frame ใหม่ จะถูก จองใช้งาน

ข้อจำกัดของขนาดของหน่วยความจำ stack นั้นแตกต่างกันไปตาม OS (เช่น OSX มีขนาด stack เท่ากับ  8MB) ถ้าโปรแกรม พยายามใช้ stack มากเกินไป จะเกิด stack overflow ซึ่งก็หมายถึง หน่วยความจำ stack ถูกจองใช้หมด  นอกจากนี้การ เขียน recursion ที่ไม่ถูกต้องก็เป็นอีกสาเหตุที่ทำให้ เกิด stack overflow ด้วย

บทสรุปของ stack

  • หน่วยความจำ stack ถูกจัดการโดย CPU ไม่สามารถเข้าไปแก้ไขได้
  • ตัวแปรถูกจองและคืนพื้นที่อัตโนมัติ
  • พื้นที่หน่วยความจำ stack มีจำกัด – ส่วนมากจะถูกกำหนด upper bound
  • stack ขยายและลดขนาดในขณะที่สร้างตัวแปรและลบตัวแปรไป
  • ตัวแปร stack จะปรากฏก็ต่อเมื่อ function ที่สร้างมันยังคงอยู่

HEAP Memory

เป็นพื้นที่สำหรับการเรียกใช้แบบ dynamic ตรงข้ามกับการใช้งานแบบ stack  หรือเรียกอีกอย่างหนึ่งว่า “free store “ ผู้ใช้เป็นผู้ใช้ จองใช้งานเองไม่ได้ใช้งานแบบ อัตโนมัติ โดย function เช่น malloc() และคืน เช่น free()   การพยายาม free() หน่วยความจำขณะถูกใช้งานอยู่ทำให้การ คืน memory ล้มเหลวและทำให้เกิด memory leak  ทำให้ process อื่น ไม่สามารถจิงใช้งานได้

เรื่อง ขนาดของ HEAP  นั้นค่อนข้างจะไม่จำกัด ซึ่งขึ้นอยู่กับ physical memory และตัวแปรที่ สร้างใน heap สามารถเข้าถึงได้จากทุกที่ในโปรแกรม และ heap memory นี่เองที่เราจะต้องใช้ pointers

บทสรุปของ HEAP

  • หน่วยความจำ HEAP จัดการโดยผู้ใช้ไม่มีขอบเขตในการเข้าถึง
  • ใน C ตัวแปรถูกจองและคืนโดยใช้ function เช่น malloc() และ free()
  • HEAP เป็นส่วนของหน่วยความจำขนาดใหญ่และถูกจำกัดโดย physical memory
  • HEAP เข้าถึงด้วยการใช้ pointer

ตัวอย่าง ของการใช้ memory

ลองพิจารณา code ต่อไปนี้ครับ

picture form https://craftofcoding.wordpress.com

ตัวแปร x เป็น static เพราะว่า เป็นการประกาศแบบ global

ตัวแปร y และ str เป็น stack ซึ่งจะถูกคืนพื้นที่เมื่อโปรแกรมจบ

function malloc() นั้นใช้สำหรับการจองพื้นที่ 100 ช่อง ของ หน่วยความจำ heap แต่ละช่องมีขนาดตาม size ของ char  ให้กับตัวแปร str

function free() สำหรับคืนพื้นที่ ที่ ชี้โดย str

picture form https://craftofcoding.wordpress.com

เป็นไงกันบ้างครับ ทั้งหมดนี้เป็น แนวคิดการใช้งาน พื้นที่หน่วยความจำของตัวแปรแต่ละประเภท สหรับโปรแกรมเมอร์ควรจะต้องเข้าใจกันสักนิสหนึ่ง ผมมั่นใจว่า เราเคยเจอ stack overflow และ memory leak กันเป็นประจำอยู่แล้วในงานการพัฒนาโปรแกรม เกร็ดเล็กเกร็กน้อยช่วยเราให้สามารถหาข้อมูลแก้ไขต่อไปได้ ครับ

Categories: C++

Real-Time Framework [ Single- to Multi-Server Online Game ]

ได้มีโอกาสร่วมอยู่ในงานวิจัย และพัฒนาเกมที่เป็นกึ่ง ๆ online game  แบบ single-server ซึ่ง เดินมาถึงจุดที่ single – server ไม่สามารถให้บริการได้เนื่องจาก มี ผู้ใช้มากขึ้น และจำนวน object หรือ entity ก็มากขึ้นเป็นเงาตามตัวเช่นเดียวกัน  การพัฒนาก็เริ่มมอง หา solution ทำจะช่วยแก้ปัญหาโดยต้องใช้ เวลา และ แรงงาน  ไม่มากนัก  และ RTF ก็เป็น solution หนึ่งที่ น่าสนใจเป็นอย่างยิ่ง ครับ

Real-Time Framework หรือ RTF คือ middleware ที่จะช่วยให้เราสามารถเปลี่ยน Single-Server ให้เป็น Multi-Server online game ครับ  อ้างจาก cast study ที่อ้างอิงในบทความนี้ นะครับว่า  game ประเภท Fast-paced action เช่น First Persons Shooters หรือ FPS นั้น หากต้องการความสามารถ ในการ ขยายระบบรองรับผู้เล่นจำนวนมาก แล้วละก็ ต้องมี สถาปัตยกรรม แบบ multi-server ถึง จะทำได้  แต่การทำ mult-server นั้นเป็นงานที่ท้าทายต่อผู้พัฒนา  เนื่องจาก การประมวลผลจะต้องเป็นการประมวลผลแบบ ขนาน และการ distribute game state  ก็ต้องทำอย่าง มีประสิทธิภาพ  ครับ สองงานหลัก ๆ ที่ game แบบ multi-server นั้นต้อง จัดการให้ได้ ก็คือ เรื่องของการ ทำให้เป็นการประมวลผลแบบขนาน และ การประสานงาน การแจกจ่ายสถานะของ game ให้ได้ประสิทธิภาพ

เนื่องจากว่า มุมมองที่เราจะนำ RTF มาใช้งานก็คือผู้พัฒนา ที่มี game ที่เป็น single-server เป็นของตัวเองอยู่แล้ว และต้องการ ปรับปรุง ให้เป็น multi-server โดยที่ไม่ต้องไปลือระบบของตัวเอง จนแทบจะเรียกได้ว่า ต้องทำกันไหม อะไร แบบนั้นอะครับ  เนื่องจากว่า RTF นั้น จะช่วย ในเรื่องของ การทำ parallelization  และ การจัดการกับ game state โดยเฉพาะในเรื่องของการแจกจ่าย game state ให้อัตโนมัติ  ผุ้พัฒนาที่ใช้ RTF ไม่ต้องเข้าไปดำเนินการเรื่องนี้ เพียงแค่เรียกใช้ผ่าน hight level support ของ RTF เท่านั้นเอง

เพื่อให้ภาพนะครับ ดูจากภาพ แรก

จากภาพเป็นโครงสร้างและการทำงานของ game แบบ single-server นะครับ จะเห็นว่า server เพียงตัวเดียวควบคุมการทำงานทั้งหมด  การคำนวน game states การโต้ตอบกับ ผู้ใช้ และการกระจาย game states กลับไปให้ client ทั้งหมด  ครับ รูปต่อไป


จากภาพแสดงให้เป็น สถาปัตยกรรมแบบ Multi-server game จะเห็นว่า งานการประมวลผล game state การโต้ตอบกับผู้ใช้และการ กระจาย game state นั้นถูกแบ่งออกไป ให้ server อื่น ๆ ช่วยทำงาน  ซึ่งจะเห็นได้ว่า แน่นอนครับการขยายระบบ การเพิ่มจำนวนผู้เล่น ย่อมเกิดขึ้นได้ โดยสถาปัตยกรรมแบบ mult-server

ปัญหาคือว่า ผู้พัฒนาที่มี game ที่เป็น single-server อยู่ในมือจะทำให้เป็น mult-server ได้ด้วย RTF อย่างไร     (ตามที่ได้กล่าวไปแล้วว่า RTF จะช่วยให้ เราเปลี่ยจาก single-server เป็นเป็น Multi-server ได้) จะขอไว้ต่อใน คราวหน้านะครับ

s_teerapong2000@yahoo.com – Soft Speed Solution

Reference
[From a Single- to Multi-Server Online Game: A Quake 3 Case Study Using RTF  , Alexander Ploss, Stefan Wichmann, Frank Glinka , and Sergei Gorlatch  University of Munster, Germany]

แนะนำ การใช้งาน String ใน C++ Win32 – Charater Encodings

ท่านครับ เป็นเรื่องปวดหัวเป็นอย่างยิ่งที่เรา จะต้องแก้ปัญหา เรื่อง ความหลากหลายทางพันธุกรรมของ ข้อมูล string  ที่ใช้งานอยู่ใน c++ ไอ้กระผม ก็รู้จักเพียงอย่างเดียวว่า ข้อมูลแบบ string ก็คือ char * ( array ของ character นั่นเอง ตบท้ายด้วย  ‘\O’ ) เท่านั้น  ต่อมามันรู้สึกว่า ไม่พอเสียแล้ว เวลาไปแก้ปัญหา โปรแกรม ที่มี แบบข้อมูล string ชนิดอื่น ก็ เลยไม่เข้าใจ มึนงง และ หาทางออกไม่ได้ ก็เลยต้อง มานั่ง ศึกษาสักนิดให้เข้าออกเข้าใจ แล้วก็เอามาแบ่งปัน ให้กัน ท่านทั้งหลาย “

มาปูพื้นกันก่อน นะครับ  มาทำความรู้จักกับ  ASCII   DBCS  Unicode

เนื่องจากว่า  string ในแบบของ C-style นั้น มันก็คือ arrays ของ characters  ก็หมายความว่าเราก็ควรที่จะรู้จัก characters กันให้ถ่องแท้ซะก่อน  เขาบอกว่า characters นั้นมีการแบบเข้ารหัส (characters encoding schemes ) 3 แบบ และ ก็แบบของข้อมูลอยู่ 3 ชนิดเช่นเดียวกัน ครับ

character encoding scheme อันแรกก็คือ single-byte character set หรือ SBCS ในการเข้ารหัสแบบนี้ หนึ่ง character ต่อหนึ่ง byte พอดิบพอดีไม่เกินนั้น  ตัวอย่างเช่น  การเข้ารหัสแบบ ASCII ไงครับ   และการปิดท้าย string ของ SBCS ก็ใช้ single zero byte.

character encoding scheme ถัดไปก็คือ multi-byte character set หรือ MBCS ครับ การเข้ารหัสแบบนี้ บาง character ก็มีความยาว 1 byte บาง character ก็มีความยาวมากกว่า 1 bytes   MBCS ที่ใช้ใน Windows มี อยู่ 2 ชนิดคือ
single-byte characters และ double-byte characters   และเรามักจะ  double-byte characters set หรือ DBCS แทน MBCS เนื่องจากว่า multi-byte character ที่ยาวที่สุดที่ใช้ใน windows นั้น ยาวเท่ากับ 2 byte นั่นเอง

ข้อมูลเพิ่มเติมของ DBCS encoding   ข้อมูลบ้างส่วนจะถูก reserved ไว้สำหรับการกำหนดว่า  มันคือ double-byte character เช่น การ encoding แบบ Shift-JIT ( ใช้กับภาษา ญี่ปุ่น ) จะมีค่า  0x81-0x9F และ 0xE0-0xFC หมายถึง นี่คือ double-byte character และข้อมูลถัดจากนี้ไป เป็นข้อมูลของ character นี้  ครับ  ค่าดังกล่าวเราเรียกว่า lead bytes และ จะมากกว่า 0x7F เสมอ  ข้อมูลที่ถัดจาก lead byte เรียกว่า trail byte  และ ข้อมูลในส่วนนี้เป็นค่าอะไรก็ได้ที่ไม่ใช่ 0 หรือ none-zero value  และก็เช่นเดียวกันกับ SBCS   string ของ DBCS นั้น จบด้วย single zero byte

character encoding แบบสุดท้าย ก็คือ Unicode  -unicode เป็นมาตรฐานการ เข้ารหัสที่ ทุก characater แทนด้วยข้อมูล ขนาด 2 byte ครับ  บางที่เราก็เรียก Unicode ว่า Wide characters เพราะมันกว้างกว่า single-byte characters ครับ ก็มันกว้างกว่า ก็เท่านั้น เอง และมันก็ไม่เหมือน กัย MBCS เนื่องจากว่า ใน การแทนข้อมูลของ MBCS นั้นสามารถแทนได้ด้วย 1 byte ก็ได้ 2 byte ก็ได้ นั่นเอง   ส่วนการจบท้ายอขง Unicode string ใช้  two zero bytes

ตัวอย่างของการใช้งานของแต่ละชนิดก็อย่างเช่น  Single-byte characters ใช้แทนข้อมูล ตัวอักษร Latin   ตัวอักษรที่ใช้กำหนด accented และ ตัวอ้กษร graphics    แบบ encoding ที่เรารู้จัก ก็อย่างเช่น ASCII และ DOS Operating system.   ส่วน Double-byte characters นั้นใช้กับภาษา ของประเทศในแถบ เอเชียตะวันออก และ ตะวันออกกลาง  และสุดท้าย Unicode ใช้ใน COM  และใช้ใน Windows NT.

ที่แน่ ๆ นะครับเรารู้จักคุ้นเคยกับ single-byte characters อยู่แล้ว  เวลาเราเขียนโปรแกรม เรียกใช้ char  หมายถึงคุณกำลังดำเนินการับ single-byte character ครับ ส่วน double-byte เราก็ประกาศด้วย char เช่นเดียวกัน ส่วน Unicode นั้น เราแทนเด้วย wchar_t และ  ตัวอักษร และ string literals  แบบ Unicode  ให้นำหน้าด้วย L เช่น ตัวอย่าง

wchar_t wch = L’1′;                 // ใช้ 2 bytes

wchar_t wsz = L”Hello”;         //  10 bytes + 2 bytes ( two zero bytes – to terminate the string )

การใช้งาน functions ที่กัดการเกี่ยวกับ String – ( string handling function )

อย่างที่ได้เคยรู้จัก C string functions เช่น strycpy()  sprintf()  atol()  ฟังก์ชันเหล่านี้ เราใช้กับ single-byte string เท่านั้นนะครับ อย่างไรก็ตาม ใน standard library ก็ยั้งได้จัด function ในการทำงานลักษณะเดียวกัน ให้กับ Unicode string เช่น wcscpy()  swprintf() _wtol()

เอาไว้เท่านี้ก่อนดีมั่ยครับ เอาเป็นไปต่อกันในตอนนที่ 2 นะครับ

s_teerapong2000@yahoo.com  http://www.sssolution.net

Categories: C++

Creating and Using a Static Library (C++) การสร้างและการใช้งาน static library ….

การสร้างและการใช้งาน static library ….

คงไม่ต้อง ให้คำอธิบาย นะครับ ว่า static library คืออะไร เพราะ ถ้าเราหาเรื่องนี้อ่าน ก็หมายถึงว่าเราอยากรู้ว่ามันเป็นอย่างไร ใช้งานอย่างไร  ครับ การใช้ static library นั้นเป็นหนทางที่ดีในการ reuse code หรือ การเขียนโปรแกรมแบบที่สามารถนำส่วนของ code ที่ใช้บ่อย ๆ  มารวมกันไว้ที่ใดที่หนึ่ง ให้สามารถถูกเรียกใช้ได้ ทั่วไป โดยไม่ต้อง ไปเขียน code ลักษณะเดียวกัน ทุกครั้งที่ต้องการใช้งาน  ไหนบอกว่าจะไม่อธิบายไง    นั่นก็คือ เขียนครั้งเดียว ใช้ได้ พร่ำเพรื่อ ฮะ ฮะ

ในบทความนี้ก็จะกล่าวถึง

  • การสร้าง static library
  • การเพิ่ม class ลงใน static library
  • การ สร้าง app ที่เรียกใช้ หรือ อ้างอิง function หรือ class ใน static library

ก่อนอื่นต้อง บอกก่อนว่า ผมอ้างอิง visual c++ ของ Microsoft นะครับ อาจจะเริ่มตั้งแต่  visual studio .NET ขึ้นไปนะครับ

การสร้าง static library

ในการสร้าง static library นั้นเรา ทำตาม ขั้นตอน เหล่านี้นะครับ

  • สร้าง  Project ใหม่       [เลือก New -> Project ]
  • กำหนด ให้ Project type เป็น Win32 [visual c++ ->  Win32 เลือก console application ]
  • กำหนดชื่อ project ให้เป็น MatchFuncLib หรือ ชื่ออื่นก็ได้ตามที่ต้องการ และกำหนด solution Name ให้เป็น  StaticLibrary  หลังจากนั้น ก็ click OK
  • click Next เมื่อ เจอหน้า Win32 Application Wizard
  • กำหนด Application type ให้เป็น static library
  • และเอา Precompiled header ออกpic2
  • สุดท้าย Click finish เพื่อจบขึ้นตอนการสร้าง Project

การเพิ่ม class ลงใน static library

  • สร้าง Header file ให้กับ class ใหม่
  • ที่ Project menu ,  เลือก Add New Item หลังจาก Add New Item dialog box แสดงขึ้นมาให้  เลือก code และ Header File(.h) กำหนดชื่อ ให้เป็น MathFuncsLib.h แล้ว กดปุ่ม Add  จะได้ file เปล่าๆ ขึ้นมาหนึ่ง file
  • เพิ่ม  code นี้ลงไป code นี้ผมเอามาจาก  http://msdn.microsoft.com/en-us/library/ms235627.aspx นะครับ หากต้องการ ข้อมูลเพิ่มเติม ให้เป็นตาม link ได้เลย

namespace MathFuncs
{
class MyMathFuncs
{
public:
// Returns a + b
static double Add(double a, double b);

// Returns a – b
static double Subtract(double a, double b);

// Returns a * b
static double Multiply(double a, double b);

// Returns a / b
// Throws DivideByZeroException if b is 0
static double Divide(double a, double b);
};
}

  • สร้าง source file โดย Project -> Add New Item เลือก C++ file(.cpp) กำหนดชื่อ ให้เป็น MathFuncLib.cpp และ click Add จะได้ file เปล่ามาอีกหนึ่ง file
  • พื่อ implement function ต่าง ที่อยู่ใน header file ขั้นแรกเรา จะทำการ include header file ชื่อ MathFuncLib.h และจึง implement ตัง functions ทั้งหมด ตาม code นี้

// MathFuncsLib.cpp
// compile with: /c /EHsc
// post-build command: lib MathFuncsLib.obj

#include "MathFuncsLib.h"

#include <stdexcept>

using namespace std;

namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}

double MyMathFuncs::Subtract(double a, double b)
{
return a – b;
}

double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}

double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw new invalid_argument("b cannot be zero!");
}

return a / b;
}
}

เอาละครับ มาถึงตรงนี้เรา ก็ ได้ทำการ สร้าง Static library Project ขึ้นมาแล้ว ซึ่ง ถ้าเราสังเกตจะเห็น ว่ามันมี สอง file ชื่อ MathFuncsLib.h และ MathFuncsLib.cpp เราประกาศ class ไว้ใน MatchFuncsLib.h และ implement ใน MatchFuncsLib.cpp นะครับ หลังจากนี้ เราจะทำการ build project ให้เป็น library
ก่อนทำการ Build ให้ทำการ กำหนด project properties ให้ กำหนด configuration properties เป็น general และ Configuration Type ให้เป็น static library(.lib) กดปุ่ม OK เพื่อบันทึกการเปลี่ยนแปลง
Compile static library โดยการ Build Solution จาก Build menu เป็นการจบขั้นตอนการสร้าง static library เพื่อให้โปรแกรม อื่นเรียกใช้งาน

ต่อไปเป็นตัวอย่าง การเรียก ใช้  function จาก static library จาก console application

–          สร้าง console application ( win32 console application )  โดยอาจ ตั้งชื่อให้เป็น  MyExecRefsLib.cpp

–          เพื่อที่จะใช้ math routines ที่สร้างไว้ใน  static library เราจะต้องทำการ อ้างอิงไปหา หรือ Reference

  • ให้เลือก  Reference จาก Project menu ใน properties page dialog box ให้ขยาย common properties node และเลือก reference  แล้วเลือก Add New Reference
  • ขณะนี้ Add reference dialog box จะแสดง   ใน dialog box นี้แสดง รายการ  libraries ทั้งหมด ที่เราสามารถอ้างอิง  ในส่วนของ Project tab นั้นแสดง Projects ทั้งหมด ที่อยู่ใน solution และ libraries ต่าง ๆ ที่มีอยู่  ใน Project tab นี้เรา เลือก MathFuncsLib แล้ว OK
  • เพื่อให้เราสามารถ อ้างอิงไปยัง header files ของ static library ได้ เราต้อง แก้ไข include directories path  โดย ทำดังนี้ ใน Property Pages dialog box, ขยาย Configuration node ขยาย C/C++ node เลือก General
    • เพิ่ม  Additional Include Directories  พิมพ์ หรือ เลือก path ที่  MathFncsLib.h ตั้งอยู่

#include "stdafx.h"
#include <iostream>
#include "MathFuncsLib.h"

using namespace std;
//#include "iostream.h"

int _tmain(int argc, _TCHAR* argv[])
{
double a = 7.4;
int b = 99;

cout << "a + b = " <<
MathFuncs::MyMathFuncs::Add(a, b) << endl;
cout << "a – b = " <<
MathFuncs::MyMathFuncs::Subtract(a, b) << endl;
cout << "a * b = " <<
MathFuncs::MyMathFuncs::Multiply(a, b) << endl;
cout << "a / b = " <<
MathFuncs::MyMathFuncs::Divide(a, b) << endl;

return 0;
}

ทั้งหมด คงพอจะเห็น การทำงานนะครับ หวังว่าจะได้ อะไร ไปบ้าง นะครับ มีอะไร ไม่เข้าใจ mail มาคุยกันนะครับ s_teerapong2000@yahoo.com

Categories: C++, DOT NET, OOP

The game of life, the classic problem and unbeliverable.

What is the game of life ????

The game of life ( or simply life ) is not a game in convenional sense. There are no players , and no winning or losing. One the “piece” are placed in the starting position, the rules determine everything that happens later.  Nevertheless , life is full of surprise! In most cases, it is impossible to look at starting position ( or pattern ) and see what will happen in the future. The only way to find out is to follow the rules of the game…..

There is a good reference site for the rule of this game go to this link : http://www.math.com/students/wonders/life/life.html or if you want to see some online example go : http://www.bitstorm.org/gameoflife/ and this is my code for the game of life in C++ version ( and very simple one )

#include

using namespace std;

int main(int argc, char *argv[])
{
const int row = 34 ;
const int col = 34 ;
// this table for displaying the result
int myTable[row+1][col+1] = {{0}};
// this table for caculating …
int cTable[row+1][col+1]=
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } ;
int count = 1; ;
int Pcount ;
while(count < 1000) {//----------------------Start of while ----------------------------------- cout << "Round number : " << count << endl ; for ( int i = 0; i < row ; i++) { for (int j = 0; j < col; j++) { Pcount = 0; //------------------------------------------------------------------ // Determine amount of neihbore cell.... // ----------------------------------------------------------------- if (( i == 0 )&& ( j == 0 )) // Upper left corner { if (cTable[i+1][j] == 1) Pcount++; if (cTable[i+1][j+1] == 1) Pcount++; if (cTable[i][j+1] == 1) Pcount++; } else if (( i == 0 ) && ( j > 0 )) // Upper border …..
{
if (cTable[i][j-1] == 1 )
Pcount++;
if (cTable[i+1][j-1] == 1)
Pcount++;
if (cTable[i+1][j] == 1)
Pcount++;
if (cTable[i+1][j+1] == 1)
Pcount++ ;
if (cTable[i][j+1] == 1)
Pcount++;
}
else if ( ( i == 0 ) && ( j == col )) // Upper right cornet
{
if (cTable[i+1][j] == 1)
Pcount++;
if (cTable[i+1][j-1] == 1)
Pcount++;
if (cTable[i][j-1] == 1)
Pcount++;
}
else if ( ( j == 0 ) && ( i > 0 ) ) // left border …………
{
if (cTable[i-1][j] == 1)
Pcount++;
if (cTable[i-1][j+1] == 1)
Pcount++;
if (cTable[i][j+1] == 1)
Pcount++;
if (cTable[i+1][j+1] ==1)
Pcount++;
if (cTable[i+1][j] == 1)
Pcount++;
}
else if ( ( j == 0 ) && ( i == row )) // lower left
{
if(cTable[i-1][j] == 1 )
Pcount++;
if(cTable[i-1][j+1] == 1)
Pcount++;
if(cTable[i][j+1] == 1)
Pcount++;
}
else if ( ( i == row ) && ( j > 0 ) ) // lower border …….
{
if(cTable[i][j-1] == 1)
Pcount++;
if(cTable[i-1][j-1] == 1)
Pcount++;
if(cTable[i-1][j] == 1)
Pcount++;
if(cTable[i-1][j+1] == 1)
Pcount++;
if(cTable[i][j+1] == 1)
Pcount++;
}
else if ( ( i == row ) && ( j == col )) // lower right
{
if(cTable[i][j-1] == 1 )
Pcount++;
if(cTable[i-1][j-1] == 1)
Pcount++;
if(cTable[i-1][j] == 1)
Pcount++;
}
else if ( ( i > 0 ) && ( j == col )) // right border …..
{
if(cTable[i+1][j] == 1)
Pcount++;
if(cTable[i+1][j-1] == 1)
Pcount++;
if(cTable[i][j-1] == 1)
Pcount++;
if(cTable[i-1][j-1] == 1)
Pcount++;
if(cTable[i-1][j] ==1)
Pcount++;
}
else if ( (( i > 0 ) && ( i < row )) && ( ( j > 0 )&&( j < col )) ) // inside the box ...... { if(cTable[i-1][j-1]==1) Pcount++; if(cTable[i-1][j] == 1) Pcount++; if(cTable[i-1][j+1] == 1) Pcount++; if(cTable[i][j-1] == 1) Pcount++; if(cTable[i][j+1] == 1) Pcount++; if(cTable[i+1][j-1] == 1) Pcount++; if(cTable[i+1][j] == 1) Pcount++; if(cTable[i+1][j+1] == 1) Pcount++; } else { Pcount = 0; } // ----------------------------------------------------------------- // Determine and plot to myTable... // This part apply to all i,j // ----------------------------------------------------------------- if ( cTable[i][j] == 0 ) // dead cell { if ( Pcount == 3 ) { myTable[i][j] = 1; } } else // life cell { if ( ( Pcount == 2 ) || ( Pcount == 3) ) { myTable[i][j] = 1; } else { myTable[i][j] = 0 ; } } } } // ------------------------------------------------------------------------- // -------- Copy all from myTable to cTable , for the next calculation ----- // ------------------------------------------------------------------------- for (int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { cTable[i][j]= myTable[i][j]; } } // -------------------------------------------------------------------------- // ------- Display the result ----------------------------------------------- // -------------------------------------------------------------------------- for ( int i = 0; i < row; i++ ) { for(int j= 0; j < col; j++) { //cout << myTable[i][j] << " " ; if (myTable[i][j] == 1 ) { cout << "*" << "" ; } else { cout << "-" << ""; } } //cout << endl; cout << endl; } //-------------------------------------------------------------------------- // Clear The display Table.... for ( int i = 0; i < row; i++ ) { for(int j= 0; j < col; j++) { myTable[i][j] = 0; } } // delay form some amount of time.. Time_Delay(); // clear the console... system("cls"); // Add one to count ... count++; }// end of while system("PAUSE"); return EXIT_SUCCESS; } //---------------------------------------------------------------------------------------------- // ---- Function Library ----------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- void Time_Delay(void) { //----------------------------------------------------------------------------------------- // delay for some amount of times... don't know how many , but just some amount of time.. //----------------------------------------------------------------------------------------- for ( int i = 0; i < 10000 ; i++) { for ( int j = 0; j < 20000 ; j++) { ; } } } [/sourcecode]

Categories: C++

The publication, book and tape classes , more advance….

Add another base class sales that holds and array of three floats it can record the sales of a particular publication for the last three months. Include getdata() function to get three sales amounts from the user , and a putdata() function to display the sales figures. Alter the book and tape classes so that they are derived from both publication and sales. An object of class book or tape should input or output sales along with its other data.

#include
using namespace std;

class sale
{
private:
float salerec[3];
public:
void getdata()
{
cout << " Enter the sales for the last three months :" << endl; for (int i = 0; i < 3 ; i++) { cout << " Enter sales for month : " << i+1 << " > “;
cin >> salerec[i];
}
}
void putdata()
{
cout << " The sale of the last three month " << endl; for(int i=0; i < 3; i++) { cout << " Month no : " << i+1 << " > ” << salerec[i] << endl; } } }; class publication { private: char title[50] ; float price; public: void getdata() { cout << " Enter publication title : " ; cin >> title;
cout << " Enter publication price : " ; cin >> price;
}

void putdata()
{
cout << " Publication title : " << title << endl; cout << " Publication price : " << price << endl; } }; // end of class publication class book : public publication, public sale { private: int pageCount ; public: void getdata() { publication::getdata(); cout << " Enter page count : " ; cin >> pageCount;
sale::getdata();
}
void putdata()
{
publication::putdata();
cout << " Page count : " << pageCount ; cout << endl; sale::putdata(); } }; class tape : public publication , public sale { private: int playingtime; public: void getdata() { publication::getdata(); cout << " Enter page count : "; cin >> playingtime;
sale::getdata();
}
void putdata()
{
publication::putdata();
cout << " Playing time : " << playingtime; cout << endl; sale::putdata(); } }; int main(int argc, char** argv) { book mybook; //tape mytape; // get the book data mybook.getdata(); //mybook.sale::getdata(); mybook.putdata(); //mybook.sale::putdata(); // get the tape data //mytape.getdata(); //mytape.putdata(); return (EXIT_SUCCESS); } [/sourcecode]

Categories: C++

Inheritance , Classroom Exercise, NIIT student

Create a class called publication that store the title ( a string ) and price ( type float ) of a publication. From this class, derive two class: book which adds a page count ( type int ); and tape , which adds a playing time (type int ) in minutes. Each of these classes should have a getdata() function to get its data from the user, and a putdata() to display its data.

//———————————————————

#include
using namespace std;
class publication
{
private:
char title[50] ;
float price;
public:
void getdata()
{
cout << " Enter publication title : " ; cin >> title;
cout << " Enter publication price : " ; cin >> price;
}

void putdata()
{
cout << " Publication title : " << title << endl; cout << " Publication price : " << price << endl; } }; // end of class publication class book : public publication { private: int pageCount ; public: void getdata() { publication::getdata(); cout << " Enter page count : " ; cin >> pageCount;
}
void putdata()
{
publication::putdata();
cout << " Page count : " << pageCount ; cout << endl; } }; class tape : public publication { private: int playingtime; public: void getdata() { publication::getdata(); cout << " Enter page count : "; cin >> playingtime;
}
void putdata()
{
publication::putdata();
cout << " Playing time : " << playingtime; cout << endl; } }; int main(int argc, char** argv) { book mybook; tape mytape; // get the book data mybook.getdata(); mybook.putdata(); // get the tape data mytape.getdata(); mytape.putdata(); return (EXIT_SUCCESS); } [/sourcecode] .. That what i've done with the exercise ...

Categories: C++