วันศุกร์ที่ 8 ตุลาคม พ.ศ. 2553

The Lex & Yacc

compiler หรือ interpreter สำหรับภาษาโปรแกรม(programming language) นั้นโดยปกติแล้วจะแบ่งออกเป็น 2 ส่วนคือ

  1. ส่วนที่ใช้ในการอ่าน Source Program และตรวจสอบโครงสร้างหรือ Structure ของตัว Source Program
  2. เป็นส่วนที่ใช้จัดการกับ Structure ของ Source Program

สิ่งที่ Lex และ Yacc ทำคือ

  1. ตัดคำหรือแบ่ง Source file ออกเป็น token ย่อยๆ (Lex)
  2. ตรวจสอบไวยากรณ์ของภาษาโปรแกรม โดยวิเคราะจากโครงสร้างที่แตกย่อยออกมาของ program (Yacc)

Lex – A Lexical Analyzer Generator

Lex นี้จะช่วยตัดคำ(Token) ของ source program จากการกำหนดโดย regular expressions ที่ได้รับมาจาก input stream แล้วส่งไปให้ parser ทำงานต่อ โดย source ของ Lex นี้ก็คือตาราง regular expressions และ คำหรือ Token ต่างๆที่ถูกกำหนดเอาไว้ในภาษาโปรแกรมที่ออกแบบไว้ โดยตารางนี้จะถูก translated เป็น program ที่จะใช้ในการอ่านข้อมูลจาก input stream โดยจะตัดคำ(Token) ที่ตรงกับ expressions ที่ได้กำหนดเอาไว้ โดย expression นี้จะถูกกำหนดโดย DFA หรือ deterministic finite automaton generated โดย Lex

 Yacc: Yet Another Compiler-Compiler

Yacc คือ tool ที่ใช้สำหรับอธิบายข้อมูลอินพุทให้กับ computer program ซึ่งผู้ที่ใช้ Yacc นี้จะกำหนดโครงสร้าง(Structure) ของข้อมูล input รวมไว้กับ code ที่จะถูกเรียกเอาไว้สำหรับในแต่ละ structure ที่ตรงกันสำหรับจัดการกับข้อมูลอินพุท โดยจะแบ่งออกเป็น subroutine ย่อยๆเอาไว้

 

เนื่องจาก lex กับ yacc มันเก่าแล้ว ก็เลยมีคนพัฒนา tool ตัวใหม่ๆออกมาหลายตัวดัวยกัน แต่สำหรับเอง ผมใช้

  • flex อันนี้ใช้สำหรับ lex
  • bison อันนี้ใช้สำหรับ yacc

*flex = lex,bison = yacc

ซึ่ง tool สองอันนี้เป็น OpenSource จึงสามารถนำมา compile และติดตั้งบน Linux ได้โดยไม่มีปัญหา

Flex,A fast scanner generator

Flex เป็น tool สำหรับสร้าง scanner (scanner generator) โดยprogramที่จะได้รับการยอมรับนั้นจะต้องตรงตาม lexical patterns โดยการทำงานของ flex นี้จะเริ่มจากการอ่านข้อมูล input จาก file เข้ามาหรือผ่านทาง stardard input ถ้าไม่มีการส่ง file name ให้กับ flex เพื่อใช้การอธิบายข้อกำหนดต่างๆ ก่อนที่จะทำการ generate scanner code ออกมา ดังนั้นก่อนที่จะใช้เจ้า flex นี้ได้ เราจะต้องมีการกำหนด regular expressions และชุดคำสั่งภาษา C ซึ่งเราจะเรียกว่า “RULES “ หลังจากที่กำหนด rules ต่างๆเรียบร้อยแล้วจึงใช้ flex นี้เป็น code generator ที่เราจะใช้เป็น scanner สำหรับตัดคำนั้นเอง โดย flex นี้จะ gen. ไฟล์ออกเป็นเป็นไฟล์ภาษา C ที่ชื่อว่า “lex.yy.c” ซึ่งใน file นี้จะมี routine ‘yylex()’ อยู่ภายใน จากนั้นก็เอาไฟล์ที่ได้มานี้ไปทำการ compile กับ c compiler ได้ออกมาเป็น executable ไฟล์สำหรับใช้งานอีกทีนึง

Bison, The Yacc-Compatible Parser Generator

Bison คือ parser generator ที่แปลงส่วนอธิบาย grammar ของ LALR context-free grammar (LALR parser generator เป็น software tool ที่ใช้ในการอ่าน BNF Grammar เข้ามาแล้ว generate code ให้เป็น LALR parser) ออกมาเป็น C program ที่ใช้ในการวิเคราะห์ไวยากรณ์

