วันพุธที่ 1 มิถุนายน พ.ศ. 2559

เริ่มต้นใช้งานอาดุยโน่ : บทที่ 4 ตัวแปร


ตัวแปร (variable)

ในทางโปรแกรมมิ่ง  คือข้อมูล หรือปริมาณ ที่เก็บไว้ในหน่วยความจำ  ซึ่งหน่วยความจำนั้นเป็นระบบดิจิตอล (จะกล่าวถึงในภาคผนวก)  ดังนั้น จึงมีการตีความด้วยระบบเลขฐานสอง แต่เราสามารถใช้เลขฐาน 10 ในการแสดงถึงจำนวนได้ เพื่อความสะดวกในการเขียนโปรแกรม


ตัวแปรนั้นมีหลายประเภท แบ่งตามขนาด และรูปแบบข้อมูล

ขนาดของตัวแปร นับเป็นไบต์ (byte) แสดงถึงขนาดของหน่วยความจำที่ใช้สำหรับ
ตัวแปรนั้นๆ 1 ตัว


ประเภทของตัวแปรเบื้องต้น

char ขนาด 1 byte ใช้เก็บจำนวนเต็ม และอักขระ สามารถเก็บค่าตั้งแต่ -128 ถึง 127
int ขนาด 2 byte ใช้เก็บจำนวนเต็ม  สามารถเก็บค่าตั้งแต่ -32768 ถึง 32767
long ขนาด 4 byte ใช้เก็บจำนวนเต็ม สามารถเก็บค่าตั้งแต่ -2,147,483,648 ถึง 2,147,483,647
float ขนาด 4 byte ใช้เก็บทศนิยม สามารถเก็บค่าตั้งแต่ -3.4028235*10^38 ถึง 3.4028235*10^38



การใช้งานตัวแปร

การใช้งานตัวแปรนั้น โดยส่วนใหญ่จะใช้เพื่อเก็บข้อมูลไว้เพื่อนำไปแสดงผล หรือนำไปคำนวณ  ซึ่งจะพิจารณาจากลักษณะของข้อมูลที่ใช้เก็บ และช่วงของข้อมูล เพื่อนำไปเลือกชนิดของตัวแปรให้มีความเหมาะสม
ตัวแปรในทางโปรแกรมมิ่งนั้น คล้ายกับทางคณิตศาสตร์ คือสามารถเรียกใช้ชื่อ เพื่อแทน
จำนวนหนึ่งๆ และสามารถปรับเปลี่ยนค่าได้


การประกาศตัวแปร

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


1. การประกาศตัวแปรแบบไม่กำหนดค่าตั้งต้น

ชนิดของตัวแปร      ชื่อของตัวแปร ;

2. การประกาศตัวแปรแบบกำหนดค่าตั้งต้น

ชนิดของตัวแปร  ชื่อของตัวแปร  = ค่าของตัวแปร ;




ตัวอย่าง


ข้อสังเกต

1. ภาษาซี เป็นภาษาที่สนใจตัวพิมพ์เล็ก - พิมพ์ใหญ่ (case - sensitive)  ดังนั้น ชนิดของตัวแปร จะต้องพิมพ์ตามตัวอย่างเท่านั้น เช่น int  จะไม่สามารถพิมพ์เป็น Int , INT ได้  นอกจากนี้ ชื่อของตัวแปร ที่เขียนไม่เหมือนกัน เช่น a กับ A  จะไม่ถือว่าเป็นตัวเดียวกัน


2. การเว้นวรรค ระหว่างชนิดของตัวแปร และชื่อของตัวแปร เป็นสิ่งที่จำเป็นต้องมี แต่จะเว้นกี่ครั้งก็ได้ นอกนั้น จะเว้น หรือไม่เว้นก็ได้ เช่น int a=5;  เป็นต้น

3.ไม่สามารถประกาศตัวแปรซ้ำชื่อเดิมได้

