วันจันทร์ที่ 19 กันยายน พ.ศ. 2554

อาร์เรย์ (Array)

อาร์เรย์ (Array)
จากเนื้อหาที่ผ่านมาได้แนะนำการกำหนดตัวแปรเพื่อใช้ในการเก็บข้อมูล ซึ่งตัวแปรเหล่านั้นมีลักษณะเป็นข้อมูลเดียว (Simple data type) ซึ่งมีความหมายว่าตัวแปรหนึ่งตัวจะสามารถเก็บข้อมูลได้เพียงข้อมูลเดียว เช่น
VAR X : integer;
จะมีความหมายว่า ตัวแปร X เป็นตัวแปรที่เก็บข้อมูลเลขจำนวนเต็ม ซึ่ง X จะสามารถเก็บเลขจำนวนเต็มได้ค่าเดียว ถ้าหากเราต้องการที่จะเก็บ ข้อมูลที่เป็นชนิดเดียวกันหลายๆ จำนวน เราก็จำเป็นจะต้องจองตัวแปรชนิดเดียวกันเป็นจำนวนหลายๆ ตัวให้เท่ากับจำนวนที่ต้องการด้วย ซึ่งตัวแปรแต่ละตัวก็จำเป็นจะต้องมีชื่อที่แตกต่างกันด้วยเช่น ถ้าต้องการจองตัวแปรชนิด เลขจำนวนเต็มเป็นจำนวน 10 ตัว โดยใช้วิธีดังที่กล่าวมาจะต้องทำดังนี้
VAR X1, X2, X3, X4, X5, X6, X7, X8, X9, X10 : integer;
จะเห็นว่าว่าวิธีการจองตัวแปรแบบนี้เป็นวิธีที่ไม่สะดวก เพราะถ้าหากมีตัวแปรเพิ่มขึ้นมากๆ เช่น 100 ตัวก็จะต้องพิมพ์ชื่อตัวแปรไปเรื่อยๆ จนครบจำนวน 100 ตัวเช่นกัน และถ้าหากสังเกตให้ดีแล้วการจองตัวแปรในลักษณะนี้จะก่อให้เกิดความยุ่งยากในการเขียนโปรแกรมด้วย
ตัวแปรข้อมูลชนิดโครงสร้าง (Structured data type) ซึ่งลักษณะตัวแปรข้อมูลประเภทนี้เกิดจากการนำเอาข้อมูลชนิดพื้นฐานหลายตัวมาประกอบรวมกันตามแต่ที่ผู้ใช้จะกำหนด เช่น ข้อมูลชนิดอาร์เรย์ ข้อมูลชนิดเรคอร์ด ข้อมูลชนิดเซต และข้อมูลชนิดไฟล์ เป็นต้น ซึ่งการนำข้อมูลหลายๆตัวมารวมกันจะสามารถแก้ไขความยุ่งยากที่เกิดขึ้นจากการมีตัวแปรปริมาณมาก ๆ ได้ คือ มีตัวแปรทั้งสิ้น 100 ตัว และต้องการรวมตัวแปร 100 ตัวนี้เข้าด้วยกันเป็นตัวแปรข้อมูลชนิดโครงสร้างตัวเดียว เช่นนี้ สามารถทำได้โดยตัวแปรชนิดโครงสร้างที่เรียกว่า อาร์เรย์ (ARRAY)
อาร์เรย์ เป็นข้อมูลแบบโครงสร้างชนิดหนึ่ง ซึ่งประกอบขึ้นจากข้อมูลหลายๆ ตัวรวมเข้าด้วยกันเป็นกลุ่ม โดยข้อมูลแต่ละตัวในกลุ่มถูกเรียกว่าเอลิเมนต์ (Element) และแต่ละเอลิเมนต์จะต้องเป็นข้อมูลชนิดเดียวกัน การอ้างถึงข้อมูลจะใช้ตัวแปรชื่อเดียว ซึ่งจะหมายถึงชื่อของกลุ่ม และสามารถอ้างถึงข้อมูลแต่ละเอลิเมนต์ในกลุ่มได้โดยใช้ดัชนี (Index) ต่อท้ายหลังชื่อตัวแปรของกลุ่ม ดัชนีนี้จะเป็นตัวบ่งบอกถึงลำดับที่ของเอลิเมนต์ ลักษณะของดัชนีที่เราสามารถเข้าใจได้ง่ายที่สุดก็คือ ตัวเลข