*Bison นี้ถูกพัฒนามาจาก Yacc ซึ่งการเขียน Yacc Grammar นี้จะสามารถนำไปใช้ได้กับ Bison ได้โดยไม่ต้องมีการเปลี่ยนแปลงเลย ซึ่งทำให้ผู้ที่มีความคุ้นเคยกับ Yacc นั้นสามารถเปลี่ยนมาใช้ Bison ได้โดยง่าย

วันนี้ง่วงนอนแระ เอาไว้รอบหน้าผมจะเอา Flex/Bison มาอธิบายให้ฟังกันอย่างละเอียดกันไปเลยทีเดียวละกันนะคับ อิอิ

วันพฤหัสบดีที่ 7 ตุลาคม พ.ศ. 2553

วิธีกำหนด JFrame ให้อยู่กลางจอ

ถ้าเราจะจัดให้ JFrame ของเราอยู่กลางหน้าได้โดยเรียกใช้ Function getToolkit().getScreenSize() เราจะได้ขนาดของหน้าจอกลับมาในรูปของ Dimention Object (ไอ้เจ้าฟังก์ชั่น getToolkit() ของ JFrame นี้มัน inherit มาจาก Window) ลองมาดูตัวอย่างกันคับ

Dimension d = getToolkit().getScreenSize();

int screenWidth = d.width;

int screenHeight = d.height;

หลังจากนั้นเราก็มาหาตำแหน่งกึ่งกลางของจอโดยเอาค่าความกว้างกับความยาวมาหารด้วย2

int centerX = screenWidth/2;

int centerY = screenHeight/2;

แล้วก็มาหาตำแหน่งที่เราจะวาง JFrame เพื่อให้ frame นั้นอยู่กลางหน้าจอ เนื่องจากว่าเวลาเรากำหนดตำแหน่งของ frame ตำแหน่งที่เรากำหนดจะเป็นตำแหน่งของมุมซ้ายด้านบนของ frame มันเลยไม่อยู่ตรงกลางให้เรา (55+) ดังนั้นถ้าเราจะกำหนดตำแหน่งกึ่งกลางจอให้กับ JFrame ตรงๆนั้น frame ก็จะไม่ได้อยู่ตรงกลางเราจึงต้องคำนวนหาตำแหน่งของมันซะก่อน โดยลบค่าของ centerX และ centerY ด้วยขนาดครึ่งนึงของ frame ตามลำดับดังนี้

int xPos = centerX – frame.getWidth() / 2;

int yPos = centerY – frame.getHeight() / 2;

*สมมติให้ frame เป็น reference ของ JFrame

และแล้วเราก็จะได้ตำแหน่งที่จะต้องกำหนดให้กับ JFrame แว้ววว… ก็มาsetค่าตำแหน่งให้กับมันเลยคับ

frame.setLocation(xPos,yPos);

ก็เป็นอันว่า frame ของเราก็จะอยู่ตรงกลางเป็นที่เรียบร้อยละค๊าบบ.. มาดูตัวอย่างกันดีกว่า อิอิ

import javax.swing.*;

import java.awt.*;

public class TestJFrame extends JFrame {

  public static void main(String[] agrs) {

    JFrame f = new JFrame(“Centering JFrame”);

    f.setSize(200,200);

    Dimension d = f.getToolkit().getScreenSize();

    int screenWidth = d.width;

    int screenHeight = d.height;

    int centerX = screenWidth / 2;

    int centerY = screenHeight / 2;

    int xPos = centerX – f.getWidth() / 2;

    int yPos = centerY – f.getHeight() / 2;

    f.setLocation(xPos,yPos);

    f.setVisible(true);

  }

}

วันจันทร์ที่ 26 กรกฎาคม พ.ศ. 2553

Style การเขียนโปรแกรมเมื่อใช้ &

โปรแกรมเมอร์ C++ บางคนชอบเขียนเครื่องหมาย & ต่อท้ายชนิดข้อมูลมากกว่าที่จะเขียนไว้หน้าตัวแปร เช่น

void swap(int& a,int& b);

และนอกจากนี้บางคนยังนิยมเขียนวิธีนี้กับ Pointer operator ด้วยเช่น

float* p;