4.การกำหนดค่าให้ตัวแปร ต้องกำหนดให้สอดคล้องกับชนิดของตัวแปรที่ประกาศไว้

5. ชื่อของตัวแปร สามารถใช้ได้เฉพาะตัวอักษรภาษาอังกฤษ(ทั้งพิมพ์เล็ก พิมพ์ใหญ์)  เครื่องหมายอันเดอร์สกอร์ และตัวเลขเท่านั้น ไม่สามารถใช้อักขระพิเศษอื่นๆได้ (รวมถึงห้ามเว้นวรรคในชื่อตัวแปร) และห้ามใช้ตัวเลขนำหน้าชื่อ นอกจากนี้ ยังมีคำสงวนที่ห้ามตั้งเป็นชื่อตัวแปร 


คำสงวนในภาษา C และ C++
คือคำที่ไม่สามารถใช้ตั้งเป็นชื่อของตัวแปรได้  ส่วนใหญ่คือคำที่ซ้ำกับชื่อของคำสั่ง หรือชื่อของชนิดตัวแปร หรือชื่อที่สามารถตีความไปในความหมายอื่นได้  ได้แก่
auto        break    case       char        const        continue    default    do     
double     else      enum      extern     float           for            goto       if     
int           long      register    return     short         signed      sizeof    static  
struct      switch   typedef    union      unsigned   void          volatile   while
asm                    bool                catch        class       const_cast   delete     
dynamic_cast      explicit            false         friend       inline            mutable     
namespace          new                operator    private      protected      public    
reinterpret_cast    static_cast      template    this          throw           true  
try                       typeid             typename  using        virtual          wchar_t


Tool Tip !!!    หากเราตั้งชื่อตัวแปรแล้วมีสีปรากฏขึ้นมา หมายความว่าชื่อนั้นไม่สามารถใช้ได้ เช่น


ในกรณีเราตั้งชื่อตัวแปรผิด โปรแกรมจะขึ้นแจ้งเตือน  ถ้าหากโปรแกรมขึ้นแจ้งเตือนในลักษณะนี้ ก็ให้ลองใช้ชื่ออื่นแทน






ขอบเขตขอบตัวแปร (Variable scope)


คือขอบเขตที่การประกาศตัวแปรนั้นมีผล  ก็คือขอบเขตที่เราสามารถเรียกใช้ หรือปรับเปลี่ยนค่าของตัวแปรที่เราประกาศ แบ่งเป็นสองแบบคือ Global และ Local ดังรูป

แสดงตำแหน่งในการประกาศ และขอบเขตของตัวแปร

1. Global scope คือการประกาศตัวแปรไว้เหนือฟังก์ชันแรก (ในที่นี้คือ setup)  สังเกตว่าจะประกาศอยู่บนสุด และอยู่นอกฟังก์ชัน (โดยปกติใช้สำหรับการประกาศ (declaration) ไม่สามารถเขียนชุดคำสั่งได้) ทำให้ตัวแปรที่ประกาศแบบ Global สามารถเรียกใช้ได้จากทุกๆทีในโปรแกรม

 2. Local scope คือการประกาศตัวแปรไว้นั้นขอบเขตของฟังก์ชัน หรือก็คือประกาศไว้ภายในวงเล็บปีกกาของฟังก์ชัน   การประกาศแบบนี้จะทำให้ตัวแปรสามารถใช้ได้เฉพาะในฟังก์ชันนั้น ไม่สามารถใช้งานในฟังชั่นอื่นได้

นอกจากลักษณะการประกาศแล้ว ขอบเขตของตัวแปรยังเป็นไปตามการประมวลผลโปรแกรม ซึ่งจะรันจากบนลงล่าง ทำให้จะสามารถเริ่มใช้ตัวแปรนั้นได้ในบรรทัดล่างถัดจากการประกาศตัวแปร เท่านั้น


การกำหนดหรือปรับเปลี่ยนค่าตัวแปร     (assignment operator)

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