การประกาศและอ้างถึงข้อมูลชนิดอาร์เรย์
จากส่วนประกาศตัวแปรในการจองตัวแปรจำนวน 10 ตัวเพื่อใช้ในการเก็บข้อมูลที่เป็นเลขจำนวนเต็ม ตามตัวอย่างที่ผ่านมานั้น เราจองตัวแปร X1,X2,X3,X4,X5,X6,X7,X8,X9,X10 เป็นตัวแปรชนิดจำนวนเต็ม ซึ่งถ้าหากเราเปลี่ยนมาใช้ตัวแปรชนิดโครงสร้างที่เป็นอาร์เรย์ก็สามารถทำได้ดังต่อไปนี้
VAR X : ARRAY [1..10] OF integer;
จากส่วนประกาศตัวแปรข้างบนพบว่าตัวแปร X เป็นตัวแปรแทนกลุ่มข้อมูลชนิดเลขจำนวนเต็ม โดยจำนวนของเอลิเมนต์ให้ดูจากดัชนี ซึ่งการกำหนดดัชนีของข้อมูลตามตัวอย่างถูกกำหนดให้อยู่ในรูปของช่วงย่อย (Subrange) โดยช่วงย่อยนี้ประกอบด้วย ค่าเริ่มต้น เครื่องหมาย ".." และค่าสิ้นสุด ทั้งหมดนี้จะอยู่ภายในเครื่องหมาย "[" และ "]" ในที่นี้คือ[1..10] ซึ่งมีความหมายว่า ดัชนีของตัวแปรอาร์เรย์ X เริ่มต้นจากเลข 1จนถึงเลข 10 รวมจำนวนทั้งสิ้น 10 ตัว และเราสามารถอ้างถึงข้อมูลแต่ละเอลิเมนต์ได้ดังนี้
X[1] ,X[2] ,X[3] ,X[4] ,X[5] ,X[6] ,X[7] ,X[8] ,X[9] ,X[10]
ภาพแสดงลักษณะโครงสร้างของตัวแปร X ซึ่งเป็น อาร์เรย์ ของเลขจำนวนเต็ม
VAR
X : ARRAY [0..99] OF real;
n : integer;
BEGIN {main program}
FOR n := 0 TO 99 DO
X[n] := n+1;
END.
จากตัวอย่างจะพบว่า X เป็นตัวแปรโครงสร้างชนิดอาร์เรย์ของ เลขจำนวนจริง โดยมี ดัชนีเริ่มต้นจาก 0 ถึง 99 รวมทั้งสิ้นเป็นเลขจำนวนเต็มทั้งหมด 100 จำนวน ซึ่งทำให้เราทราบว่าดัชนีของข้อมูลไม่จำเป็นที่จะต้องเริ่มต้นด้วย 1 ซึ่งในที่นี้เริ่มต้นด้วย 0 และจากส่วนของ main program ซึ่งทำการกำหนดค่าข้อมูล ตั้งแต่ 1 ถึง 100 ให้กับตัวแปร X ตั้งแต่ ดัชนี ที่ 0 ถึงดัชนีที่ 99 จะเห็นว่าเราสามารถใช้ตัวแปร n เป็นดัชนีเพื่อทำการชี้ตำแหน่งเอลิเมนต์ของตัวแปร X
TYPE lettertype = ARRAY ['A'..'Z'] OF Integer;
VAR
letter : lettertype;
index : 'A'..'Z';
BEGIN {main program}
FOR cindex := 'A' TO 'Z' DO letter[cindex] := 0;
END.
จากตัวอย่างทำให้เราทราบว่าดัชนีของอาร์เรย์อาจจะเป็นชนิดข้อมูลอิสระ ก็ได้ ซึ่งในที่นี้ดัชนีของตัวแปรอาร์เรย์ที่ชื่อว่า letter นี้ก็คือ ตัวอักษร 'A' ถึง 'Z'
TYPE
DayOfWeek = (sun, mon, tue, wed, thu, fri, sat);
day = ARRAY [DayOfWeek] OF integer;
VAR
day : Dday;
จากตัวอย่าง จากส่วนประกาศจะพบว่าเราสามารถกำหนดชนิดข้อมูล ขึ้นมาใหม่มีลักษณะเป็นแบบแจงนับ (enumerated data type) และใช้ชนิดของข้อมูลใหม่นี้เป็นดัชนีของอาร์เรย์ได้ ซึ่งจะทำให้เกิดเอลิเมนต์ดังต่อไปนี้
day[sun],day[mon],day[tue],day[wed], day[thu],day[fri],day[sat]
TYPE
ArrayOfChar = ARRAY [BYTE] OF char;
VAR
Message : ArrayOfChar;
ในตัวอย่างพบว่าสามารถใช้ชนิดของตัวแปร บางชนิดในการกำหนดดัชนีของตัวแปรอาร์เรย์ได้ชนิดข้อมูลที่ใช้กำหนดเป็น ดัชนีของข้อมูลชนิดอาร์เรย์ได้จะต้องเป็นข้อมูลแบบเรียงลำดับ (Ordinal Type) เท่านั้น จากตัวอย่าง เราได้ตัวแปรที่ชื่อ message เป็นอาร์เรย์ของตัวอักษร โดยมีจำนวนตัวอักษรหรือเอลิเมนต์ทั้งหมด 256 ตัวอักษร
ชนิดข้อมูลที่กำหนดให้กับเอลิเมนต์ในอาร์เรย์จะเป็นข้อมูลชนิดใดก็ได้เช่น ข้อมูลชนิดพื้นฐาน ข้อมูลชนิดโครงสร้างอื่นๆ รวมทั้งข้อมูลชนิดอาร์เรย์เอง แต่ทุกเอลิเมนต์ในอาร์เรย์เดียวกันจะต้องมีชนิดเหมือนกันเช่น
TYPE
Complex_number = RECORD
real_val : real;
imag_val : real;
END;
Sample = (HCL,CO1,SO2);
Sampling_result = ARRAY [ sample ] OF real;
Testing_mode =(burnt_test,shock_test,prev_maintenance,overall);
Testing_set = ARRAY [Testing_mode] OF Sampling_result;
VAR
X : ARRAY [1..20} OF Complex_number;
Experiment_Result : ARRAY [1..10] OF Sampling_result;
Monthly_Operation : ARRAY [1..31] OF Testing_set;