จุดประสงค์เพื่อจะให้มีความแตกต่างว่าเป็นข้อมูลชนิดpointer แต่วิธีการนี้อาจก่อให้เกิดความสับสนกับการประกาศเพราะ & และ * ใช้กับลิสต์ของตัวแปรไม่ได้เช่น ถ้าต้องการประกาศตัวแปร Integer 2ตัว เป็นpointer

int* a,b;

จะทำไม่ได้เพราะ b จะเป็นตัวแปรแบบ Integer ธรรมดาไม่ใช้ตัวแปรแบบ Pointer เพราะ & และ * จะใช้ได้กับตัวแปรทีละตัวเท่านั้น

สำหรับการเขียน &,* นั้นจะเขียนแบบไหนก็ได้เพราะ compiler จะตีความหมายเหมือนกัน

วันอาทิตย์ที่ 25 กรกฎาคม พ.ศ. 2553

การคืนค่า Function แบบ References

     นอกจากจะใช้พารามิเตอร์ Reference ได้แล้ว ยังสามารถใช้วิธีการนี้กับการคืนค่าของfunctionได้ เราสามารถทำได้โดยใช้เครื่องหมาย & นำหน้าชื่อ function เช่น prototype ของ f() ที่คืนค่า Integer แบบ Refernce

int &f();

     ในfunctionที่คืนค่าแบบ Reference นั้น compiler จะรู้เองว่าต้องคืนค่าที่เป็น address ของ object แทนที่จะเป็นค่าของมัน เช่น