การปรับเปลี่ยนค่าตัวแปรจะใช้คำสั่งดังนี้



ชื่อของตัวแปร  = ค่าของตัวแปร ;

ตัวอย่าง


ซึ่งการกำหนดคือตัวแปรนั้น จะใช้ตัวดำเนินการกำหนดค่า (assignment operator) ซึ่งก็คือเครื่องหมาย "=" นั่นเอง  ซึ่งตัวดำเนินการในการกำหนดค่านี้ ไม่เหมือนกับเครื่องหมายเท่ากับในระบบสมการ เพราะตัวดำเนินการนี้ จะทำการส่งค่าจากด้านขวาไปยังตัวแปรที่อยู่ด้านซ้าย


ข้อสังเกต
1.จะสามารถกำหนดค่าของตัวแปรได้ภายในขอบเขตฟังชั่นเท่านั้น
2.ตัวแปรที่ประกาศแบบไม่ระบุค่าเริ่มต้น ควรมีการอัพเดทค่าก่อนเรียกใช้
3.ด้านซ้ายของ "=" จะต้องเป็นตัวแปรเท่านั้น

การเรียกใช้ตัวแปร

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


ตัวอย่าง


จากโค๊ดตัวอย่าง คือการกำหนดค่าตัวแปร b ให้มีค่าเท่ากับค่าของตัวแปร a  เมื่อตัวแปร a มีค่าเท่ากับ 5 ดังนั้นคำสั่ง b = a; จึงมีค่าเท่ากับคำสั่ง b = 5;  นั่นเอง

การแสดงค่าตัวแปรบน  Serial monitor

เราสามารถใช้งานคำสั่ง(ฟังก์ชัน) Serial.print หรือ Serial.println ได้ตามปกติ แต่ในหนึ่งคำสั่งนั้น จะสามารถแสดงตัวแปรเพียงหนึ่งตัวเท่านั้น และห้ามมีข้อความอื่น แต่เราสามารถใช้วิธีปริ้นต่อกันได้

ตัวอย่าง

ตัวอย่างการแสดงค่าตัวแปรผ่านซีเรียลมอนิเตอร์





ตัวดำเนินการทางคณิตศาสตร์(Arithmetic Operators)

ในเบื้องต้นที่ควรรู้คือ + , - ,* , /   ใช้ในการคำนวณทางคณิตศาสตร์ต่างๆ ซึ่งสามารถใช้ได้กับทั้งค่าคงที่และตัวแปรดังรูป

ตัวอย่าง
**ข้อสังเกต** การเว้นวรรค เว้นบรรทัดไม่มีผลกับตัวดำเนินการ

จากตัวอย่างด้านบน  โปรแกรมจะดำเนินการทางคณิตศาสตร์ก่อน จากนั้นจึงนำค่าที่ได้ ซึ่งเป็นผลลัพธ์ของการคำนวณ ไปอัพเดทค่าตัวแปร ดังนั้นลองพิจารณาตัวอย่างด้านล่าง



จากที่กล่าวไว้ข้างต้นว่า "โปรแกรมจะดำเนินการทางคณิตศาสตร์ก่อน" ดังนั้น การอัพเดพค่า a จึงยังไม่เกิดขึ้น ดังนั้น ค่า a จึงยังเป็นค่าเดิมนั่นคือ 3 ดังนั้นจะได้ว่า a = 3 + 5;  จะได้ a เท่ากับ 8



นอกจากนี้ เรายังสามารถใช้ตัวดำเนินการมากกว่าหนึ่งตัวต่อการกำหนดค่าตัวแปรหนึ่งครั้งได้ เช่น





โดยโปรแกรมจำคำนวณจากเครื่องหมาย * ,  /   ก่อน และคำนวณจากซ้ายไปขวา นั้นคือ

a = 1*2   +   4*5+6/3*2 
a =  2    +   20   +   2 * 2 
a =  2    +   20   +   4
a = 26