การใช้ข้อมูลอาร์เรย์เบื้องต้น
ตัวแปรที่มีชนิดข้อมูลอาร์เรย์นั้น เมื่อเรานำมาใช้งานส่วนใหญ่แล้วผู้ใช้จะต้องการอ้างเข้าไปถึง  เอลิเมนต์แต่ละตัวของอาร์เรย์ โดยใช้ดัชนีเป็นตัวช่วยอ้างถึงตำแหน่งเอลิเมนต์ที่ต้องการ หากต้องการใช้หรืออ้างถึงทุกๆ เอลิเมนต์ หรือช่วงใดช่วงหรือช่วงหนึ่งของอาร์เรย์ เราสามารถทำได้โดยใช้คำสั่งวนรอบเพื่อเข้าถึงเอลิเมนต์ทีละเอลิเมนต์จนครบทุกเอลิเมนต์ตามที่ต้องการ ในหัวข้อนี้จะกล่าวถึงวิธีการเขียนโปรแกรมเพื่อเข้าถึงเอลิเมนต์ต่างๆ ในตัวแปรอาร์เรย์
การกำหนดค่าเริ่มต้นให้แก่ชนิดข้อมูลอาร์เรย์
การตั้งค่าข้อมูลเริ่มต้นให้แก่ทุกเอลิเมนต์ให้มีข้อมูลค่าเดียวกันเขียนได้ดัง
CONST max_samp = 100;
VAR
Score : ARRAY [ 1.. max_samp] OF real;
IDX : integer;
BEGIN
FOR IDX := 1 TO max_samp DO
Score[IDX] := 0.0;
END.