int &f(){

  int i;

  cin >> i;     // get a value for i

  return i;     // automaticity returns reference to i

วันจันทร์ที่ 19 กรกฎาคม พ.ศ. 2553

จัดไป1เพลง กับวันเหง๊าาาา….เหงา

 

 

 

 

 

 

 

 

 

 

 

ในยามที่เราได้พบกัน ฉันจะเปรียบเธอเป็นเช่นดอกไม้
ในยามที่เราได้รักกัน ฉันจะปลูกต้นรักไปทั้งใจ
เวลาที่มีหยาดฝนโปรยปราย ฉันจะปรากฏกายข้างเธอไม่ห่างไปไหน
เวลาที่มีเรื่องร้อนใจ ฉันจะปัดและเป่าให้เธอจนชื่นใจ

ถึงแม้วันใดไม่มีฉันอยู่ ให้เธอรู้ความรักคงอยู่ไม่ห่างไปไหน
ต้นรักที่ฉันปลูกไว้ข้างใน หากเธอคงรักนั้นไว้ คอยดูแลรักฉันไว้... โว๊ะ โอ โอะ..

ความรักที่มีให้กัน ถ้าเธอคอยรักและอยู่เคียงข้างกัน
แค่ให้ความอบอุ่น และรักที่มีนั้นช่วยพาเราไป โว๊ะ โอ โอะ..
ความรักส่งไปให้เธอ แด่เธอที่รัก มั่นคงไว้เสมอ
ด้วยความรักที่มีแค่เรา ข้างกันและกัน

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

วันเสาร์ที่ 17 กรกฎาคม พ.ศ. 2553

Newton – Raphson Method

การแก้ปัญหาทางคณิตศาสตร์ วิทยาศาสตร์ บางครั้งจะต้องแก้หาค่า x จากสมการ f(x)=0 ถ้าหากเป็นfunction กำลังสองทั่วไปอาจใช้ สูตรมาแก้สมการได้ แต่ถ้าเป็นfunctionที่มีกำลังสูงขึ้นจะไม่มีสูตรที่แน่นอน จึงมีวิธีการทางการวิเคราะห์เชิงตัวเลข(Numerical Analysis) มาแก้ปัญหาสำหรับเทคนิคที่นิยมใช้กันจะเป็นวิธีของนิวตัน หรือ Newton – Raphson Method ซึ่งจะใช้เส้นสัมผัสเส้นโค้ง y=f(x) ที่จุด f เข้าใกล้ศูนย์มาช่วยประมาณค่า

สมการของเส้นสัมผัสของกราฟ y=f(x) ที่จุด x=a หรือเส้นสัมผัสที่ผ่านจุด(a,f(a)) จะมีสมการเป็น
                        L(x) = f(a) – f‘(a) (x-a)

image

 

 

จากภาพ เป็นfunction y = x^2
และเส้นสัมผัสของ f(x) ที่จุด x=5

 

 


 

 

ขั้นตอนของ Newton – Raphson

การประมาณค่ารากของ function จากสมการ f(x) = 0 จะทำโดยอาศัยเส้นสัมผัส เส้นโค้ง y = f(x) ถ้าหากเริ่มต้นประมาณค่า x ด้วย x0 ให้ลากเส้นสัมผัสที่จุด (x0,f(x0)) เส้นสัมผัสจะตัดแกน x1 ซึ่ง x1 นี้จะมีค่าใกล้เคียงกับรากของสมการด้วย เรามาดูตัวอย่างในรูปกันคับ

image
















จากนั้นให้ใช้ x1 ประมาณค่าต่อไปโดยลากเส้นสัมผัสที่จุด (x1,f(x1)) ทำให้เส้นสัมผัสมาตัดแกน x ที่จุด x2 และใช้ x2 นี้ประมาณค่าต่อไปอีก ซึ่งจะทำให้ค่า x ที่ได้ใกล้เคียงคำตอบมากขึ้นเรื่อยๆ ดังนั้นถ้าทำขั้นตอนเหล่านี้ n+1 ครั้ง จะได้ค่าประมาณเป็น x ที่ n+1 ซึ่งเกิดจากการประมาณค่าจากจุด x ที่ n โดยสมการเส้นสัมผัสที่จุด (xn,f(xn)) คือ

                              y – f(xn) = f’(xn) (x-xn)

เนื่องจากเส้นสัมผัสที่ตัดแกน x นั้นค่า y จะเท่ากับศูนย์อย่างในรูป ดังนั้น
                             0 – f(xn) = f’(xn) (x-xn)
                                - f(xn) = f‘(xn) (x-xn)
                                - f(xn) = f’(xn) * x – f’(xn) * xn
                             f(xn) * x = f’(xn) * xn – f(xn)
                                       x = xn – f(xn) / f’(xn)

Overriding Method

Methods defined in a superclass can be overridden by methods defined in a subclass. Here is the definition:

Definition Overiding: Overriding refers to the introduction of an instance method in a subclass that has the same name,signature,and return type of a method in the superclass. Implementation of the method in the subclass replaces the implementation of the method in the superclass.

Overriding is different from overloading.Overriding is concerned with methods of different classes that have an inheritance relationship.In overriding,methods share the same name,signature,and return type.In contrast,overloaded methods are part of the same class,but have different signatures.

We can illustrate the distinction between overloading and overriding in the following manner. In

class A{
        public void m1(){
            //statement
        }
        public void m1(int i){
            //statement
        }
    }

class A contain two overloaded methods.An instance of A can access both methods,depending on the arguments of the method invocation,so

A a = new A();
a.m1();            //invoke m1()
a.m1(1);          //invoke m1(int)

Now,let us assume that we have the two classes

class B{
    public void m2(){
        //statement
    }
}
class C{
    public void m2(){
        //statement
    }
}

Implementation of method m2() in class B is overridden by another implementation of method m2() in class C. For a given object,one but not both of the implementations of method m2() is available, depending on the class of the object.

B b = new B();
C c = new C();
b.m2(); //invoke the m2() in class B
c.m2(); //invoke the m2() in class C

Overriding a method with another method of different signature or return type is not allowed.For example,the following code segment will cause a compilation error:

class B{
    public void m3(int i){
    }
}
class C{
    public void m3(char c){
    }
}

วันศุกร์ที่ 16 กรกฎาคม พ.ศ. 2553

Overloading Method

Definition Overloading: Overloading refers to the ability to allow different methods of constructors of a class to share the same name. The name is said to be overloaded with multiple implementations.

The legality of overloading depends on the signatures of the methods or constructors being overloaded. The signature of a methods or constructor consists of the name of  the method and a list of the types of its parameters.Note that the return type,parameter names and final designations of parameters are not part of the signature. Parameter order,however,is significant. The following are some examples of methods and their signatures.

Method Signature
String toString() toString()
void move(int dx,int dy) move(int,int)
void move(final int dx,final int dy) move(int,int)
void paint(Graphics g) paint(Graphics)

The Rule of Overloading: Two methods of constructors in the same class can be overloaded,i.e.,sharing the same name,if they have either different numbers of parameters or the same number of parameters but of different types.In other words,no two methods or constructors in the same class may have identical signatures.

The following class declaration illustrates overloaded constructors and overloaded methods:

public class Point {
    protected double x,y;
    public Point(){
        x = 0.0;y = 0.0;
    }
    public Point(double x,double y){
        this.x = x;this.y = y;
    }
    /** calculate the distance between this point and the other point */
    public double distance(Point other){
        double dx = this.x - other.x;
        double dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy *dy);
    }
    /** calculate the distance between this point and(x,y) */
    public double distance(double x,double y){
        double dx = this.x - x;
        double dy = this.y - y;
        return Math.sqrt(dx * dx + dy * dy);
    }
    /** calculate the distance between this point and(x,y) */
    public double distance(int x,int y){
        double dx = this.x - (double) x;
        double dy = this.y - (double) y;
        return Math.sqrt(dx * dx + dy * dy);
    }
    /** calculate the distance between this point and the origin */
    public double distance() {
        return Math.sqrt(x * x + y * y);
    }
    // other method
}

When an overloaded method is called, the number and the types of the arguments are used to determine the signature of the method that will be invoked.Overloading is resolved at compile time,as in the following code segment:

Point p1 = new Point();                               //invoke Point()
Point p2 = new Point(20.0,30.0);                 //invoke Point(double,double)
p2.distance(p1);                                         //invoke distance(Point)
p2.distance(50.0,60.0);                               //invoke distance(double,double)
p2.distance(50,60);                                    //invoke distance(int,int)
p2.distance();                                            //invoke distance()

วันอาทิตย์ที่ 11 กรกฎาคม พ.ศ. 2553

การสร้าง Package ใน Java

1.ตั้งชื่อ package
สมมุติให้ชื่อว่า mypackage.homework
2. package ที่เราสร้างต้องอยู่ในโฟลเดอร์หนึ่งๆ
ในที่นี้ให้อนู่ใน E:\user
3.เราต้องให้ java รู้ว่านอกจาก stardard java class แล้วยังมี package อื่นอีก
เราต้องไปกำหนดค่า base ใน classpath
วิธีการกำหนดค่าใน classpath
Start --> Settings --> Control Panel --> Systems --> Advance
--> Enviroment Variable --> หาตัวที่เราเก็บ java ไว้โดยมากจะชื่อว่า
path หรือไม่ ก็ class path เลือกแล้วกด Edit --> แล้วใส่ที่อยู่ของ package
ในที่นี้ คือ E:\user แล้วใน semi colon ต่อท้าย --> Ok
4.เราจะไปสร้างโฟลเดอร์ต่อจากที่เราเก็บที่อยู่ คือไปสร้างต่อที่ E:\user
ในที่นี้ให้ชื่อว่า mypackage
5.แล้วเราไปสร้างโฟลเดอร์ต่อจาก mypackage ให้ชื่อว่า homework
6.เสร็จแล้วเราของเอา class ที่เราเขียนมาใส่ในโปลเดอร์ homework
7.วิธีการสร้าง package เราจะใช้ keyword คำว่า package ในการขึ้นต้น
เพื่อทำให้ java ทราบว่าเรากำลังจะสร้าง package ใหม่
package mypackage.homework; //ชื่อ package กับ keyword ว่า package
public class BankAccount { //ชื่อ class ที่จะสร้างไว้เป็น package
//instance variable
//constructor
//method
}
แล้ว compile ให้ได้ไฟล์ .class เอาไว้ที่ E:\user\mypackage\homework\ ด้วยนะครับ
8.วิธีการใช้เราต้อง import เข้ามา
import mypackage.homework.BankAccount ;
public class BankAccountTest {
BankAccount A_NagativesAcc = new BankAccount(500.00);
}
credit : citec.us

วันอังคารที่ 6 กรกฎาคม พ.ศ. 2553

BiSection Method By MathLAB

อันนี้เป็นการหาrootของfunction โดยใช้วิธี BiSection Methodในการหาroot และทำการตรวจสอบfunctionที่ไม่เป็น continuous function ด้วย ซึ่งnot continuous function ก็จะมีลักษณะอย่างในภาพตัวอย่าง ซึ่งจะทำให้เราหาrootของfunctionไม่ได้นะคับ

image1 image2

ลักษณะของ function ที่เราสามารถหาrootได้จะต้องเป็น continuous function เท่านั้น โดยเราจะต้องกำหนด boundary เอาไว้ด้วยตัวอย่างเช่น

image3

เราสามารถหา root ของfunction ได้ โดยทำการกำหนด boundary เอาไว้ด้วย มาดูโปรแกรมตรวจสอบกันคับ (อันนี้ผมเขียนกับ MathLAB)

clear all;
close all;
clc;
f = inline('x^3+x^2+x-1');
a = -0.5;
b = 1;
tol1 = 0.0001;
tol2 = 0.0001;
flags = false;
max1=1+round(log(a-b)-log(tol1)/log(2));
fm = zeros(1,abs(max1));
if (f(a)*f(b) == 0)
    if (f(a) == 0)
        root = a;
    else
        root = b;
    end
