2011/10/04

C++ - String

สวัสดีผู้อ่านทุกท่านครับ วันนี้ผมจะมาแนะนำ class ตัวหนึ่ง ที่คิดว่าจะทำให้การเขียนโปรแกรมง่ายขึ้น
และเพื่อให้เข้าใจเรื่อง class มากขึ้น

class ที่ผมจะมาแนะนำให้รู้จักคือ string

class string ใน C++ ไม่เหมือนกับ string ใน ภาษา C
ในภาษา C ตัวแปร string คือแถวลำดับของ char
แต่ string ใน C++ จะจัดการกับหน่วยความจำให้กับเราเอง เราไม่ต้องไปยุ่งกับมัน

ก่อนอื่นเลย เราจะต้อง include ไฟล์ที่จำเป็นเข้ามาก่อน คือ

#include <string>

string อยู่ใน namespace std เวลาจะประกาศ object เราจะต้องข้ึนต้นด้วย std

std::string s;

หรือจะประกาศ using namespace std; ไว้เลยก็ได้

using namespace std;


string s;

ลองมาดูฟังก์ชันที่ใช้บ่อยใน string กัน

string::size()
string::length()

ทั้งสองฟังก์ชันนี้จะ return ค่าความยาวของข้อความออกมา
เช่น

s = "Test String";
cout << s.length() << endl;

จะได้ผลลัพท์คือ 11

string::max_size()

จะ return ค่าความยาวของข้อความทั้งหมดที่ string จะสามารถเก็บได้

string::resize(size_t n)
string::resize(size_t n, char c)

จะเป็นการเปลี่ยนขนาดของ string และถ้าเป็นการเพิ่มขนาด จะเอา c ไปต่อท้าย
แต่ถ้าไม่ได้ใส่ค่า c ค่า default คือ '\0'

s = "Test String";
s.resize(7);      // s = "Test St"
s.resize(9, '_'); // s = "Test St__"
s.resize(12);     // s = "Test St__"


string::clear()


เป็นการลบค่าใน string ออก


string::empty()


เป็นการตรวจสอบว่า string มีข้อมูลหรือไม่


string::at(size_t pos)
string::operator[]


คือ char ตัวที่ pos ของ string เช่น s[2]


string::operator+=


เป็นการต่อ string เช่น


s = "String1";
s += " String2";
// s = "String1 String2";


มีความหมายเหมือนกับ


s = s + " String2";


เป็นยังไงกันบ้างครับ string ใช้ง่ายใช่ไหมหล่ะ


เรามาต่อเรื่อง class กันดีกว่า


คราวนี้ผมจะพูดเรื่องการนำฟังก์ชันใน class ออกมาเขียนข้างนอก
จำได้ไหมครับ ว่า class เขียนยังไง ?
คราวนี้ผมจะเขียนแต่ prototype ของฟังก์ชัน


class triangle {
    private:
        float b, h;
    public:
        void setBase(float);
        void setHight(float);
        float getArea();
};


ผมจะนิยามฟังก์ชันข้างนอก ต้องใช้ เครื่องหมาย scope (::) ขั่นระหว่างชื่อ class กับชื่อฟังก์ชัน



void triangle::setBase(float base)
{
    b = base;
}

void triangle::setHight(float hight)
{
    h = hight;
}

float triangle::getArea()
{
    return 0.5 * b * h;
}

ทำไมถึงต้องทำแบบนี้ ?
เพราะว่าถ้าในฟังก์ชันมีคำสั่งเยอะมาก จะทำให้เรามองภาพรวมของ class ยาก
ถ้าใน class มีแต่ prototype และตัวแปร เราจะมองเห็นภาพรวมง่ายขึ้น



หวังว่าบทความนี้จะมีประโยชน์สำหรับใครหลาย ๆ คน นะครับ

2011/10/03

C++ - Classes

จาก Data Structure ที่ผมได้กล่าวไปเมื่อคราวที่แล้ว ยังจำกันได้ไหมเอ่ย

Data Structure คือ กลุ่มของข้อมูลหลาย ๆ ชนิดมารวมอยู่ด้วยกัน
และ Class ก็เหมือน Structure คือกลุ่มของข้อมูลหลาย ๆ ชนิด แต่ยังมี Method อีกด้วย