การรับข้อมูลและแสดงผลตัวแปรชนิดอาร์เรย์
คำสั่ง READ, READLN, WRITE, WRITELN ซึ่งเป็นคำสั่งรับข้อมูล และแสดงผลของภาษาปาสคาล ไม่สามารถใช้รับข้อมูลหรือแสดงผลตัวแปรอาร์เรย์ได้ทั้งตัว ต้องสั่งให้แสดงผลทีละ เอลิเมนต์ไป ตัวอย่างในการรับข้อมูลและแสดงผลตัวแปรอาร์เรย์ แสดงในตัวอย่าง
PROGRAM Ex_Result (Input,Output);
CONST
Max_Samp = 100;
VAR
Exp_Result : ARRAY [1.. Max_Samp] OF real;
ExNo : integer;
Max_Exp : integer;
BEGIN
REPEAT
Write('Enter no. OF sampling : ');
Readln(Max_Exp);
UNTIL (Max_Exp <= max_samp) and (max_exp > 0);
FOR ExNo := 1 TO Max_Exp DO
BEGIN
Write('Result No.',ExNo:4':');
Readln('Exp_Result[ExNo]);
END;
FOR ExNo := 1 TO Max_Exp DO
Writeln('Result no.',ExNo:4,' :',Exp_Result[ExNo]);
END.



การอ้างถึงตัวแปรอาร์เรย์ในรูปแบบต่าง ๆ
การใช้ตัวแปรอาร์เรย์ในคำสั่งต่างๆ ต้องอ้างถึงเอลิเมนต์ของอาร์เรย์ โดยระบุดัชนี เช่น
RESULT[I] := SCORE [ I ] / 100;
SUMMARY[1] := SUM_SCORE / NUM_SCORE;
SUMMARY[2] := NUM_SCORE;
STEP_VALUE[STEP_NO+1] := STEP_VALUE[STEP_NO] + STEP_INC;
การอ้างถึงตัวแปรอาร์เรย์ทั้งตัว ที่มีการใช้ในคำสั่งบางลักษณะ ได้แก่
1. คำสั่งกำหนดค่าตัวแปรให้อาร์เรย์ตัวหนึ่งๆ (ทุกๆ เอลิเมนต์) มีข้อมูลเหมือนตัวแปรอาร์เรย์อีกตัวหนึ่งมีข้อจำกัดว่า ตัวแปรอาร์เรย์ทั้งสองตัวจะต้องประกาศด้วยชนิดข้อมูลอาร์เรย์ที่เหมือนกันเท่านั้น ดังตัวอย่าง
TYPE
Result_Array = ARRAY [1..100] OF real;
VAR
First_result, Second_Result : Result_Array;
BEGIN
Second_Result := First_Result;
END.
2. เป็นพารามิเตอร์ของโพรซีเยอร์ หรือฟังก์ชันที่กำหนดชนิดพารามิเตอร์เป็นอาร์เรย์หากมี   โพรซีเยอร์ หรือฟังก์ชันที่ต้องส่งผ่านอาร์เรย์ทั้งตัวเป็นพารามิเตอร์ ก็สามารถใช้ชนิดข้อมูลอาร์เรย์เป็นชนิดของพารามิเตอร์ได้แต่ต้องประกาศชนิดโดยใช้ส่วนประกาศชนิด (Type) สร้างชื่อชนิดใหม่ที่เป็นอาร์เรย์ที่มีจำนวน และชนิดของเอลิเมนต์ตามที่ต้องการ จึงนำชื่อชนิดนั้นไปใช้เป็นชื่อชนิดของพารามิเตอร์ได้ในการเรียกใช้โพรซีเยอร์หรือฟังก์ชัน ตัวแปรที่จะส่งไปเป็นพารามิเตอร์ก็ต้องใช้ชนิดเดียวกันกับชื่อชนิดของการกำหนดพารามิเตอร์ในการประกาศโพรซีเยอร์หรือฟังก์ชันด้วย ดังตัวอย่าง
TYPE
Result_Array = ARRAY [1..100] OF real;
VAR
First_Result : Result_Array;
Frist_count : integer;
First_arg : real;
FUNCTION Result_avg(Result_A:Result_Array;Res_no:INTEGER):real;
VAR
R_SUM : real;
IDX : integer;
BEGIN
R_SUM := 0.0;
FOR IDX := 1 TO Res_no DO
R_SUM := R_SUM + Result_A[IDX];
Result_avg := R_Sum/Res_no;
END;
PROCEDURE Print_Result(Result_A:Result_Array; Res_no:integer);
VAR
IDX : integer;
BEGIN
FOR IDX := 1 TO Res_no DO
Writeln(LST,'Result no.',IDX:4':',Result_A[IDX]:10:4);
END;
BEGIN
First_avg := Result_avg(First_Result,First_count);
Print_Result(First_Result,First_count);
END.
ประโยชน์ของการใช้อาร์เรย์ มักใช้เก็บข้อมูลที่เป็นชุด ในบางครั้งอาจต้องมีการค้นหาข้อมูล ที่เก็บอยู่ในอาร์เรย์เพื่อให้ได้ข้อมูลที่ต้องการ เช่น ต้องการข้อมูลที่มีค่าสูงสุด ต่ำสุด ต้องการข้อมูลที่มีค่าต่ำกว่าตัวแรกที่พบในชุดข้อมูลที่มีข้อความนำหน้าด้วยอักษร "S" หรืออาจต้องการรับข้อมูลเข้าสู่ตัวแปรอาร์เรย์ แล้วนำไปจัดเรียงลำดับค่ามากน้อย หรือเรียงลำดับตัวอักษรของข้อความ เพื่อนำไปแสดงผล หรือเก็บบันทึกให้สามารถนำไปใช้ต่อ ในหัวข้อนี้จะยกตัวอย่างการเขียนโปรแกรมเพื่อค้นหา และจัดเรียงลำดับข้อมูลที่มีอยู่ในอาร์เรย์
โปรแกรมนี้จะทำการรับค่าจำนวนของนักเรียน และรับค่าคะแนนของนักเรียนแต่ละคน หลังจากนั้นจะทำการหาผลรวมของคะแนนทั้งหมด และหาค่าเฉลี่ยเลขคณิตของคะแนนทั้งหมด
PROGRAM LinAver;
USES CRT;
VAR
score : ARRAY[1..100] OF real;
avg, sum : real;
i, num : integer;
BEGIN
Clrscr;
REPEAT
Write('Enter number OF student: ');
Readln(num);
UNTIL num in [1..100];
Writeln;
sum := 0;
FOR i := 1 TO num DO
BEGIN
Write('Enter score OF student number ',i,' : ');
Readln(score[i]);
sum := sum + score[i];
END;
avg := sum/num;
Writeln;
Writeln('Summation OF all scores is ',sum:0:2);
Writeln('The average OF all scores is ',avg:0:2);
Readln;
END.

การประกาศและอ้างถึงชนิดข้อมูลอาร์เรย์
ในส่วนที่ผ่านมาเราได้แนะนำถึงอาร์เรย์ชนิดหนึ่งมิติ ซึ่งจะเห็นว่าในการกำหนดอาร์เรย์ชนิดนี้จะมีดัชนีซึ่งมีลักษณะเป็นช่วงเพียงชุดเดียว ข้อมูลที่เป็นอาร์เรย์หนึ่งมิติจะมีลักษณะเหมือนการนำเอาข้อมูลชนิดเดียวกันมาเรียงต่อกันเป็นเส้นตรงคล้ายกับการเข้าแถว
ในโปรแกรมภาษาปาสคาลสามารถสร้างและใช้อาร์เรย์หลายมิติได้สำหรับอาร์เรย์สองมิติเราสามารถเปรียบเทียบได้กับลักษณะของตารางซึ่งประกอบด้วยแกนแนวตั้งและแกนแนวนอน แกนแต่ละแกนนี้ก็คือดัชนีในแต่ละมิตินั้นเอง การประกาศอาร์เรย์หลายมิตินั้นสามารถทำได้โดยทำการกำหนดดัชนีซึ่งมีลักษณะเป็นช่วงเช่นเดียวกับดัชนีของอาร์เรย์หนึ่งมิติจำนวนหลายๆ ชุดโดยแต่ละตัวจะคั่นด้วยเครื่องหมาย ","
ตัวอย่าง เช่น
VAR M_array : ARRAY [1..10,1..3] OF char;
มีปัญหาอยู่หลายอย่างที่จำเป็นจะต้องเก็บข้อมูลให้อยู่ในรูปของตารางตัวอย่างเช่น ถ้าหากเราต้องการจดบันทึกค่าของแรงดันภายในท่อน้ำตามตำแหน่งต่างๆ ทั้งหมด 4 ตำแหน่งด้วยกันโดย ในหนึ่งวันจะทำการจดบันทึกทั้งหมด 5 ครั้ง ค่าของแรงดันที่อ่านได้สามารถบันทึกลงในตารางได้ดังนี้
ตารางแสดงตัวอย่างการการบันทึกข้อมูลในลักษณะตาราง
จากตารางที่สร้างขึ้นจะพบว่า ความดันในท่อน้ำ 4 ค่าที่อ่านได้ในหนึ่งครั้งนั้นอยู่ในแนวนอน และจำนวนครั้งที่อ่านทั้งหมด 5 ครั้งอยู่ในแนวตั้งรวมจำนวนข้อมูลทั้งหมด 20 ตัว เราสามารถกำหนดตัวแปรเพื่อสำหรับใช้ในการเก็บข้อมูลชุดนี้ได้ดังนี้
CONST
Times = 5; Locations = 4;
TYPE
PressureDataTable=ARRAY[1..Times,1..Locations] OF real;
VAR
PressureTable : PressureDataTable;
ในการอ้างถึงตัวข้อมูลนั้นสามารถอ้างได้ดังตัวอย่างเช่น ถ้าต้องการอ้างถึงข้อมูลของแรงดันที่วัดได้จากการอ่านครั้งที่ 5 ตำแหน่งที่ 2 จะเป็นดังนี้
PressureTable[5,2]
จากตัวอย่างในการกำหนดตัวแปรอาร์เรย์ที่เป็น 2 และ 3 มิติ ที่ผ่านมาคงพอจะทำให้เกิด ความเข้าใจในการกำหนดตัวแปรอาร์เรย์ชนิดหลายมิติได้ถ้าหากต้องการที่จะเพิ่มมิติให้กับตัวแปรอีกก็สามารถทำได้โดยเพิ่มจำนวนดัชนีดังตัวอย่างของอาร์เรย์ 2 และ 3 มิติ และจำนวนตัวแปรทั้งหมดที่
เกิดขึ้นจะเท่ากับผลคูณของจำนวนเอลิเมนต์ในแต่ละมิติ