else
    lamda = abs((a+b)/20);
    if f(a)<f(b)
       if f(a)<f(a+lamda)
          disp ('Continuous function')
          flags = true;
       else
          disp ('Not continuous function')
       end
    elseif f(b)<f(a)
       if f(b)<f(b-lamda)
          disp ('Continuous function')
          flags = true;
       else
           disp ('Not continuous function')
       end
    end
    count = 0;
end
if(flags)
   for j = 1:max1
      m = (a+b)/2;
      fm(j) = f(m);
      [j a b m f(m)]
      if(f(a)*f(m) > 0)
          a = m;
      else
          b = m;
      end
      if (b-a)/2<tol1
          flags = false;
          root = m;
      end
   end
   fm_greater_than_zero = [fm(find(fm>0))]
   fm_less_than_zero = fm(find(fm<0))
end

วันอังคารที่ 15 มิถุนายน พ.ศ. 2553

การส่งparameter แบบ pass by reference

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

#include <iostream>
using namespace std;
void MyFunction(int&);
void main(){
    int iMyVariable = 5;
    MyFunction(iMyVariable);
    cout << "iMyVariable = " << iMyVariable << endl;
}
void MyFunction(int &i){
    i+=3;
}

วันพฤหัสบดีที่ 20 พฤษภาคม พ.ศ. 2553

การใช้ & operator ใน C++

โอเปอเรเตอร์ & ใน c++ อาจหมายถึง address หรือการอ้างอิงก็ได้ compiler c++ จะตีความหมายของ & operator โดยดูจากเนื้อความของประโยคนั้นๆ

ตัวอย่าง 1: ในประโยคต่อไปนี้ & operator ใช้ในการสร้างตัวแปรแบบอ้างอิง(Reference Variable) หรือก็คือ Alias Variable นั้นเอง

int &iAccount = iMyVariable;

ตัวอย่าง 2: ในประโยคต่อไปนี้ & operator ใช้หา Address ของตัวแปร

cout << “Address of iMyVariable = “ << &iMyVariable

วันจันทร์ที่ 10 พฤษภาคม พ.ศ. 2553

Fibonacci in Assembly

INCLUDE Irvine32.inc

          .data

         .code

main PROC

          mov ecx,7

          mov eax,0

          mov ebx,1

          mov edx,eax

          add edx,ebx

          call writedec

          call crlf

          xchg eax,ebx

          call writedec

          call crlf

          xchg ebx,eax

          mov eax,edx

          call writedec

          call crlf

l1:     mov edx,ebx

          add edx,eax

          mov eax,edx

          call writedec

          call crlf

          xchg ebx,eax

          loop l1

          exit

main ENDP

          END main

วันพฤหัสบดีที่ 15 เมษายน พ.ศ. 2553

Pointer กับ Array

pointer กับ array ในภาษา c++ จะมีความใกล้ชิดกันมาก ตัวอย่างเช่น เมื่อประกาศตัวแปรarray ชนิดหนึ่งขึ้นมา ชื่อตัวแปรนั้น ก็คือ address ที่ชี้ไปยังดัชนีแรกสุด โดยที่เราไม่ต้องใช้ operator & วางหน้าตัวแปรarray เลย และถ้าเราเพิ่มจากเดิมไปอีก1ก็จะได้เป็น address ใหม่ที่จะชี้ตำแหน่งถัดไป ลองมาดูตัวอย่างกันคับ

int x[5] = {12,14,16,18,20};

cout<<x<<endl; //พิมพ์ค่า address ของ array ณ ตำแหน่งที่ 0 ออกมา

cout<<x+1<<endl; //เพิ่มค่าindexเข้าไปอีก1 จะทำให้ address เพิ่มไปอีก 1 ตำแหน่ง

วันอังคารที่ 13 เมษายน พ.ศ. 2553

Decimal to Binary

#include <iostream>

#include <string>

using namespace std;

string compute(int n){

     if(n==0)

          return "";

     else if(n%2==0)

          return compute(n/2)+"0";

     else

          return compute(n/2)+"1";

}

int main(){

     cout<<compute(14)<<endl;

     return 0;

}

วันพุธที่ 7 เมษายน พ.ศ. 2553

Binary to Decimal

#include <iostream>

#include <string>

using namespace std;

int compute(string s){

     if(s=="")

          return 0;

     else if(s.at(s.length()-1)=='1')

          return compute(s.erase(s.length()-1,1))*2+1;

     else

          return compute(s.erese(s.length()-1.1))*2+0;

}