ซึ่งตรงกับผลที่แสดงผ่านซีเรียลมอนิเตอร์  หรือเราสามารถใส่วงเล็บ "( )" เพื่อกำกับในการคำนวณได้ ซึ่งใช้หลักการเดียวกับเครื่องหมายทางคณิตศาสตร์  โดยเราสามารถใส่วงเล็บได้อย่างอิสระ ภายในบริเวณที่เป็นค่าของตัวแปร ซึ่งก็หรือระหว่างเครื่องหมายเท่ากับ(=) และเครื่องหมายเซมิโคล่อน (;) โดยจะต้องใส่ให้ครบคู่ และสามารถใส่ได้เฉพาะวงเล็บกลมเท่านั้น



**ข้อควรระวัง**

1.เกี่ยวกับการหารตัวแปรประเภท int จะเป็นการหารแบบปัดเศษทิ้ง เพราะโครงสร้างของตัวแปรชนิดนี้ไม่สามารถเก็บตัวแปรทศนิยมได้

2.ถ้าค่าของตัวแปรถูกกำหนดให้มีค่ามากกว่า หรือน้อยกว่าช่วงที่ตัวแปรสามารถเก็บค่าได้  ค่าที่เก็บไว้ในตัวแปรจะไม่ถูกต้อง

3.ถ้าตัวแปรถูกเพิ่ม หรือลดเนื่องจากการบวก ลบ หรือคูณ จนเกินช่วงที่ตัวแปรสามารถเก็บค่าได้ จะเกิดเหตุการณ์โอเวอร์โฟลว์ คือการที่ค่านั้นเด้งไปฝั่งตรงข้าม เช่น a = 32767 + 1;  จะทำให้ค่าของ a เด้งไปเป็นค่ามากสุดของฝั่งลบ นั่นคือ -32768 เป็นต้น ทำให้ค่าของตัวแปรไม่ถูกต้อง

4.การกำหนดค่าตัวแปรด้วยตัวแปรคนละประเภทกัน อาจทำให้ข้อมูลผิดพลาดได้หลายเหตุการณ์ เช่น
ถ้าค่าของตัวแปรที่ใช้มีค่ามากกว่าคำที่ตัวแปรที่เราจะกำหนดค่ารับได้ จะเกิดตามข้อ 2
ถ้าค่าของตัวแปรทั้งสองเป็น float และ int จะเกิดการปัดเศษทิ้ง

5.การกำหนดค่าคงที่ประเภท float จะต้องใส่ทศนิยมทุกครั้ง ไม่งั้นจะถูกดำเนินการแบบจำนวนเต็ม คือปัดเศษ

6.เมื่อคำสั่ง Serial.print หรือ Serial.println ในการปริ้นค่าของตัวแปร float จะแสดงทศนิยมแค่ 2 ตำแหน่ง  แต่เราสามารถเพิ่มได้ดังตัวอย่าง


7.ถ้าเราสั่งปริ้นตัวแปรประเภท char จะปรากฏเป็นตัวอักษรขึ้นมาแทน ตามรหัสแอสกี้ดังตัวอย่าง


เพราะโดยปกติ ตัวแปรประเภท char มีไว้เก็บตัวอักษร โดยจะแทนตัวอักษรภาษาอังกฤษด้วยตัวเลข ตามรหัสแอสกี้  เช่นรหัสของตัว "x" ก็คือ 120 เป็นต้น  แต่เราสามารถเลือกได้ว่าจะให้แสดงค่าในลักษณะไหน ด้วยการระบุประเภทของข้อมูลที่ต้องการหลังชนิดตัวแปร เช่น DEC เป็นเลขฐานสิบ BIN เป็นเลขฐานสอง และ HEX เป็นเลขฐาน16 เป็นต้น




การเปลี่ยนชนิดของตัวแปร


เราสามารถเปลี่ยนชนิดของตัวแปรจากชนิดหนึ่ง ไปเป็นอีกชนิดหนึ่งได้โดย