สรุปคือ
    Data Structure = Data
    Class = Data + Methods

เพื่อความเข้าใจ ผมจะขอยกตัวอย่าง

ยังจำกันได้ไหมว่า structure ประกาศยังไง ?

struct human {
    char name[255];
    int age;
};

ถ้าเราต้องการที่จะประกาศ class เราก็แค่เปลี่ยนคำว่า struct เป็น class

class human {
    char name[255];
    int age;
};

เหมือนกันเลย แค่เปลี่ยนตัวหน้านิดเดียว

แต่ !! เมื่อเราสร้าง object (ตัวแปรของ class เราจะไม่เรียกว่าตัวแปร แต่จะเรียกว่า object แทน) ของ class human เราไม่สามารถที่จะเรียกสมาชิกในนั้นได้...

อย่างเช่น

human a;

เราจะไม่สามารถเรียก

a.name = "Name";

ได้ ทำไมถึงเป็นแบบนี้ ?

คำตอบคือ เพราะว่า class มีการปกป้องข้อมูลของตนเอง เพื่อจำกัดสิทธิ์ในการเข้าถึง

ในภาษา C++ รูปแบบสิทธิ์ของการเข้าถึงข้อมูลจะมี 3 แบบ (ใน Object Pascal มี 4 แบบ)
ได้แก่
    - private
    - public
    - protected

เมื่อเราสร้างตัวแปรใน class แล้วไม่ได้กำหนดขอบเขตการเข้าถึง มันจะถูกกำหนดให้เป็น private โดยอัตโนมัติ

เมื่อขอบเขตถูกกำหนดเป็น private ตัวแปรนั้น ๆ จะไม่สามารถถูกเข้าถึงจากภายนอกได้ เราจึงไม่สามารถเรียก a.name ได้

ถ้าเราต้องการให้ตัวแปรนั้น ๆ สามารถถูกเรียกจากภายนอกได้ เราต้องกำหนดสิทธิ์เป็น public
เราจะได้หน้าตาของ class human แบบใหม่

class human {
    public:
        char name[255];
        int age;
};

คราวนี้เราก็สามารถเรียก a.name ได้แล้ว

ถ้าเราต้องการกำหนดขอบเขตเป็น private ก็แค่ใส่ private: เข้าไป

ส่วน protected ผมขอยังไม่พูดถึงตอนนี้


แล้ว Method คืออะไร ?

ถ้าจะให้พูดง่าย ๆ เลย มันก็คือฟังก์ชันนั่นแหละ

ของดูตัวอย่าง class นี้

class triangle {
    private:
        float b, h;
    public:
        void setBase(float base)
        {
            b = base;
        }
        void setHight(float hight)
        {
            h = hight;
        }
        float getArea()
        {
            return 0.5 * b * h;
        }
};

จะเห็นว่า เราไม่สามารถจะเรียกใช้ตัวแปร b กับ h ใน class นี้ได้
แต่เราสามารถเข้าถึงผ่านทาง function ที่อยู่ใน class แทน

ทำไมถึงต้องทำแบบนี้ ?
ก็เพราะ เพื่อไม่ให้ข้อมูลถูกแก้ไขตามใจชอบ สามารถป้องกันการเปลี่ยนข้อมูลแล้วเกิดข้อผิดพลาดได้อีกด้วย

เมื่อเราจะใช้เราก็เรียกผ่านฟังก์ชันพวกนี้ เช่น

triangle s;
s.setBase(4.2);
s.setHight(6.0);
cout << s.getArea() << endl;

class จะช่วยให้การเขียนโปรแกรมมีความยืดหยุดมากขึ้น
ยังเหลืออีกหลาย ๆ เรื่องเกี่ยวกับ class ที่ผมไม่ได้ยกมาพูดตอนนี้
แต่ผมจะมาพูดให้ฟังในคราวหน้า หวังว่าทุกท่านจะสนุกกับการสร้าง class นะครับ ^_^

C++ - Data Structures

เรารู้จักกลุ่มของข้อมูลชนิดเดียวกันมาแล้ว เรียกว่า array
คราวนี้ผมจะแนะนำให้รู้จักกลุ่มของข้อมูลต่างชนิดกัน ที่เรียกว่า Data Structure

Data Structure คือ กลุ่มของข้อมูลต่างชนิดกันเอามารวมไว้ด้วยกันและตั้งชื่อเพื่อใช้เรียก

ไวยากรณ์

struct structure_name {
    type_1 member_1;
    type_2 member_2;
    ...
    type_n member_n;
};


ตัวอย่าง

struct human {
    char name[255];
    int age;
};

เวลาประกาศตัวแปรก็ประกาศเหมือนตัวแปรแบบปกติ

human a;

เวลาเรียกใช้เราจะใช้ . (จุด) เพื่อบอกข้อมูล member ของ structure นั้น

เช่น ถ้าเราจะเข้าถึงข้อมูลที่ชื่อ name ใน a เราจะใช้ a.name

a.name = "Name";
a.age = 5;

แล้วถ้าต้องการตัวแปร human หลาย ๆ ตัว เราก็สามารถสร้างเป็น array ได้

human b[20];

คือการประกาศตัวแปร array ของ human 20 ตัว

เมื่อเราสร้างตัวแปร structure ที่เป็น pointer

human *c = new human;

แล้วถ้าเราต้องการจะเข้าถึง member ของ c จะต้องเขียนยังไง ?

c.age = 5;

หรือ

*c.age = 5;

ทั้งสองแบบข้างบนเป็นวิธีที่ผิด
เราจะต้องนำค่าของ c ออกมาก่อนโดยการใช้ *c แล้วค่อยเข้าถึง member เราจึงต้องใส่ ( ) ครอบ *c

(*c).age = 5;

แต่ถ้าจะพิมพ์วงเล็บ แล้วใส่ * อีก ทำให้เสียเวลาพิมพ์มาก จึงมีสัญลักษณ์ตัวหนึ่งที่ใช้ลดรูป (*_) คือ ->
เราจึงสามารถเปลี่ยนได้เป็น

c->age = 5;

นอกจากนี้เรายังสามารถประกาศตัวแปรหลังจากประกาศ structure ได้เลย โดยการเขียนชื่อตัวแปรต่อท้ายก่อนเครื่องหมาย ;

struct human {
    char name[255];
    int age;
} a, b, c;

คือการประกาศตัวแปร a, b, c เป็น human

2011/10/02

C++ - Pointer to Array

สวัสดีรอบสองของวันนี้ครับ
คราวนี้ผมจะมาเขียนเรื่องการใช้ Pointer เป็น Array

ปกติในภาษา C เวลาจะประกาศตัวแปรแบบ array เราจะประกาศเป็น

int a[5];


คือการประกาศตัวแปร a เป็น array ของ int มีสมาชิก 5 ตัว (0 - 4)

และเวลาที่เราจะประกาศ Pointer เราจะเขียนเป็น

int *b;

คือให้ b เป็น pointer ของ int
ในภาษา C ถ้าเราต้องการให้ pointer เป็น array เราจะต้องจองหน่วยความจำให้มันโดยใช้ฟังก์ชัน calloc


void* calloc(size_t num, size_t size);


ถ้าจะให้ b เป็น array ที่มีสมาชิก 5 ตัวเราจะเขียนว่า

b = (int*)calloc(5, sizeof(int));

และจะใช้


void free(void*);

ในการลบข้อมูลที่จองออก

free(b)

ในภาษา C++ เราสามารถเขียนอีกแบบหนึ่งได้

เวลาจะประกาศตัวแปร int แต่ต้องการให้เป็น pointer เราจะใช้คำสั่ง new ในการจองหน่วยความจำ

int *c = new int;

และเราจะใช้ คำสั่ง delete ลบค่าออก

delete c;

แต่ถ้าต้องการให้ตัวแปรเป็นแบบ array เราจะใส่จำนวนสมาชิกลงไปด้วย

int *d = new int[5];

คือการประกาศให้ d เป็น array ที่มีสมาชิก 5 ตัว
เห็นไหมครับว่าง่ายกว่าภาษา C เยอะเลย