int main(){

     cout<<compute("1110010")<<endl;

     return 0;

}

วันจันทร์ที่ 5 เมษายน พ.ศ. 2553

Pointerกับการจองหน่วยความจำ

เราจะจองหน่วยความจำเมื่อเราต้องการให้Programของเราทำงานแบบ Dynamic แต่ถ้าเรากำหนดขนาดของตัวแปรแบบArrayเอาไว้ล่วงหน้าแล้ว ถ้าเวลาจริงเราใช้ไม่พอ ก็จะขยายขนาดของArrayไม่ได้เลย จึงต้องหันไปใช้ LinkedList แทน การจองพื้นที่หน่วยความจำใน c และ c++ ก็จะต่างกันหน่อยนึง ลองมาดูกันคับ

  • ภาษา c จะใช้ function พวก malloc,calloc ในการจองหน่วยความจำและใช้คำสั่ง free ในการคืนหน่วยความจำให้กับระบบ
  • ภาษา c++ จะใช้คำสั่ง new ในการจองหน่วยความจำ และ delete ในการคืนหน่วยความจำให้กับระบบ

เราลองมาดูตัวอย่างกันนะคับ

int *num;

*num = 72;

การที่จู่ๆเราเอา pointer ของเราไปไปค่า72แบบนี้ทำไม่ได้นะคับ เนื่องจาก pointer ไม่สามารถนำไปเก็บค่าแบบนี้ได้โดยตรง เราก็เลยจะต้องจองพื้นที่ในหน่วยความจำให้มันกันก่อน แล้วจะสามารถนำมาเก็บค่า72ได้คับ

int *num;

num = new int;

*num=72;

cout<<*num<<endl;

delete num;

เมื่อเราจองหน่วยความจำได้แล้ว ข้อมูลในช่องนั้นสามารถนำไปใช้ในโปรแกรมของเราได้ ส่วนมากในการเขียนโปรแกรมทั่วๆไป เราไม่จำเป็นต้องประกาศตัวแปรPointer และจองหน่วยความจำแบบนี้เสมอไป เราก็แค่ประกาศตัวแปรแบบธรรมดาและเก็้บค่าไปเท่านั้น แต่ในการทำงานของ LinkedList นั้นจะต่างจาก array ตรงที่ linked list ไม่ได้จองหน่วยความจำทีเดียวแบบ array เช่น

int number[40];

array number ตัวนี้จะเเก็บค่าได้ 40 ตัว ขยายก็ไม่ได้ด้วย แต่ถ้าเราเปลี่ยนมาให้ LinkedList เราจะต้องจองหน่วยความจำให้กับข้อมูลที่ต้องการจะเก็บ และถ้าจะเพิ่มข้อมูลเข้าไปใน Linked List อีก ก็จองหน่วยความจำให้กับข้อมูลใหม่ และก็เชื่อมต่อเข้าไปอีกเรื่อยๆ

วิธีการของ Linked List นี้จะข่วยไม่ให้เราต้องจองหน่วยความจำเอาไว้มากมาย และจะเก็บข้อมูลเท่าที่เราต้องการจะเก็บเท่านั้น เมื่อเราลบข้อมูลในช่องใดออกไปก็จะไม่มีช่องว่างเหลือเหมือนกับarray

วันอาทิตย์ที่ 4 เมษายน พ.ศ. 2553

Pointer to Structures

การใช้ pointer ชี้ไปที่ข้อมูลชนิด structure เป็นที่นิยมมาก โดยเราจะใช้ตัวดำเนินการ -> (arrow operator) ในการอ้างถึงฟิลด์ต่างๆ เราลองมาพิจารณาโครงสร้างชนิดข้อมูลนี้กันดูคับ

struct database {

     int key;

     int big_array[25];

}my_data;

เป็นการประกาศข้อมูลชนิดโครงสร้างโดยใช้ชื่อ database แล้วก็กำหนดให้ my_data เป็นตัวแปรชนิดนี้ แล้วก็จะประกาศ pointer ชื่อ my_pointer ให้เป็นตัวแปร pointer ชนิดโครงสร้างนี้

struct database *my_pointer;

เราสามารถกำหนดให้ pointer ชื่อ my_pointer ชื่อไปยังตัวแปร my_data ได้ดังนี้

my_pointer = &my_data;

ต่อจากนี้เราก็จะสามารถอ้างถึงฟิลด์ต่างๆใน my_data เช่น my_data.key โดยใช้ตัวดำเนินการ ->