ชนิดตัวแปรที่ต้องการ (ชื่อของตัวแปรที่จะแปลง)


ตัวอย่าง




ภาคผนวก %(modulo)

เป็นตัวดำเนินการทางคณิตศาสตร์ตัวหนึ่ง ลักษณะการใช้งานคล้ายกับการหาร ( / ) แต่ค่าที่ได้ จะเป็นเศษของการหารแทน เช่น 5%3  จะได้ 2 เพราะ 5 / 3  จะได้ 1 เศษ 2   เป็นต้น และในกรณีที่หารลงตัว เช่น 6%3 จะได้ 0

ภาคผนวก Unsigned

unsigned เป็นการประกาศตัวแปรอีกวิธีหนึ่งใช้กับตัวแปรประเภทจำนวนเต็ม ได้แก่ char int long  โดยตัวแปรที่เก็บจะไม่มีจำนวนซีกลบ ทำให้ค่าสูงสุดที่เก็บได้ของตัวแปรนั้นๆเพิ่มขึ้น   โดย

unsigned char เก็บค่าตั้งแต่ 0 - 255
unsigned int เก็บค่าตั้งแต่ 0 - 65,535
unsigned long เก็บค่าตั้งแต่ 0 - 4,294,967,295
สำหรับค่าที่เก็บได้ในตัวแปรตัวแปรจำนวนเต็มนั้น มีวิธีการคำนวณโดยคิดตามขนาดของตัวแปร เช่น char มี 8-bit  เมื่อเราแทนค่าทุก bit ด้วย 1 จะได้ 1111 1111  ซึ่งเมื่อแปลงเป็นฐาน 10  จะได้ 255  ดังนั้นจะเก็บค่าได้ 0 - 255 ในกรณีที่ไม่มีจำนวนติดลบ 


สำหรับการติดลบนั้น  ขอให้ผู้อ่านพิจารณาดังนี้

เมื่อตัวแปร char มีค่าเป็น 0 ( 0000 0000 )  แล้วเราลดค่าลงหนึ่ง  ในกรณีที่ไม่มีจำนวนติดลบ จะมีค่าเท่าใด.....??

คำตอบคือ 255 เพราะเกิดการโอเวอร์โฟลว์ ซึ่ง 255 = 1111 1111 ในเลขฐานสอง  เมื่อเราลดค่าลงเรื่อยๆที่ละ 1 ค่าจะเป็น 254 ,253 ,252

แล้วถ้าจำนวนนั้นมีค่าติดลบหละ ถ้าเราลดค่าจาก 0 ลงหนึ่ง จะได้ค่าเท่าไหร่...?
ไม่ยากเลย คำตอบนั้นคือ -1 เมื่อลดลงเรื่อยๆจะเป็น -2 ,-3 ,-4 ตามลำดับ

เมื่อเรานำค่าจากทั้งสองฝั่งมาเทียบกัน จะได้ดังนี้



ดังนั้น ถ้าเรามองค่า 255 ให้เป็นค่า -1 จะทำให้คอนโทรลเลอร์ (บอร์ดอาดุยโน่) ใช้ตัวดำเนินการบวกลบแบบเดียวกันได้

เมื่อเรานำค่าตัวแปรที่มีเครื่องหมายมาเขียนตามเลขฐานสองจะได้


จึงเป็นที่มาของค่าต่ำสุดสูงสุดของ char สำหรับตัวแปรชนิดอื่นๆก็จะอยู่ในทำนองเดียวกัน ดังนั้นจึงสรุปได้ว่า
1. ตัวแปรแบบ unsigned  ค่าต่ำสุด คือ 0 ค่าสูงสุดคือ (2^n) - 1
2. ตัวแปรแบบ ไม่ unsigned ค่าต่ำสุดคือ -(2^(n-1)) ค่าสูงสุดคือ (2^(n-1))-1
โดยที่ n เป็นขนาดของหน่วยความจำ (bit)



3 ความคิดเห็น: