หวัดดีคร้าบท่านผู้อ่านทุกท่าน บทนี้จะนำเสนอเรื่องการจองอาเรย์แบบที่ปรับเปลี่ยนขนาดได้!!!

ปรับเปลี่ยนได้ไม่ได้หมายถึง จองไว้ 10 แล้วกลางโปรแกรมหดเลือห 5 แล้วยืดไป 7 อะไรแบบนี้นะครับ
(ทำได้รึเปล่าไม่รู้แฮะ) แต่หมายถึงว่า เราสามารถให้โรแกรมกำหนดขนาดตอนจองได้(อ่าว งงละสิ)

คืองี้ครับ ปกติเวลาเราจองอาเรย์ เราก็จะประกาศแบบนี้(สมมติจอง 100 ช่อง)

int array[100];

ซึ่งหมายความว่า ไม่ว่าเราจะรันกี่ร้อยกี่พันครั้ง มันก็จะจองให้เรา 100 ช่อง

สมมติเราทำโปรแกรมเก็บอายุนักเรียน แบบเขียนครั้งเดียว แจกให้ทุกโรงเีรียนทั่วประเทศ ถ้าโรงเรียนนึง
 มี 100 คน อีกโรงเรียนมี 200 คน อีกโรงเรียนมี 500 คน เราก็ต้องประกาศอาเรย์ถึง 500 ช่องถูกมั้ยครับ
ถ้าน้อยกว่านี้ โรงเรียนสุดท้ายก็จะมีอาเรย์ไม่พอ แต่ถ้าประกาศ 500 ช่อง โรงเรียนแรกซึ่งต้องการใช้
แค่100 ช่อง ก็จะเสียหน่วยความจำไปฟรีๆ400ช่อง การสร้างตัวแปรแบบ Dynamic จึงได้ถือกำเนิดขึ้น!!!

ก่อนอื่น ทุกคนควรจะมีความู้เรื่อง pointer มาบ้างนะครับ เพราะจำเป็นสำหรับบทนี้

วิธีการคือ เวลาเราประกาศ เราไม่ต้องไปประกาศเป็นอาเรย์ครับ ให้ประกาศเป็น pointer ไปเลย!!!

int* dnm;

จากนั้น เราก็จัดการบอกโปรแกรมว่า ต้องการให้มันมีกี่ช่อง ด้วยฟังก์ชันแบบนี้

dnm = ( int *)malloc(size * sizeof(int));

ชนิดข้อมูลไม่จำเป็นต้องเป็น int นะครับ อย่างอื่นก็ได้ แต่ต้องประกาศเป็นพอยเตอร์ชนิดนั้นๆ
แล้วก็เปลี่ยนคำว่า int ตรง malloc เป็นชื่อชนิดข้อมูลนั้นๆด้วย

size : ขนาด หมายถึงจำนวนช่อง ใส่เป็นตัวแปรได้(นี่คือสิ่งที่ทำให้มันเป็น dynamic เพราะการ
ประกาศอาเรย์ปกติใส่ตัวแปรไม่ได้ ยกเว้นตัวแปรค่าคงที่) เช่นถ้าให้ประกาศ 10 ช่องก็ใส่เลข 10 ถ้าให้
ประกาศ n ช่องก็ใส่ตัวแปร n เข้าไปได้เลย

เวลาใช้งาน เราก็ลืมไปเลยว่ามันเป็น pointer ครับ ใช้งานเหมือนอาเรย์ได้ทุกประการ

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

free(ชื่อตัวแปร);

เช่น

free(dnm);

หลังจากที่ free ไปแล้ว เราจะใช้งานตัวแปรอาเรย์ไดนามิกที่เราสร้างขึ้นไม่ได้อีก ถ้าอยากใช้งาน
ต้องจับมันมา malloc อีกครั้ง

ตัวอย่างโปรแกรม

#include   [stdio.h ] // change  [ , ] to < , >

