การสร้างชนิดข้อมูล ก่อนจะศึกษาชนิดข้อมูลแบบโครงสร้างและยูเนียนนั้น จะต้องรู้จักคำสั่งในการสร้างชนิดข้อมูลก่อน เพราะข้อมูลแบบโครงสร้างและยูเนียน จะใช้คำสั่งนี้สร้างขึ้นมา นั่นก็คือ typedef ผู้ใช้จะสามารถสร้างข้อมูลใหม่จากขนิดข้อมูลพื้นฐานที่มีอยู่เดิมแล้ว โดยรูปแบบคำสั่งของ typedef ดังนี้ รูปแบบ Typedef [ชนิดข้อมูล] [ชื่อชนิดข้อมูลใหม่]ตัวอย่างข้างล่างนี้เป็นการสร้างและใช้ชนิดข้อมูลนั้นๆ
typedef char*STRING;
STRING stringPtrAry[20];
ตัวอย่างด้านบน ในบรรทัดแรก แสดงการสร้างชนิดข้อมูลขึ้นมาใหม่หนึ่งตัว ให้เป็นชนิดข้อมูล STRING และบรรทัดที่ 2 เป็นการประกาศตัวแปรที่ชื่อ stringPtrAry โดยให้มีชนิดข้อมูลเป็น STRING และมีขนาดเป็น 20 ซึ่งตัวแปรที่ชื่อ stringPtrAry ก็จะมีลักษณะเหมือนกับสตริงที่ศึกษากันในบทที่ผ่านมา ข้อมูลแบบโครงสร้าง ชนิดข้อมูลแบบโครงสร้าง (Structrue) คือ การรวมตัวแปร ที่มีชนิดข้อมูลหลายแบบมารวมกันให้เป็นโครงสร้างเดียวกัน แล้วโครงสร้างนั้นก็จะมีชื่อประจำตัวของโครงสร้างนั้นด้วยแต่ละตัวแปรในโครงสร้าง จะเรียกว่าสมาชิก ซึ่งในหนึ่งโครงสร้างนั้นสามารถมีตัวแปรหรือสมาชิกได้ไม่จำกัด และแต่ละสมาชิกมีหน่วยความจำของตัวเอง
ในรูปที่ 11-1 มีอยู่ 2 ตัวอย่าง ตัวอย่างแรกเป็นโครงสร้างชื่อ fraction ซึ่งจะมีสมาชิก 23 สมาชิก และตัวอย่างที่ 2 จะเป็นโครงสร้างที่ชื่อ student ซึ่งจะมีสมาชิก 3 สมาชิก
การสร้างและกำหนดลักษณะของโครงสร้าง
การสร้างข้อมูลแบบโครงสร้างสามารถทำได้ 2 แบบ คือการสร้างตัวแปรเป็นโครงสร้างและการสร้างโครงสร้างเป็นชนิดข้อมูลใหม่
การสร้างตัวแปรเป็นโครงสร้าง การสร้างตัวแปรเป็นโครงสร้าง จะมีรูปแบบดังนี้
struct { [รายชื่อสมาชิก] } [ชื่อของโครงสร้าง];
ตัวอย่างด้านล่างนี้ เป็นตัวอย่างโครงสร้างที่ชื่อ student ซึ่งภายในของโครงสร้างนี้จะมีสมาชิกดังนี้ id,name และ gradePoints
Struct
{
char id[10];
char name[26];
int gradePoints;
}student;การสร้างโครงสร้างเป็นชนิดข้อมูลใหม่ การสร้างโครงสร้างเป็นชนิดข้อมูลใหม่ ซึ่งโดยการใช้โครงสร้างจะนิยมใช้แบบนี้ เพราะโครงสร้างที่สร้างขึ้น จะเป็นชนิดข้อมูลใหม่อีกชนิดหนึ่งซี่งสามารถนำสร้างตัวแปรได้ โดยมีรูปแบบดังนี้
Typedef struct { [รายชื่อสมาชิก ]} [ชื่อชนิดข้อมูลใหม่];
ตัวอย่างด้านล่างนี้ เป็นตัวอย่างตัวแปรแบบโครงสร้างที่ชื่อ STUDENT ภายในของโครงสร้างจะมีสมาชิก id,name และ gradePoints พร้อมกับสร้างตัวแปร aStudent ให้มีโครงสร้างตามโครงสร้าง STUDENT และการส่งค่าโดยให้มีพารามิเตอร์มีชนิดข้อมูลเป็น STUDENT ด้วย
Typedef struct
{
char id[10];
char name[26];x
}STUDENT;
STUDENT aStudent;
Void printStudent (STUDENT Stu);การกำหนดค่าเริ่มต้น
ผู้ใช้สามารถกำหนดค่าเริ่มต้นให้กับโครงสร้างได้ ในรูปที่ 11-2 แสดง 2 ตัวอย่างของการกำหนดค่าเริ่มต้นให้กับโครงสร้าง ตัวอย่างแรกเป็นการกำหนดค่าให้กับแต่ละสมาชิก ส่วนตัวอย่างที่ 2 เป็นการกำหนดค่าให้บางสมาชิกของโครงสร้าง โดยค่าที่จะกำหนดให้จะเก็บลงในสมาชิก เรียงตามลำดับของโครงสร้างที่สร้างไว้ แต่ถ้าเป็นการกำหนดค่าบางสมาชิก ในสมาชิกที่ ไม่ได้ถูกกำหนดจะมีค่าเป็นค่ามาตรฐานของชนิดข้อมูลนั้น โดยที่ถ้าสมาชิกนั้นเป็นชนิดข้อมูลแบบ integer และ float จะมีค่าเป็น 0 และถ้าเป็น character และ string จะเป็น ‘’
รูปที่ 11-2 การกำหนดค่าเริ่มต้นให้กับโครงสร้างการเข้าถึงโครงสร้าง
หลังจากที่สร้างโครงสร้างได้แล้ว ต่อมาก็ศึกษาการเข้าถึงสมาชิกแต่ละตัวในโครงสร้างที่สร้างขึ้น ซึ่งผู้ใช้สามารถที่จะเข้าถึงและกระทำต่อสมาชิกภายในโครงสร้างได้ โดยตัวอย่างการเข้าเข้าถึงสมาชิแต่ละสมาชิกในโครงสร้าง Student ได้แสดงตัวอย่างด้านล่างนี้
aStudent.id
aStudent.name
aStudent.gradePointsในรูปที่ 11-13 เป็นการเรียกใช้สมาชิกแต่ละสมาชิกของโครงสร้าง SAMPLE ในรูปที่ 11-2
Sam 2 |
รูปที่ 11-3 การเรียกใช้สมาชิกแต่ละสมาชิกในโครงสร้าง SAMPLEผู้ให้สามารถใช้คำสั่งเงื่อนไขเพื่อหาค่าได้ โดยมีเงื่อนไขอยู่ว่า ถ้าค่าใน u มีค่าเท่ากับ A ให้นำค่าสมาชิก x มาบวกกับสมาชิก y แล้วเก็บค่าไว้ในสมาชิก x โดยชุดคำสั่ง ได้แสดงข้างล่าง
If (sam2.u=’A’)
Sam2.x + =sam2.y;และผู้ใช้ยังสามารถที่จะรับค่าจากคีย์บอร์ดเข้าสู่สมาชิกต่างๆ ในโครงสร้าง ในตัวอย่างจะใช้คำสั่ง sanf รับค่าเข้าสู่สมาชิกแต่ละตัวในตัวแปร sam1 ที่มีชนิดเป็นโครงสร้าง student
scanf(“%d %d %f %c”,
&sam1.x,&samt.y,%sum1.t,&sum1.y);โปรแกรมที่ 11-1 เป็นโปรแกรมที่ใช้คูณ 2 fractions และพิมพ์ค่าออกมา
#include<stdio.h> #include<conio.h> typedet struct { clrscr(); int numerators; int denominator; } FRACTION; int main(void) { FRACTION fr1; FRACTION fr2; FRACTION res; printf(“Write the first fraction in the form of x/y:”); scanf(“%d/%d”, &fr1.numerator, &fr1.denominator); printf(“Write second fraction in the form of x/y:”); scanf(“%d /%d”,&fr2.numerator, &fr2.denominator); res.numerator = fr1.numerator * fr2.numerator; res.denominator= fr1.denominator * fr2.denominator; printf(“\The result of %d/%d* %d/%d is %d/%d”; fr1.numerator,fr1.denominator; fr2.numerator,fr2.denominator; res.numertor,res.denominator); getch(); return 0; } ผลลัพธ์ที่ได้ : Write the first fraction in the form of x/y: 2/6 Write second fraction in th from of x/y: 7/4 The result of 2/6*7/4 is 14/24 |
ถ้าผู้ใช้มีตัวแปรโครงสร้างที่มีโครงสร้างเหมือนกัน ผู้ใช้สามารถที่จะคัดลอกข้อมูลจากตัวแปรหนึ่งไปไว้ในอีกตัวแปรหนึ่งได้โดยใช้เครื่องหมาย = ในรูปที่ 11-4 แสดงการคัดลอกข้อมูลจาก sam1 ไปไว้ใน sam2
ก่อน
Sam2 sam1
Sam2 sam1 หลัง |
รูปที่ 11-4 แสดงการคัดลอกโครงสร้างพอยเตอร์ของโครงสร้าง
ผู้ใช้สามารถใช้พอยเตอร์กับโครงสร้างได้เหมือนกัน ซึ่งในรูปที่ 11-5 แสดงการใช้พอยเตอร์กับโครงสร้าง
รูปที่ 11-5 แสดงการใช้พอยเตอร์กับโครงสร้าง ซึ่งในขั้นตอนแรกจะต้องสร้างพอยเตอร์ ให้มีโครงสร้างตามโครงสร้างของตัวแปรที่ต้องการก่อนSAMPLE *ptr;
จากนั้นก็กำหนดให้พอยเตอร์ตัวนั้นชี้ไปยังตัวแปรโครงสร้างที่ต้องการ
ptr=&sam1;
และเมื่อต้องการใช้สมาชิกต่างๆในโครงสร้างที่พอยเตอร์ชี้ไปก็สามารถทำได้ดังนี้
(*ptr).x (*ptr).y (*ptr).t (*ptr).uที่ต้องใช้วงเล็บ เพราะเครื่องหมายวงเล็บมีลำดับความสำคัญมากกว่าเครื่องหมายจุดและถ้าไม่ใส่วงเล็บความหมายของตัวแปรจะเปลี่ยนไปอีกแบบหนึ่งดังแสดงในรูปที่ 11-6
รูปที่ 11-6 แสดงการใช้พอยเตอร์แบบที่ถูกและแบบที่ผิด
การใช้พอยเตอร์กับโครงสร้างนั้น จะมีวิธีใช้อีกแบบนอกจากวิธีแบบนอกจากวิธีที่ผ่านทมาแล้ว โดยวิธีที่ผ่านมาแล้วเรียกว่า Indirection (ตัวอย่าง (*ptr).x) แล้วยังมีอีกวิธีหนึ่งคือ Selection โดยวิธีนี้จะใช้เครื่อง -> แสดงในรูปที่ 11-7
รูปที่ 11-7 แสดงการใช้พอยเตอร์โดยวิธี Selectionในโปรแกรมที่ 11-2 เป็นโปรแกรมจำลองการทำงานของนาฬิกา ซึ่งมีโครงสร้างอยู่ 1 ตัวโดยมี 3 สมาชิก คือ ชั่วโมง, นาที และวินาที และมี 2 ฟังก์ชั่น ฟังก์ชั่นแรกคือ ฟังก์ชั่น increment เป็นตัวคำนวณเวลา และฟังก์ชั่นที่ 2 คือ ฟังก์ชั่น show เป็นที่ใช้แสดงเวลาออกมา
โปรแกรมที่ 11-2 โปรแกรมจำลองการทำงานของนาฬึกาโดยใช้พอยเตอร์
include<stdio.h> include<conio.h> typedet struct { clrscr(); int hr; int min; int ser; }CLOCK; void increment(CLOCK*clock); void show(CLOCK* clock);int main (void) { CLOCK clock={14,38,56}; int i; for(i=o; i<o;++) { increment (&clock); show (&clock); } return 0; { void increment (CLOCK*clock) { (clock->sec)++; if(clock->min)++; { clock->min=0; (clock->hr)++; if(clock->hr==24) clock->hr=0; } } } void show(CLCOCK* clock) } printf(“%02d:%02d:%2d:\n clock->hr,clock->min,clock-<sec”); getch(); return; } |
ผลลัพธ์ที่ได้: 14:38:57 14:38:58 14:38:59 14:39:00 14:39:01 14:39:02 |
โครงสร้างซ้อนโครงสร้างผู้ใช้สามารถที่สร้างโครงสร้างให้มีสมาชิกภายในเป็นโครงสร้าง และสมาชิกที่เป็นโครงสร้างก็สามารถมีได้ไม่จำกัดจำนวน
ตัวอย่าง สมมุติต้องการมีโครงสร้างที่ชื่อ stamp โดยต้องการจะเก็บ date และ time ไว้ภายใน date จะต้องเก็บ month,day และ year ส่วน hour,minute และ second ซึ่งโครงสร้างของ stamp แสดงในรูปที่ 11-8
รูปที่ 11-8 แสดงโครงสร้างซ้อนโครงสร้าง การประกาศโครงสร้างซ้อนโครงสร้าง
การประกาศโครงสร้างซ้อนโครงสร้างนั้น โดยจะใช้โครงสร้างจากรูปที่ 11-8 มาสร้างซึ่งสามารถทำได้ดังนี้
typedet struct
{
int month;
int day;
int year;
}DATE;
typedef struct
{
int hour;
int min;
int sec;
} TIME
typedef struct
{
DATE date;
TIME time;
}STAMP;
STAMP stamp;การเข้าถึงโครงสร้างซ้อนโครงสร้าง เมื่อใดที่ผู้ใช้ต้องการจะเข้าถึงสมาชิกในโครงสร้าง จะต้องเรียกเข้าจากระดับสูงสุดไล่ลงไปยังจุดต่ำสุด ซึ่งตัวอย่างด้านล่างเป็นการเข้าโครงสร้าง stamp
stamp
stamp.date
stamp.date.month
stamp.date.day
stamp.date.year
stamp.time
stamp.time.hour
stamp.time.min
stamp.time.secการกำหนดค่าเริ่มต้นโครงสร้างซ้อนโครงสร้างการกำหนดค่าเริ่มต้นให้กับโครงสร้างซ้อนโครงสร้าง จะมีกฎอยู่ว่า โครงสร้างที่อยู่ภายในโครงสร้างหลักจะต้องกำหนดค่าอยู่ในวงเล็บปีกกา และสมาชิกภายในโครงสร้างนั้นจะต้องคั่นด้วยเครื่องหมายลูกน้ำเท่านั้น ถ้าในโครงสร้างหลักมีสมาชิกข้างในเป็นโครงสร้างหลายสมาชิกจะต้องคั่นระหว่างสมาชิกด้วยเครื่องหมายลูกน้ำด้วย ดังเช่นตัวอย่างด้านลางเป็นกำหนดค่าเริ่มต้นให้กับโครงสร้าง stamp
STAMP stamo={{05,10,1936},{23,45<00}};โครงสร้างที่มีอาร์เรย์เป็นส่วนสมาชิกการประกาศโครงสร้างที่มีอาร์เรย์เป็นสมาชิก โครงสร้างสามารถมีอาร์เรย์เป็นสมาชิกได้ โดยการประกาศนั้นก็เหมือนกับการประกาศอาร์เรย์ทั่วไป สามารถดูได้ในรูปที่ 11-9
การเข้าถึงอาร์เรย์ในโครงสร้างนั้น ก็สามารถทำได้กับสมาชิกที่มีชนิดข้อมูลแบบต่างๆแต่อาร์เรย์จะต้องมีลำดับหรือ Index ด้วย ตัวอย่างในถัดไปเป็นการเข้าถึงสมาชิกที่เป็นอาร์เรย์ในรูปที่ 11-9
student
student.name
student.name[i]
student.midterm
student.midterm[i]
student.final
รูปที่ 11-9 แสดงการประกาศอาร์เรย์ในโครงสร้าง ข้อมูลแบบยูเนียน ข้อมูลแบบยูเนียน (Union) เป็นข้อมูลที่มีลักษณะคล้ายกับข้อมูลแบบโครงสร้าง แต่ตัวแปรหรือสมาชิกต่างๆ ในยูเนียนนั้น จะใช้หน่วยความจำเดียวกัน คือจะมีตัวแปรหรือสมาชิกใดสมาชิกหนึ่งเท่านั้นที่ใช้หน่วยความจำในช่วงเวลานั้น
รูปที่ 11-10 แสดงการประกาศและลักษณะของยูเนียน
โปรแกรมที่ 11-3 แสดงการใช้ SH_CH2 เพื่อแสดงค่าของ 1 ตัวเลขและ 2 ตัวอักษรซึ่งจะแสดงให้เห็นถึงผลกระทบของการใช้งานยูเนียนที่ว่า สมาชิกทั้งหมดจะใช้หน่วยความจำที่เดียวกัน โปรแกรมที่ 11-3 แสดงผลกระทบของการใช้ยูเนียน
#include<stdio.h> #include<conio.h> typedef union { clrscr(); short num; char chAry[2]; }SH_CH2; int main(viod) { SH_CH data; data.num=16706; printf(“Short: %hd\m”,data.num); printf(“Ch[0]: %c\n”,data.chAry[0]); printf(“Ch[1]: %c\n”,data.chAry[1]); getch(); return 0; } |
ผลลัพธ์ที่ได้: Short : 115 Ch[0] : A Ch[1] : B |
การเข้าถึงยูเนียน
ในการเข้าข้อมูลแบบยูเนียนนั้นก็จะเหมือนกับการเข้าถึงข้อมูลแบบโครงสร้าง โดยตัวอย่างด้านล่างจะเป็นการเข้าถึงยูเนียน SH_CH2 ในรูปที่ 11-10
data.num
data.chAr7y[0]
Design by Pratya |