my_pointer -> key = 5;   // ใช้เช่นเดียวกับ my_data.key

วันเสาร์ที่ 3 เมษายน พ.ศ. 2553

Pointers to Pointers

Pointer ชี้ไปที่ Pointer ต่างๆ

ใน c เราสามารถกำหนดตัวแปรpointerให้ชี้ไปยังตัวแปรpointerตัวอื่นๆได้อีก การกำหนดให้ pointer ชี้ไปยัง pointer อื่นๆใน C จะใช้เครื่องหมาย ** ข้างหน้าตัวแปร เพื่อระบุ pointer ชี้ไปยัง pointer เช่น

char **char_ptr;

จำนวนของ * ทั้งหมดที่เขียนไว้ข้างหน้าตัวแปรเพื่ออ้างอิงค่าที่pointerชื้ เรียกว่า Level of indirection ของตัวแปร pointer เพื่อใช้ระบุจำนวนตัวแปรpointerที่ชี้ต่อเนื่องกันไปจนถึงแหล่งข้อมูล

ตัวอย่างโปรแกรมที่มีการใช้ pointer ชี้ไปยัง pointer

int int_data = 9;

int *int_ptr1;

int **int_ptr2;

int ***int_ptr3;

int_ptr1=&int_data;

int_ptr2=&int_ptr1;

int_ptr3=&int_ptr2;

วันศุกร์ที่ 2 เมษายน พ.ศ. 2553

Pointer คืออะไร

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

ถ้ายังงงๆอยู่ก็ขออธิบายเป็นภาษาคนละกันนะคับ คือว่า เวลาเราจะรับ-ส่ง ตัวแปรในfunction เราก็มักจะให้มัน return ค่าออกมา แล้วก็มีตัวแปรไปรับค่านั้น แต่ถ้าเรามาใช้ pointer เนี้ย เราก็สามารถไปแก้ที่ address ของมันได้เลย ไม่ต้องมารอรับค่า return อยู่!!

ความสะดวกของมันก็คือ ถ้าในกรณีที่เราต้องการค่าreturnจากfunction เพียงตัวเดียวก็คงจะเหมือนๆกับตัวแปรทั่วไป แต่ถ้าเป็น function ที่มีการ return หลายๆตัวแปรล่ะ ถ้าเราใช้ array แล้ว return ออกมาก็ได้ผลเหมือนกันแหละคับแต่ว่าถ้ามันเป็นคนละชนิดกันละ อิๆๆ

การกำหนดตัวแปร Pointer

การกำหนดตัวแปร Pointer จะคล้ายกับการกำหนดตัวแปรชนิดต่างๆ เพียงแต่ต้องมีเครื่องหมาย *หน้าชื่อตัวแปร ดังนี้

int *pt;

ในที่นี้กำหนดให้ pt เป็นตัวแปร Pointer ซึ่งเก็บ Address ของตัวแปรชนิด Integer

ในเรื่อง Pointer จะมีเครื่องหมายอยู่ 2 ชนิดคือ * และ & โดยเครื่องหมายแต่ละตัวจะมีหน้าที่ดังนี้

  • * จะเป็นการอ้างอิงถึงข้อมูลที่อยู่ใน address โดย address นี้จะเก็บอยู่ในตัวแปรแบบ Pointer เช่นในตัวอย่างคือ pt
  • & จะให้ค่า address ของตัวแปรที่อยู่หลังเครื่องหมายนี้

ตัวอย่าง

#include <iostream>

using namespace std;

int main() {

int *pt,a,b;

a=20;

pt=&a;

b=*pt;

cout<<"pt's address = "<<&pt<<endl;

cout<<"assign a = 20"<<endl;

cout<<"address of a = "<<&a<<endl;

cout<<"store address of a to pt,pt = "<<&a<<endl;

cout<<"assing b = data in address of pt(*pt),b = "<<b<<endl;

return 0;

}

***ข้อจำกัดในการใช้ตัวดำเนินการ&

- ห้ามใช้กับตัวคงที่

var_address = &100;

- ห้ามใช้กับนิพจน์ที่มีตัวดำเนินการ + และ /

int var1 = 100;

var_address = &(var1 + 10);

- ห้ามใช้กับตัวแปร register

register reg1;

var_address = &reg1;   //ตัวแปร register จะใช้ใน CPU โดยตรง

*ตัวแปรชนิด register ไม่ต้องมี addressที่หน่วยความจำสำหรับเก็บค่า