int main()
{
    int* p;
    int n,i;
    printf("How many element in array : ");
    scanf("%d",&n);
    p = (int *) malloc(n*sizeof(int));
   
printf("Input\n");
    for(i=0;i
        scanf("%d",&p[i]);
    for(i=0;i
        printf("%d ",p[i]);
    free(p);
    scanf(" ");
    return 0;
}

ผลการรัน

 


edit @ 5 Jul 2009 21:32:18 by Mistertun

edit @ 5 Jul 2009 21:39:17 by Mistertun

สำหรับผู้ที่เขียนภาษาซีเป็นแล้ว (และควรจะเขียนฟังก์ชันใช้งานเองเป็น)

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

หลายๆคนคงเคยเขียนโปรแกรมที่ต้องมีการจัดเรียนข้อมูล(sort)ในอาเรย์ ซึ่งการเขียนฟังก์ชันsortเองก็อาจจะ
เสียเวลา ในภาษาซีเรามีฟังก์ชันสำเร็จรูปมาให้แล้วครับ(ซึ่งทำงานได้เร็วพอสมควร)

ข้ันแรก ทำการ include ไฟล์ stdlib.h ด้วย

ขั้นที่ 2 ก๊อปฟังก์ชันด้านล่างนี้ไปแปะไว้ก่อน main()

int compare(const void *  a,const void * b)
{
    return (*(int*)a - *(int*)b);
}

ขั้นที่ 3 เมื่อไหร่ที่ต้องการซอร์ต ให้แทรกฟังก์ชันนี้เข้าไป

qsort(ชื่ออาเรย์,จำนวนช่องที่ต้องการจัดเรียง,ขนาดของข้อมูลแต่ละตัว,compare);

ชื่ออาเรย์ก็คือชื่อของอาเรย์ที่เราต้องการจัดเรียงข้อมูล
จำนวนช่อง ก็คือ สมมติว่าเรามีอาเรย์ขนาด 10 ช่อง แต่ต้องการจัดเรียงแค่ 5 ช่อง เราก็ใส่ 5 แค่นั้น(ใส่เป็นตัว
แปรเช่น n ก็ได้)
ขนาดข้อมูล ตรงนี้ให้ใส่แบบนี้ครับ sizeof(ชนิดข้อมูล) ถ้าเป็นอาเรย์แบบ int ก็ให้ชนิดข้อมูลเป็น int ถ้าอาเรย์
double ก็ให้ชนิดข้อมูลเป็น double
ส่วน compare ไม่ต้องสนใจ ใส่ๆไป

นี่เป็นตัวอย่างการจัดเรียงแบบน้อยไปมาก ถ้าอยากได้แบบมากไปน้อย ในฟังก์ชัน compare ให้แก้เป็นแบบนี้

int compare(const void *  a,const void * b)
{
    return (*(int*)b - *(int*)a); // สังเกตว่า a และ b สลับที่กัน
}

ตัวอย่างโปรแกรมนะครับ

#include [ stdio.h ] // change [ , ] to < , >
#include [ stdlib.h ] // change [ , ] to < ,>

int compare (const void * a, const void * b)
{
  return ( *(int*)b - *(int*)a
); // sort Max to Min
}


int main ()
{
  int n,arr[50],i;
  printf("How many number : ");
  scanf("%d",&n);
  printf("Input Number\n");
  for(i=0;i
    scanf("%d",&arr[i]);
  qsort (arr, 6, sizeof(int), compare);
  for (i=0;i
     printf ("%d ",arr[n]);
  scanf(" ");  
  return 0;
}

ผลการรัน

 

 

 


 

edit @ 5 Jul 2009 21:24:13 by Mistertun

edit @ 5 Jul 2009 21:25:54 by Mistertun

edit @ 5 Jul 2009 21:26:04 by Mistertun

edit @ 5 Jul 2009 21:40:07 by Mistertun

ไม่ได้มาซะนาน ช่วงนี้เปิดเทอมแล้วง่ะ.. งานชักเริ่มเข้ามา แถมยังมี FarCry2 ให้ติดอีกต่างหาก เฮ่อ - -"

การใช้งานอาเรย์สองมิติ

อาเรย์ที่เราได้เรียนๆไปแล้วคืออาเรย์มิติเดียวครับ สังเกตว่าพอเราประกาศขึ้นมาแล้ว มันจะมีค่าเท่ากับการประกาศตัวแปรหลายๆตัว ซึ่งบางทีเราก็จะมองมันเป็นแถวของตัวแปรครับ ลองเปรียบเทียบตัวแปรเป็นเก้าอี้ว่างๆ และเปรียบข้อมูลเป็นคนนั่ง ถ้าเราประกาศตัวแปรธรรมดา (int n;) เราก็จะไำด้เก้าอี้มา 1 ตัวและมีใครก็ไม่รู้นั่งอยู่แต่ถ้าเราประกาศเป็นอาเรย์ สมมติ int arr[10]; เราก็จะได้เก้าอี้ต่อกันเป็นแถวยาวๆ 10 ตัว แต่ละตัวมีหมายเลขกำกับอยู่ ถ้าเราอยากจะคุยกับคนที่นั่งเก้าอี้ตัวไหน เราก็ใช้หมายเลขของเก้าอี้เวลาเรียกเค้ามา แบบนี้คือมิติเดียวครับ สังเกตว่าเก้าอี้จะเรียงกันเป็นแถวเดียว แต่จะยาวเท่าไหร่ไม่รู้

ตัวอย่างอาเรย์มิติเดียว    |5|6|9|7|12|26|100|... 

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

ตัวอย่างอาเรย์สองมิติ  
|5|9|1|2|
|2|4|7|4|
|5|5|5|4|

เวลาเราจะเรัยกตัวไหน จากที่เราเคยใช้หายเลขตัวเดียวเช่น อาเรย์ช่องที่ 3 , อาเรย์ช่องที่ 7 เราก็ต้องใช้ 2 ตัวครับ คือ ต้องบอกว่าแถวที่เท่าไหร่ และตัวที่เท่าไหร่ในแถวนั้น เหมือนเวลาไปสอบแล้วเค้าบอกให้คุณนั่งที่โต๊ะแถวที่ 7 ตัวที่ 5 อะไรประมาณนั้น

วิธีการประักาศ

ชนิดข้อมูล ชื่อตัวแปร[จำนวนแถว][จำนวนตัวในแถว];

เช่น

int arr[10][8];

เราก็จะไำด้อาเรย์ชื่อ arr มี 10 แถว แถวละ 8 ตัว(เรีียกว่า"แถวละ 8 คอลัมน์")

เวลาเราอ้างอิงถึงข้อมูล เราก็ใช้วิธีเดียวกับอาเรย์มิติเดียวครับ เช่นต้องการกำหนดค่าในแถวที่ 5 คอลัมน์ที่ 0 ให้มีค่าเท่ากับ 12 เราก็ทำแบบนี้

arr[5][0] = 12;

โดยมากเราจะใช้อาเรย์มิติเดียวในการเก็บข้อมูลที่เป็นแถวยาวๆ เช่น เก็บเซตของตัวเลข เก็บชื่อคน(เป็นตัวอักษรเรียงต่อกัน) และใช้อาเรย์สอมิติในการเก็บตาราง เพราะสังเกตว่าตารางจะมีแถวและคอลัมน์ เช่น อาจจะใช้เก็บตารางสูตรคูณ โดยใช้อิเด็กซ์เป็นตัวตั้งและตัวคูณ เช่น 2*5เท่ากับ 10 เราก็เก็บค่าในแถวที่ 2 คอลัมน์ที่ 5 เป็น 10 ดูในตัวอย่างครับ ให้สีน้ำเงินเป็นอินเด็กซ์(แนวนอนคือแถว แนวตั้งคือคอลัมน์)และสีน้ำเงินอ่อนเป็นค่าในตัวแปร

    |  0|  1|  2|  3|  4|  5|  6|  7|  8|  9|10|11|12|
  0|  0|  0|  0|  0|  0|  0|  0|  0|  0|  0|  0|  0|  0|  
  1|  0|  1|  2|  3|  4|  5|  6|  7|  8|  9|10|11|12|
  2|  0|  2|  4|  6|  8|10|12|14|16|18|20|22|24|
  3|  0|  3|  6|  9|12|15|18|21|24|27|30|33|36|
  4|  0|  4|  8|12|16|20|24|28|32|36|40|44|48|
  5|  0|  5|10|15|20|25|30|35|40|45|50|55|60|
  6|  0|  6|12|18|24|30|36|42|48|54|60|66|72|
  7|  0|  7|14|21|28|35|42|49|56|63|70|77|84|
  8|  0|  8|16|24|32|40|48|56|64|72|80|88|96|
  9|  0|  9|18|27|36|45|54|63|72|81|90|99|108|
10|  0|10|20|30|40|50|60|70|80|90|100|110|120|
11|  0|11|22|33|44|55|66|77|88|99|110|121|132|
12|  0|12|24|36|48|60|72|84|96|108|120|132|144|

นี่คือลักษณะการเก็บข้อมูลของอาเรย์สองมิติครับ ถ้าเราอยากรู้ว่า 2*5 คือเท่าไหร่ ก็เข้าไปในอาเรย[2][5]ก็จะพบกับค่า 10 ส่วนวิธีการจะทำยังไงที่จะสร้างตารางสูตรคูณแบบนี้ เดี๋ยวจะมาดูตัวอย่างกันครับ

อาเรย์สองมิตินิยมใช้กับลูป 2 ชั้นครับ

ตัวอย่างการสร้างตารางสูตรคูณอย่างง่าย(ผมไม่เขียน include นะ แต่เวลาทำจริงให้เขียนด้วย)

int main()
{
    int table[4][4];
    table[0][0] = 0;
    table[0][1] = 0;
    table[0][2] = 0;
    table[0][3] = 0;

    table[1][0] = 0;
    table[1][1] = 1;
    table[1][2] = 2;
    table[1][3] = 3;

    table[2][0] = 0;
    table[2][1] = 2;
    table[2][2] = 4;
    table[2][3] = 6;

    table[3][0] = 0;
    table[3][1] = 3;
    table[3][2] = 6;
    table[3][3] = 8;
    return 0;

}

นี่คือตัวอย่างการสร้างครับ ไม่ต้องตกใจถ้าเอาไปรันแล้วมันขึ้นมาแว็บนึงแล้วหายไปเลย เพราะเราไม่ได้ใส่ sscanf(" "); เอาไว้ก่อนจะ return 0; ทีนี้ ถ้าเราอยากดูว่า 3*2 เท่ากับเท่าไหร่ เราก็ใส่ printf("%d",table[3][2]); เข้าไปก็เท่านั้นเองครับ แต่ถ้าเราต้องทำตารางสูตรคูณหลายๆแม่ เช่นทำถึงแม่ 12 ขืนมานั่งเขียนกำหนดค่าทีละบรรทัดคงเหนื่อยแย่

ตัวอย่างการสร้างตารางสูตรคูณด้วยลูปสองชั้นและัอาเรย์สองมิติ

ถ้าเราต้องการสร้างตารางขนาดใหญ่ๆ เราสามารถใช้ลูปเข้ามาช่วยครับ ให้โปรแกรมสร้างตารางสูตรคูณขึ้นมา จากนั้นผู้ใช้จะใส่เลข 1 ตัวมาให้ ให้โปรแกรมแสดงสูตรคูณแม่นั้นๆ
เช่นใส่เลข 5 ก็ให้แสดงสูตรคูณแม่ 5

#include [stdio.h] // change [ , ] to < , >

int main()
{
    int table[13][13];   // ประกาศ 13 เพราะต้องเก็บตั้งแต่แม่ 0 ถึงแม่ 12
    int i,j; // อันนี้เป็นตัวนับรอบ
    int a; // เก็บว่าอยากดูแม่อะไร
   for(i=0;i<=12;i++) // ลูปนี้สร้างตาราง อธิบายลูปทีหลัง
       for(j=0;j<=12;j++)
            table[i][j] = i*j;
    scanf("%d",&a); //
    for(i=0;i<=12;i++) // ลูปนี้แสดงผล เดี๋ยวอธิบาย
       printf("%d\n",table[a][i]);
    scanf(" ");
    return 0;
}

ก่อนอื่นลองเอาโปรแกรมนี้ไปรันดูก่อนครับ วิธีการคือ พอเปิดโปรแกรมขึ้นมา โปรแกรมมันจะสร้างตารางขึ้นเองโดยไม่บอกอะไรเราทั้งสิ้น ให้เราใส่เลขอะไรก็ได้ระหว่าง 0 ถึง 12 สิ่งมหัศจรรย์จะปรากฏขึ้น แล้วจะตกใจ(อิอิ)

อธิบายกันหน่อย
เก็นลูปที่เป็นลูป 2 ชันมั้ยครับ ตรงที่บอกว่าเป็นลูปสร้างตารางอ่ะ จะเห็นว่ามันมี for ซ้อนกัน 2 ชั้น หลักการของลูปสองชั้น คืองี้ครับ สมมติว่าเราสร้างลูปแบบนี้

loopA(ให้ทำ 3 รอบ) {
    loopB(ทำ5รอบ) {
       ...
    }
}

จากตัวอย่าง จะเห็นว่ามี loopB ซ้อนอยู่ภายใน loopA ซึ่งหลักการคือ เรากำหนดในลูปเอทำ 3 รอบใช่มั้ยครับ มันก็จะทำลูปเอสามรอบนั่นแหละ แต่ว่าในแต่ละรอบจะทำลูปบี 5 รอบ รวมแล้ว ลูปบีจะถูกทำทั้งหมด 15 รอบ

ไม่รู้จะอธิบายยังไงดี - -" ลองไล่โปรแกรมกันละเอียดๆนะครับ แล้วจะเข้าใจเอง ต้องใช้ความพยายามหน่อยล่ะงานนี้ แต่พอเสร็จแล้ว เราจะได้ตารางขึ้นมาอยู่ในตัวแปร table (แต่ยังไม่ได้แสดงผล)

จากนั้นผู้ใช้จะใส่ค่าเข้ามาว่าอยากดูแม่ไหน(เก็บไว้ในตัวแปร a) เราก็จะเข้าไปในลูปแสดงผลครับ ซึ่งเราต้องการแสดงผลค่าในแม่ a ดังนั้นเราจึงต้องแสดงผลค่าตั้งแต่ a x 0  ถึง a x12  เราจึงเซ็ท i เริ่มต้นที่ 0 และทำจนถึง i<=12ซึ่งการทำแต่ละรอบ มันจะไปดึงค่าจาก table[a][i] มาแสดงผล สมมติว่า aเป็น 5 ในลูปรอบแรก i เป็น 0 มันก็จะแสดงผลค่าของ table[5][0] ซึ่งก็คือ 0ทำไปเรื่อยๆ สมมติทำไปจน i เป็น 7 มันก็จะแสดงผล table[5][7] ซึ่งก็คือ 35 ไปเรื่อยๆจน i เป็น 12

ตัวอย่างการรัน

5
0
5
10
15
20
25
30
35
40
45
50
55
60

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

พยายามเข้านะครับ ^ ^