เวลาจะลบข้อมูลเราก็จะใช้

delete [] d;


แล้ว array สองมิติ จะสร้างยังไงดี ?

int **e = new int*[5];
for (int i = 0; i < 5; i++)
e[i] = new int[3];

คือการประกาศให้ e เป็น array ขนาด 5x3
จากตัวอย่างเราจะสังเกตได้ว่า เราไม่จำเป็นที่จะต้องประกาศ array เป็นสี่เหลี่ยมเสมอไป
เราอาจจะประกาศเป็นรูปอะไรก็ได้

int **f = new int*[3];
f[0] = new int[2];
f[1] = new int[3];
f[2] = new int;

C++ - iostream

สวัสดีครับ ไม่ได้มาเขียนบล็อกตั้งนาน ผมขอพักเรื่อง Object Pascal ไปก่อนนะครับ
วันนี้ขอพูดถึงภาษา C++ แต่จะขอไม่พูดถึงไวยากรณ์พื้นฐานของภาษา C
เช่น if ใช้ยังไง switch case เขียนยังไง while, do while, for เขียนยังไง
ผมจะคิดว่า ทุกคนในที่นี้มีความรู้ภาษา C มาพอสมควรแล้ว

โพสนี้ผมจะพูดเรื่อง iostream ว่ามันคืออะไร ?

ขอนำภาพจาก Wikipedia มาใช้นะครับ

(ref: http://en.wikipedia.org/wiki/Standard_streams)

ปกติแล้วในภาษา C เราจะใช้คำสั่ง printf ที่อยู่ใน stdio.h (Standard Input Output) ในการแสดงข้อความ
ใน Standard Stream จะมี stream อยู่ 3 ตัว คือ stdin (Standard Input), stdout (Standard Output), stderr (Standard Error)

ในภาษา C++ จะเรียก stream ทั้ง 3 แบบว่า cin, cout, cerr
ซึ่ง stream ทั้ง 3 อยู่ใน namespace ที่ชื่อว่า std
วิธีการใช้เราจะต้องประกาศ header ที่ชื่อว่า iostream ก่อน โดยการใช้ #include 

#include <iostream>

เวลาเราจะเรียกใช้ เราต้องเขียน namespace ข้างหน้า
และเราจะใช้ bit shifts ในการส่งค่าให้กับ stream
เช่น ในภาษา C เราเขียนว่า
    printf("Hello World.\n");
เราสามารถใช้ iostream ได้เป็น
    std::cout << "Hello World.\n";
หรือจะใช้ endl (End Line) แทน \n ได้
    std::cout << "Hello World." << std::endl;
นอกจากนี้เรายังสามารถใส่ตัวแปรลงไปได้เลย
    int a = 10;
    std::cout << a << std::endl;

สำหรับการใช้ cin รับค่า
ปกติในภาษา C เราจะใช้ scanf รับค่า
เราต้องรู้ว่า %s %d %c %f มันคืออะไร
แต่ถ้าใช้ cin เราไม่จำเป็นที่จะต้องใช้ เพราะเราสามารถใส่ค่าลงในตัวแปรได้เลย
    int a;
    std::cin >> a;
ถ้าต้องการรับหลายค่าก็แค่
    int a, b, c;
    std::cin >> a >> b >> c;

ส่วน cerr จะไม่ขอพูดถึง

บางคนอาจจะคิดว่า std::cout มันยาวกว่า printf ต้องพิมพ์เยอะเสียเวลา
เราสามารถประกาศให้โปรแกรมของเรารู้จักกับเจ้า std เลย
และเวลาเรียกใช้เราไม่ต้องพิมพ์ std:: อีก
โดยการประกาศ using namespace std; ไว้ข้างบน
ลองดูตัวอย่าง

#include <iostream>


using namespace std;


int main()
{
    cout << "Input an Integer: ";
    int a;
    cin >> a;
    cout << a << " x " << a << " = " << a * a << endl;
    return 0;
}

หวังว่าการใช้ iostream จะช่วยให้เขียนโปรแกรมง่ายขึ้นนะครับ