C – Arrays อาร์เรย์ ภาษา C
อาร์เรย์ประเภทโครงสร้างข้อมูลที่สามารถจัดเก็บคอลเล็กชันแบบต่อเนื่องที่มีขนาดคงที่ขององค์ประกอบประเภทเดียวกัน อาร์เรย์ใช้เพื่อจัดเก็บชุดข้อมูล แต่มักจะมีประโยชน์มากกว่าที่จะคิดว่าอาร์เรย์เป็นชุดของตัวแปรประเภทเดียวกัน
แทนที่จะประกาศตัวแปรเดี่ยว เช่น number0, number1, … และ number99 คุณประกาศตัวแปรอาร์เรย์หนึ่งตัว เช่น ตัวเลข และใช้ตัวเลข[0], ตัวเลข[1] และ …, ตัวเลข[99] เพื่อแสดง ตัวแปรแต่ละตัว องค์ประกอบเฉพาะในอาร์เรย์สามารถเข้าถึงได้โดยดัชนี
อาร์เรย์ทั้งหมดประกอบด้วยตำแหน่งหน่วยความจำที่อยู่ติดกัน ที่อยู่ต่ำสุดสอดคล้องกับองค์ประกอบแรกและที่อยู่สูงสุดไปยังองค์ประกอบสุดท้าย
ประกาศอาร์เรย์
ในการประกาศอาร์เรย์ในภาษา C โปรแกรมเมอร์จะระบุประเภทขององค์ประกอบและจำนวนองค์ประกอบที่อาร์เรย์ต้องการดังนี้:
type arrayName [ arraySize ];
นี่เรียกว่า อาร์เรย์ 1 มิติ (single-dimensional array) arraySize ต้องเป็นจำนวนเต็มมากขึ้นอย่างต่อเนื่องกว่าศูนย์และ ชนิดข้อมูล ที่ถูกต้อง ของภาษา C ตัวอย่างเช่น ในการประกาศอาร์เรย์ 10 องค์ประกอบที่เรียกว่า balance ของชนิดข้อมูล double ให้ใช้คำสั่งนี้ −
double balance[10];
นี่คือ balance เป็นอาร์เรย์ตัวแปรซึ่งจะเพียงพอที่จะมีได้ถึง 10 หมายเลข
การเริ่มต้นอาร์เรย์
คุณสามารถเริ่มต้นอาร์เรย์ใน C ทีละรายการหรือใช้คำสั่งเดียวดังนี้ −
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
จำนวนค่าระหว่างวงเล็บปีกกา { } ต้องไม่เกินจำนวนองค์ประกอบที่เราประกาศสำหรับอาร์เรย์ระหว่างวงเล็บเหลี่ยม [ ]
หากคุณละเว้นขนาดของอาร์เรย์ อาร์เรย์ที่ใหญ่พอที่จะรองรับการเริ่มต้นจะถูกสร้างขึ้น ดังนั้น หากคุณเขียน −
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
คุณจะสร้างอาร์เรย์เดียวกันกับที่คุณทำในตัวอย่างก่อนหน้านี้ ต่อไปนี้เป็นตัวอย่างการกำหนดองค์ประกอบเดียวของอาร์เรย์ −
balance[4] = 50.0;
ข้อความข้างต้นกำหนด 5 THองค์ประกอบในอาร์เรย์ที่มีมูลค่า 50.0 อาร์เรย์ทั้งหมดมี 0 เป็นดัชนีขององค์ประกอบแรกซึ่งเรียกว่าดัชนีฐาน และดัชนีสุดท้ายของอาร์เรย์จะมีขนาดรวมของอาร์เรย์ลบ 1 ที่แสดงด้านล่างคือการแสดงภาพของอาร์เรย์ที่เรากล่าวถึงข้างต้น:
การเข้าถึงองค์ประกอบอาร์เรย์
องค์ประกอบสามารถเข้าถึงได้โดยการสร้างดัชนีชื่ออาร์เรย์ ทำได้โดยการวางดัชนีขององค์ประกอบภายในวงเล็บเหลี่ยมหลังชื่อของอาร์เรย์ ตัวอย่างเช่น −
double salary = balance[9];
ข้อความข้างต้นจะใช้เวลา 10 วันองค์ประกอบจากอาร์เรย์และกำหนดค่าให้กับตัวแปรเงินเดือน ตัวอย่างต่อไปนี้ แสดงวิธีการใช้แนวคิดทั้งสามที่กล่าวมาข้างต้น ได้แก่ การประกาศ การกำหนด และการเข้าถึงอาร์เรย์ −
#include <stdio.h>
int main () {
int n[ 10 ]; /* n is an array of 10 integers */
int i,j;
/* initialize elements of array n to 0 */
for ( i = 0; i < 10; i++ ) {
n[ i ] = i + 100; /* set element at location i to i + 100 */
}
/* output each array element's value */
for (j = 0; j < 10; j++ ) {
printf("Element[%d] = %d\n", j, n[j] );
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และรัน มันจะให้ผลลัพธ์ดังต่อไปนี้ −
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
รายละเอียดอาร์เรย์ (Arrays in Detail)
อาร์เรย์มีความสำคัญต่อ C และควรได้รับความสนใจมากขึ้น แนวคิดที่สำคัญที่เกี่ยวข้องกับอาร์เรย์ต่อไปนี้ควรมีความชัดเจนสำหรับโปรแกรมเมอร์ C −
อาร์เรย์หลายมิติ (Multi-dimensional arrays)
นี่คือรูปแบบทั่วไปของการประกาศอาร์เรย์หลายมิติ −
type name[size1][size2]...[sizeN];
ตัวอย่างเช่น การประกาศต่อไปนี้จะสร้างอาร์เรย์จำนวนเต็ม3 มิติ −
int threedim[5][10][4];
อาร์เรย์สองมิติ (Two-dimensional Arrays)
รูปแบบที่ง่ายที่สุดของอาร์เรย์หลายมิติคืออาร์เรย์สองมิติ สาระสำคัญของอาร์เรย์สองมิติคือรายการอาร์เรย์หนึ่งมิติ ในการประกาศอาร์เรย์จำนวนเต็มสองมิติที่มีขนาด [x][y] คุณจะต้องเขียนดังนี้ −
type arrayName [ x ][ y ];
โดยที่ type สามารถเป็นประเภทข้อมูล C ที่ถูกต้องและ arrayName จะเป็นตัวระบุ C ที่ถูกต้อง อาร์เรย์สองมิติถือได้ว่าเป็นตารางที่มีจำนวนแถว x และจำนวนคอลัมน์ y อาร์เรย์ a 2 มิติ ซึ่งประกอบด้วยสามแถวและสี่คอลัมน์สามารถแสดงได้ดังนี้
ดังนั้น ทุกองค์ประกอบในอาร์เรย์ จะถูกระบุโดยชื่อองค์ประกอบของรูปแบบa[ i ][ j ]โดยที่ ‘a’ คือชื่อของอาร์เรย์ และ ‘i’ และ ‘j’ คือตัวห้อยที่ระบุเฉพาะ แต่ละองค์ประกอบใน ‘a’
การเริ่มต้นอาร์เรย์ 2 มิติ
อาร์เรย์หลายมิติสามารถเริ่มต้นได้โดยการระบุค่าในวงเล็บสำหรับแต่ละแถว ต่อไปนี้เป็นอาร์เรย์ที่มี 3 แถว และแต่ละแถวมี 4 คอลัมน์
int a[3][4] = {
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};
วงเล็บปีกกาซ้อน ซึ่งระบุแถวที่ต้องการ เป็นทางเลือก การเริ่มต้นต่อไปนี้เทียบเท่ากับตัวอย่างก่อนหน้า −
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
การเข้าถึงองค์ประกอบอาร์เรย์สองมิติ
องค์ประกอบในอาร์เรย์สองมิติสามารถเข้าถึงได้โดยใช้ตัวห้อย ได้แก่ ดัชนีแถวและดัชนีคอลัมน์ของอาร์เรย์ ตัวอย่างเช่น −
int val = a[2][3];
คำสั่งข้างต้นจะนำองค์ประกอบที่ 4 จากแถวที่ 3 ของอาร์เรย์ คุณสามารถตรวจสอบได้ในรูปด้านบน ให้เราตรวจสอบโปรแกรมต่อไปนี้ที่เราได้ใช้การวนซ้ำซ้อนเพื่อจัดการกับอาร์เรย์สองมิติ −
#include <stdio.h>
int main () {
/* an array with 5 rows and 2 columns*/
int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
int i, j;
/* output each array element's value */
for ( i = 0; i < 5; i++ ) {
for ( j = 0; j < 2; j++ ) {
printf("a[%d][%d] = %d\n", i,j, a[i][j] );
}
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และรัน มันจะให้ผลลัพธ์ดังต่อไปนี้ −
a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8
ตามที่อธิบายไว้ข้างต้น คุณสามารถมีอาร์เรย์ที่มีมิติข้อมูลจำนวนเท่าใดก็ได้ แม้ว่ามีแนวโน้มว่าอาร์เรย์ส่วนใหญ่ที่คุณสร้างจะมีมิติข้อมูลหนึ่งหรือสองมิติ
การส่งผ่านอาร์เรย์เป็นอาร์กิวเมนต์ฟังก์ชันใน C
หากคุณต้องการส่งอาร์เรย์มิติเดียวเป็นอาร์กิวเมนต์ในฟังก์ชัน คุณจะต้องประกาศพารามิเตอร์ที่เป็นทางการด้วยวิธีใดวิธีหนึ่งจากสามวิธีต่อไปนี้ และวิธีการประกาศทั้งสามวิธีให้ผลลัพธ์ที่คล้ายคลึงกัน เนื่องจากแต่ละวิธีบอกคอมไพเลอร์ว่าตัวชี้จำนวนเต็มกำลังดำเนินอยู่ ที่จะได้รับ ในทำนองเดียวกัน คุณสามารถส่งอาร์เรย์หลายมิติเป็นพารามิเตอร์ที่เป็นทางการได้
วิธีที่ 1
พารามิเตอร์ทางการเป็นตัวชี้ −
void myFunction(int *param) {
.
.
.
}
วิธีที่ 2
พารามิเตอร์ทางการเป็นอาร์เรย์ขนาด −
void myFunction(int param[10]) {
.
.
.
}
วิธีที่ 3
พารามิเตอร์ทางการเป็นอาร์เรย์ที่ไม่มีขนาด −
void myFunction(int param[]) {
.
.
.
}
ตัวอย่าง
ตอนนี้ ให้พิจารณาฟังก์ชันต่อไปนี้ ซึ่งรับอาร์เรย์เป็นอาร์กิวเมนต์พร้อมกับอาร์กิวเมนต์อื่น และอิงตามอาร์กิวเมนต์ที่ส่งผ่าน ฟังก์ชันจะส่งกลับค่าเฉลี่ยของตัวเลขที่ส่งผ่านอาร์เรย์ดังนี้:
double getAverage(int arr[], int size) {
int i;
double avg;
double sum = 0;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
avg = sum / size;
return avg;
}
ตอนนี้ ให้เราเรียกใช้ฟังก์ชันข้างต้นดังนี้ −
#include <stdio.h>
/* function declaration */
double getAverage(int arr[], int size);
int main () {
/* an int array with 5 elements */
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
/* pass pointer to the array as an argument */
avg = getAverage( balance, 5 ) ;
/* output the returned value */
printf( "Average value is: %f ", avg );
return 0;
}
เมื่อโค้ดข้างต้นถูกคอมไพล์และดำเนินการ โค้ดดังกล่าวจะทำให้เกิดผลลัพธ์ดังต่อไปนี้ −
Average value is: 214.400000
อย่างที่คุณเห็น ความยาวของอาร์เรย์ไม่สำคัญเท่าที่เกี่ยวข้องกับฟังก์ชัน เนื่องจาก C ดำเนินการตรวจสอบพารามิเตอร์ที่เป็นทางการโดยไม่มีขอบเขต
ส่งคืนอาร์เรย์จากฟังก์ชันใน C
การเขียนโปรแกรม C ไม่อนุญาตให้ส่งคืนอาร์เรย์ทั้งหมดเป็นอาร์กิวเมนต์ของฟังก์ชัน อย่างไรก็ตาม คุณสามารถส่งคืนตัวชี้ไปยังอาร์เรย์ได้โดยการระบุชื่ออาร์เรย์โดยไม่มีดัชนี
หากคุณต้องการส่งคืนอาร์เรย์มิติเดียวจากฟังก์ชัน คุณจะต้องประกาศฟังก์ชันที่ส่งคืนตัวชี้ดังในตัวอย่างต่อไปนี้:
int * myFunction() {
.
.
.
}
จุดที่สองที่ต้องจำไว้คือ C ไม่ได้สนับสนุนให้ส่งที่อยู่ของตัวแปรโลคอลกลับคืนสู่ภายนอกฟังก์ชัน ดังนั้น คุณจะต้องกำหนดตัวแปรโลคอลเป็นตัวแปรสแตติก
ตอนนี้ ให้พิจารณาฟังก์ชันต่อไปนี้ซึ่งจะสร้างตัวเลขสุ่ม 10 ตัวและส่งกลับโดยใช้อาร์เรย์และเรียกใช้ฟังก์ชันนี้ดังนี้
#include <stdio.h>
/* function to generate and return random numbers */
int * getRandom( ) {
static int r[10];
int i;
/* set the seed */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i) {
r[i] = rand();
printf( "r[%d] = %d\n", i, r[i]);
}
return r;
}
/* main function to call above defined function */
int main () {
/* a pointer to an int */
int *p;
int i;
p = getRandom();
for ( i = 0; i < 10; i++ ) {
printf( "*(p + %d) : %d\n", i, *(p + i));
}
return 0;
}
เมื่อโค้ดข้างต้นถูกคอมไพล์และดำเนินการ โค้ดดังกล่าวจะทำให้เกิดผลลัพธ์ดังต่อไปนี้ −
r[0] = 313959809
r[1] = 1759055877
r[2] = 1113101911
r[3] = 2133832223
r[4] = 2073354073
r[5] = 167288147
r[6] = 1827471542
r[7] = 834791014
r[8] = 1901409888
r[9] = 1990469526
*(p + 0) : 313959809
*(p + 1) : 1759055877
*(p + 2) : 1113101911
*(p + 3) : 2133832223
*(p + 4) : 2073354073
*(p + 5) : 167288147
*(p + 6) : 1827471542
*(p + 7) : 834791014
*(p + 8) : 1901409888
*(p + 9) : 1990469526
ตัวชี้ไปยังอาร์เรย์ใน C
เป็นไปได้มากว่าคุณจะไม่เข้าใจส่วนนี้จนกว่าคุณจะอ่านบท ‘ตัวชี้’ จนจบ
สมมติว่าคุณมีความเข้าใจพอยน์เตอร์ในภาษา C มาบ้าง เรามาเริ่มกันเลย: ชื่ออาร์เรย์คือตัวชี้คงที่ไปยังองค์ประกอบแรกของอาร์เรย์ ดังนั้นในการประกาศ −
double balance[50];
balance เป็นตัวชี้ไปที่ &บาลานซ์[0] ซึ่งเป็นที่อยู่ขององค์ประกอบแรกของความสมดุลอาเรย์ ดังนั้น ส่วนย่อยของโปรแกรมต่อไปนี้กำหนด p เป็นที่อยู่ขององค์ประกอบแรกของ balance −
double *p;
double balance[10];
p = balance;
การใช้ชื่ออาร์เรย์เป็นตัวชี้คงที่เป็นเรื่องถูกกฎหมาย และในทางกลับกัน ดังนั้น *(balance + 4) เป็นวิธีที่ถูกต้องในการเข้าถึงข้อมูลที่ balance[4]
เมื่อคุณเก็บที่อยู่ขององค์ประกอบแรกใน ‘p’ คุณจะสามารถเข้าถึงองค์ประกอบอาร์เรย์ได้โดยใช้ *p, *(p+1), *(p+2) และอื่นๆ ด้านล่างนี้เป็นตัวอย่างเพื่อแสดงแนวคิดทั้งหมดที่กล่าวถึงข้างต้น −
#include <stdio.h>
int main () {
/* an array with 5 elements */
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
int i;
p = balance;
/* output each array element's value */
printf( "Array values using pointer\n");
for ( i = 0; i < 5; i++ ) {
printf("*(p + %d) : %f\n", i, *(p + i) );
}
printf( "Array values using balance as address\n");
for ( i = 0; i < 5; i++ ) {
printf("*(balance + %d) : %f\n", i, *(balance + i) );
}
return 0;
}
เมื่อโค้ดด้านบนถูกคอมไพล์และรัน มันจะให้ผลลัพธ์ดังต่อไปนี้ −
Array values using pointer
*(p + 0) : 1000.000000
*(p + 1) : 2.000000
*(p + 2) : 3.400000
*(p + 3) : 17.000000
*(p + 4) : 50.000000
Array values using balance as address
*(balance + 0) : 1000.000000
*(balance + 1) : 2.000000
*(balance + 2) : 3.400000
*(balance + 3) : 17.000000
*(balance + 4) : 50.000000
ในตัวอย่างข้างต้น p คือตัวชี้ไปยัง double ซึ่งหมายความว่าสามารถเก็บที่อยู่ของตัวแปรประเภท double ได้ เมื่อเรามีที่อยู่ใน p แล้ว *p จะให้ค่าที่อยู่ที่เก็บไว้ใน p ดังที่เราได้แสดงในตัวอย่างข้างต้น