พื้นฐานโปรแกรมภาษา C
!! "); } บรรทัดแรก #include 
!! "); ซึ่ง printf เป็น Function ในภาษา C ทำหน้าที่ให้โปรแกรม ทำการแสดงผลออกทางหน้าจอว่า Hello World
!! และทุกครั้ง ผู้พัฒนาจะต้องทำการจบคำสั่งหรือ Statement ด้วยเครื่องหมาย semi-colon ; ดังนั้นรูปแบบของการเขียนโปรแกรม จึงเขียนออกมาในรูปแบบดังนี้ // ข้อความที่อยู่ข้างหลังเครื่องหมาย // จะเป็นคำอธิบายโปรแกรม #include
หน้าที่ 2 - ตัวแปร (Variables)
int i, j, count; float sum, product; char ch; bool passed_exam;มาถึงตอนนี้ เราก็จะสามารถปรับปรุงการเขียนโปรแกรมแบบง่ายๆ ได้ดังนี้
#includeจาก code ข้างบน ผู้อ่านจะเห็น %d เมื่อมีการเรียกใช้ฟังก์ชัน scanf และ printf ทั้งนี้ %d จะเป็น format ที่ใช้บ่งบอกชนิดของตำแหน่ง (Place Holders) ที่จะมีการส่งข้อมูล โดยในที่นี้ %d หมายถึงตำแหน่งของจำนวนเต็ม หรือ int นั่นเอง ตัวอย่างของ Place Holders อื่นๆ สามารถแสดงได้ดังตาราง คราวนี้ลองมาดูตัวอย่างของการใช้ Place Holdersmain() { int its_price; printf("How much is that ? "); scanf("%d", &its_price); printf("oh! %d ?, hmmm...., too expensivenn",its_price); }
printf("C=%f, F=%f",cel,fah);
printf("He wants to score %d goals today",9);
เมื่อ % เป็นการบ่งบอกตำแหน่งเริ่มต้นของ Place Holder จากนั้น ตัวอักษร f ตัวแรก จะบ่งบอกถึง ตัวแปรcel ว่ามีค่าเป็นจำนวนจริง (Float) ส่วน f ตัวทีสอง จะบ่งบอกคอมไพเลอร์ว่า ตัวแปร fah ก็มีค่าเป็นจำนวนจริงเช่นกัน นอกจากนี้ Place holder %d และ %f ยังสามารถใช้กับการกำหนดตำแหน่งตัวเลขตามต้องการได้ ยกตัวอย่างเช่น สมมุติให้ x=235; และ y=6.54321;
change = x1 - x2; mean = (x1 + x2)/2; x = x + 1;ตอนนี้เราลองมาเขียนโปรแกรมอย่างง่าย เพื่อทำการแก้ปัญหาทางคณิตศาสตร์ ด้วยการแปลงค่า อุณหภูมิ ในหน่วยของ ฟาเรนไฮต์ เป็น เซลเซียส เมื่ออุณหภูมิในหน่วยฟาเรนไฮต์ มีค่า = 85 และเป็นที่ทราบกันดีว่า ความสัมพันธ์ระหว่าง องศาฟาเรนไฮต์ และ เซลเซียส สามารถเขียนได้อยู่ในรูปของสมการ

#includeอีกตัวอย่าง ของโปรแกรม การบวกค่าจำนวนเต็ม 2 จำนวนเข้าด้วยกัน แล้วแสดงผลลัพธ์ออกทางหน้าจอ การเขียนโปรแกรมเพื่อแก้ปัญหานี้ สามารถเขียนได้ดังนี้void main() { float F; float C; F = 85; C = 5*(F-32)/9; printf("the result is %f",C); }
#includeจากตัวอย่างการเขียนโปรแกรมข้างต้น จะเห็นว่ามีการคำนวณทางคณิตศาสตร์เข้ามาเกี่ยวข้อง คราวนี้เราลองมาดู การคำนวณในภาษา C กันว่าจะเขียนกันได้อย่างไรบ้างvoid main() { int N1, N2, Sum; printf("please input an integer number : "); scanf("%d",&N1); printf("please input another integer number : "); scanf("%d",&N2); Sum = N1 + N2; printf("so, %d + %d = %d",N1,N2,Sum); }

หน้าที่ 3 - การเปรียบเทียบ แบบมีทางเลือก (Selection Structures)
if (x < y) a = x * 2; else a = x + y;ความหมายของ code ดังกล่าว หมายความว่า ถ้า ค่า x มีค่าน้อยกว่า y แล้ว a = x*2 แต่ถ้า x มีค่ามากกว่าหรือเท่ากับ y แล้ว a = x+y นั่นเอง รูปแบบของเงื่อนไข ส่วนใหญ่จะอยู่ในรูป ตัวแปร โอเปอเรเตอร์ ตัวแปร โอเปอเรเตอร์ที่กล่าวถึงนี้จะมีอยู่ 2 แบบ ด้วยกันคือ โอเปอเรเตอร์สัมพันธ์ (Relational Operator) และ โอเปอเรเตอร์ลอจิก (Logical Operator) โอเปอเรเตอร์สัมพันธ์ที่ใช้ในภาษา C มีดังต่อไปนี้

if ( condition1 )
statement1 ;
else
if ( condition2 )
statement2 ;
. . .
else if ( condition-n )
statement-n ;
else
statement-e ;
ยกตัวอย่างของโปรแกรม Nested if สามารถเขียนได้ดังนี้if (x < 0.25)
count1++;
else if (x < 0.5)
count2++;
else if (x < 0.75)
count3++;
else
count4++;
นอกจากรูปแบบของ if-else แล้ว เรายังสามารถใช้เครื่องหมาย ? มาประยุกต์ในการเขียน code เพื่อให้ได้ความหมายเดียวกันกับ if-else ดังแสดงให้เห็นดังนี้if (x < y) a = x * 2; else a = x + y;สามารถเขียนได้ในอีกรูปแบบหนึ่งคือ a = x < y ? x*2: x+y ; // ซึ่งจะให้ความหมายเดียวกันกับ code ข้างบนนั่นเอง ในบางครั้งที่เราต้องเขียนโปรแกรมแบบมีทางเลือก โดยบางครั้งเราต้องการให้มีทางเลือกมากว่า 2 ทาง Nested if เป็นวิธีหนึ่งที่สามารถใช้แก้ปัญหาได้ แต่เพื่อให้ง่ายขึ้น ในภาษา C เราจึงสามารถใช้คำสั่ง switch ได้ โดยรูปแบบการเขียน คำสั่ง switch สามารถเขียนให้อยู่ในรูป
switch (selector)
{
case label1: statement1;
break;
case label2: statement2;
break;
...
case labeln: statementn;
break;
default: statementd; // optional
break;
}
โดยที่ selector จะต้องเป็นจำนวนเต็ม ตัวอักษร หรือผลลัพธ์ของการกระทำที่ให้เลขจำนวนเต็มหรือตัวอักษร ตัวอย่างของการเขียน code โดยมีการเรียกใช้คำสั่ง switch สามารถเขียนได้ดังนี้ switch (i) { case 1 : grade = 'A'; break; case 2 : grade = 'B'; break; case 3 : grade = 'c'; break; default : printf("%c not in range", i); break; } โดยหลักการของ switch คือ compiler จะทำการเปรียบเทียบค่าของ selector เทียบกับ label ถ้าไม่ตรงกับ label ใดๆ ก็จะเข้าไปทำในคำสั่งของ default นอกจากนี้ การใส่คำสั่ง break หรือไม่มีคำสั่ง break ก็จะให้ผลลัพธ์ที่แตกต่างกัน ดังแสดงให้เห็นดังตัวอย่างต่อไปนี้ (ทดลอง Run แล้วจะเห็นความแตกต่าง)

หน้าที่ 4 - การเขียนโปรแกรมแบบ วนซ้ำ (Loop)
sum = 0.0;
x = 5;
while (x > 0.0)
{
sum += x;
x = x 1;
}
ในที่นี้จะเห็นว่า ค่า x มีค่าเริ่มต้นเท่ากับ 5 ซึ่ง 5 > 0 เงื่อนไขของคำสั่ง while เป็นจริง จึงทำคำสั่งถัดมาคือ sum += x; หมายความว่า sum = sum + x = 5 จากนั้นค่า x ก็มีค่าลดลงไป 1 เหลือ 4 ก็จะทำการ check เงื่อนไขว่า 4 > 0 หรือไม่ เมื่อเงื่อนไขเป็นจริง ก็จะทำการวนซ้ำ sum ก็จะมีค่าเป็น 5 + 4 = 9 และ x ก็จะมีค่าลดลงเหลือ 3 และดำเนินการวนซ้ำเช่นนี้จนกระทั่ง x มีค่าเป็น 0 ซึ่งค่า 0 ไม่ได้มีค่ามากกว่า 0.0 เงื่อนไขจึงเป็นเท็จ โปรแกรมจึงจะจบการวนซ้ำ คราวนี้เราลองมาดูตัวอย่างของการใช้คำสั่ง while ในการเขียนโปรแกรมแบบวนซ้ำ และผลลัพท์ที่ได้x=0;
while( x <=2 ){
printf("%d %dn",x, x*2);
}
ผลลัพท์ที่ได้จะได้ดังนี้
0 0
0 0
0 0
: :
0 0 (infinite loop)
การที่ผลลัพท์ออกมาเช่นนี้ ก็เนื่องจากว่า x มีค่าเริ่มต้น 0 และเงื่อนไข x <= 2 เป็นจริงตลอด โปรแกรมจึงทำการพิมพ์ค่า 0 0 ออกมา และเนื่องจากค่า x ไม่มีการเปลี่ยนแปลง เงื่อนไขจึงเป็นจริงตลอด โปรแกรมจึงแสดงผลบนหน้าจอโดยไม่หยุดนั่นเอง อีกตัวอย่างของการใช้งาน while ในการเขียนโปรแกรมแบบวนซ้ำ แสดงได้ดังนี้scanf(%d,&n);
a = 10;
while (a > n) {
printf(%dn,a);
a = a-1;
}
ผลลัพท์ของโปรแกรมจะสามารถแสดงให้เห็นได้ดังนี้10 9 8 7คราวนี้เราลองมาแก้โจทย์ปัญหา การหาค่า ห.ร.ม (หารร่วมมาก) ของตัวเลข 2 ตัวใดๆ โดยอัลกอริทึม Euclidean โดยอัลกอริทึมดังกล่าว จะทำการแปลงค่าตัวเลข 2 ตัวเลขบวกใดๆ (m, n) เป็นค่า (d, 0) โดยการนำตัวเลขที่มีค่ามาก นำมาหารด้วยตัวเลขที่มีค่าน้อยกว่า นำค่าเศษที่หารได้มาแทนตัวเลขที่มีค่ามากกว่า ทำเช่นนี้จนกระทั่งได้ค่าเศษจากการหารมีค่าเป็น 0 ตัวเลขอีกตัวก็จะเป็นค่า ห.ร.ม. ยกตัวอย่างเมื่อเราทำการ Run โปรแกรม จะได้ผลดังนี้ Enter two positive integers: 532 112 The g.c.d. of 532 and 112 is 28 คราวนี้เราลองมาดูการเขียนโปรแกรมเพื่อแก้ปัญหาดังกล่าวข้างต้น สามารถเขียนได้ดังนี้
#includeการดำเนินการทางคณิตศาสตร์ สามารถเขียนให้อยู่ในรูปแบบสั้นๆ ได้ ดังตัวอย่างในตารางดังนี้void main() { int A, B, start; printf("Enter two positive intergers: "); scanf("%d %d", &A, &B); if(A < B) start = A; else start = B; while(((A%start) != 0)||((B%start) != 0)) { start = start-1; } printf("The g.c.d of %d and %d is %dn", A, B, start); }

for ( count=0 ; count < 10 ; count++)
{
printf(count = %dn,count);
}
ใน code ข้างต้น ตัวแปร count จะเริ่มต้นจากค่า 0 ซึ่งค่า 0 มีค่าน้อยกว่า 10 ก็จะทำคำสั่ง print ค่าของตัวแปร count จากนั้นค่า count ก็จะเพิ่มค่าเป็น 1 เงื่อนไข count < 10 ก็ยังคงเป็นจริง ก็จะทำการพิมพ์ ค่าของตัวแปร count วนซ้ำเช่นนี้ จนกระทั่ง count มีค่าเพิ่มขึ้นจนเป็น 10 เงื่อนไขก็จะเป็นเท็จ และจบโครงสร้างของการวนซ้ำ การเปลี่ยนแปลงค่าของตัวแปร อาจจะมีการเปลี่ยนแปลงมากกว่า 1 ค่า ยกตัวอย่างเช่นfor ( count=0 ; count < 10 ; count += 2) // ตัวแปร count มีค่าเปลี่ยนแปลงเพิ่มขึ้นครั้งละ 2
{
printf(count = %dn,count);
}
for ( count=10 ; count > 5 ; count -= 2) // ตัวแปร count มีค่าเปลี่ยนแปลงลดลงครั้งละ 2
{
printf(count = %dn,count);
}
นอกจากนี้เรายังสามารถใช้ตัวแปร เป็นการกำหนด ค่าเริ่มต้น เงื่อนไข และ เปลี่ยนแปลงได้ ยกตัวอย่างเช่นstart = 0; end = 20; step=3;
for ( count=start ; count < end ; count += step)
{
printf(count = %dn,count);
}
คราวนี้ เราลองมาทดลองเขียนโปรแกรม โดยให้โปรแกรม สามารถรับค่าตัวเลขใดๆ และแสดงค่าในรูปแบบดังตัวอย่างต่อไปนี้
Input the number > 4 0 0 1 0 1 2 0 1 2 3 0 1 2 0 1 0เราสามารถแก้ปัญหาข้างต้น โดยใช้โครงสร้างการเขียนโปรแกรมแบบวนซ้ำดังต่อไปนี้
#includeโครงสร้างการเขียนโปรแกรมแบบวนซ้ำโดยใช้คำสั่ง do-while รูปแบบของการเขียน code สำหรับโปรแกรมแบบวนซ้ำที่ใช้ do-while สามารถเขียนให้อยู่ในรูปทั่วไปได้ดังนี้ do statement while ( เงื่อนไข ); ตัวอย่างของโครงสร้าง do-while สามารถเขียนได้ดังนี้void main() { int number, i, j; printf("Enter number: "); scanf("%d", &number); for(j= 0; j< number; j++) { for(i=0; i<= j; i++) { printf("%d ", i); } printf("n"); } for(j= number-1; j>= 0; j--) { for(i=0; i< j; i++) { printf("%d ", i); } printf("n"); } }
sum = 0.0;
scanf(%f, &x);
do {
sum += x;
scanf(%f, &x);
}
while (x > 0.0);
โปรแกรมข้างต้นจะทำการอ่านค่าจะ keyboard เมื่อ User พิมพ์ค่าที่มีค่ามากกว่าศูนย์ ก็จะทำการบวกค่าเหล่านี้ไปที่ตัวแปร sum จนกระทั่ง User พิมพ์ ตัวเลข 0 หรือค่าที่น้อยกว่า ศูนย์ ทำให้เงื่อนไขเป็นเท็จ และโปรแกรมจึงจะออกจากโครงสร้าง do-while คราวนี้เราลองมาเขียนโปรแกรมที่ใช้โครงสร้าง do-while โดยโจทย์กำหนดให้ว่า ให้โปรแกรมสามารถรับค่าตัวเลขใดๆ (X) และ แสดงผลของตัวเลข ระหว่าง 0 ถึง X ที่สามารถหารด้วย 4 ลงตัว#includeตอนนี้ผู้อ่านก็คงจะรู้จัก การเขียนโปรแกรมแบบวนซ้ำกันแล้วนะ ต่อไป เราก็จะไปเรียนรู้เกี่ยวกับการเขียนโปรแกรมแบบแยกเป็นโมดูลกันvoid main() { int number, i; printf("enter the numbern"); scanf("%d", &number); i = 0; do { if((i % 4) == 0) printf("%d ", i); i++; } while(i <= number); }
หน้าที่ 5 - ฟังก์ชัน (Functions) และ โปรแกรมแยกเป็นโมดูล (Modular Programming)


{
การประกาศตัวแปรเฉพาะที่; [local-definitions declaration;]
กลไกการทำงานของฟังก์ชัน; [function-implementation;]
การคืนค่าถ้าชนิดฟังก์ชันไม่เป็น void; [return statement if function type NOT void]
}
ยกตัวอย่างเช่น
float distance(float x, float y) // float คือ ชนิดของฟังก์ชัน ส่วน distance คือ ชื่อฟังก์ชัน
{ // float x, float y คือ บัญชีตัวแปรร่วม
float dist; // float dist คือ การประกาศตัวแปรเฉพาะที่;
dist = sqrt(x*x+y*y); // dist = ระยะห่างระหว่างพิกัด (x,y) ไป (0,0)
return dist ;
}
ก่อนจะทำการเรียกใช้ฟังก์ชัน จำเป็นต้องมี การกำหนดฟังก์ชัน (function prototype) ซึ่งเป็น copy ของ function heading และมีข้อกำหนดดังนี้ 1) ตัวแปรร่วมในฟังก์ชัน ที่ประกาศไว้ และ ตัวแปรร่วมขณะเรียกใช้ฟังกชันนั้นต้องมีจำนวนเท่ากันและต้องมี type ตรงกัน มิฉะนั้นจะเกิด error ขึ้น 2) ต้องกำหนดการทำงานของฟังก์ชันก่อนการเรียกใช้ฟังก์ชัน ใน main function เพื่อให้ตัวแปรภาษารู้ว่าฟังก์ชันนี้ทำงานอย่างไร 3) แม้ฟังก์ชันที่ใช้จะไม่มีค่าตัวแปรร่วม ก็ต้องใส่วงเล็บ [ ( ) ] ไว้หลังชื่อฟังก์ชันเสมอ 4) การกำหนดฟังก์ชัน จะต้องกำหนดก่อนการใช้ Main function เพื่อให้ Main function ได้รับรู้ว่าฟังก์ชันดังกล่าวมีอะไรเป็นตัวแปรร่วม และ จะคืนค่าอะไรออกมา 5) กลไกการทำงานเต็มของฟังก์ชันย่อยจะแสดงหลังจากที่เรียก Main function แล้ว หรืออยู่ในไฟล์ที่แยกต่างหาก ซึ่งจะมีการแปรออกมาแล้วเชื่อมต่อกับ Main function การกำหนดฟังก์ชันจะมีลักษณะดังนี้float distance(float, float); // การกำหนดฟังก์ชัน [function prototype]
void main()
{
float x0 =
.,y0 =
;
float dist1 = distance(x0,y0);
}
float distance(float x, float y) // float คือ ชนิดของฟังก์ชัน distance คือ ชื่อฟังก์ชัน
{ // float x, float y คือ บัญชีตัวแปรร่วม
float dist; // float dist คือ การประกาศตัวแปรเฉพาะที่;
dist = sqrt(x*x+y*y);
return dist ;
}
ในการส่งผ่านตัวแปรเข้า ฟังก์ชัน (Passing argument) นั้นมีการเรียกได้ 2 แบบ คือ 1) ส่งผ่านตามค่า (Pass by Value) ซึ่งส่งผ่านค่า ลงในตัวแปรร่วมของฟังก์ชันโดยตรง 2) ส่งผ่านตามการอ้างอิง (pass by Reference) ซึ่งส่งผ่านค่า address ในหน่วยความจำของตัวแปร ให้กับตัวแปรร่วมของฟังก์ชัน ถ้ามีการเปลี่ยนแปลงข้อมูล ณ ตำแหน่งหน่วยความจำดังกล่าว ค่าที่ส่งให้ตัวแปรร่วมของฟังก์ชันก็จะเปลี่ยนด้วยตัวแปรที่เกี่ยวข้องกับฟังก์ชันคือ 1) ตัวแปรเฉพาะที่ (Local variables) เป็นตัวแปรที่อยู่และเปลี่ยนแปลงเฉพาะภายในฟังก์ชันที่เรียกใช้ตัวแปรดังกล่าว การเปลี่ยนแปลงภายนอกฟังก์ชันที่เรียกใช้ตัวแปรเฉพาะที่จะไม่มีผลต่อตัวแปรเฉพาะที่ดังกล่าว ดังตัวอย่างต่อไปนี้void test_locvar(int num)
{
int myvar; // Local variable fro this function
myvar = num;
}
void main()
{
int myvar, myvar_before, myvar_after; //Local variable for this function
myvar = 5;
myvar_before = myvar; // myvar_before = 5;
test_locvar(100); // call function
myvar_after = myvar; // myvar_after = 5;
}
2) ตัวแปรส่วนกลาง (Global variables) เป็นตัวแปรที่อยู่นอกฟังก์ชันซึ่งสามารถเปลี่ยนแปลงค่าภายในตัวแปรได้ตลอดเวลาเมื่อตัวแปรได้รับการเปลี่ยนแปลงโดยฟังก์ชัน ดังตัวอย่างต่อไปนี้int myvar; // Global varible
void test_locvar(int num)
{
myvar = 20;
}
void main()
{
int myvar_before, myvar_after; //Local variable fro this function
myvar = 5;
myvar_before = myvar; // myvar_before == 5;
test_locvar(100); // call function
myvar_after = myvar; // myvar_after == 20;
}
ฟังก์ชันมีหลายประเภทได้แก่ 1) ฟังก์ชันที่ไม่มี อาร์กิวเมนต์ และ ไม่คืนค่า เช่น ฟังก์ชัน void main() 2) ฟังก์ชันที่มี อาร์กิวเมนต์ แต่ ไม่คืนค่า เช่นฟังก์ชัน void do_something(float x, float y) ซึ่งจะทำงานตามที่ต้องการโดยอาศัยค่าอาร์กิวเมนต์ (ตัวแปร x,y) โดยไม่คืนค่าออกมา ฟังก์ชันดังกล่าวจะมีกลไกการับข้อมูลเข้าต่างหาก โดยไม่ต้องใช้ตัวแปรที่เป็น อาร์กิวเมนต์ 3) ฟังก์ชันที่ไม่มี อาร์กิวเมนต์ แต่ก็คืนค่า เช่น ฟังก์ชัน float do_something2() ค่าที่คืนมาได้จาก ตัวแปรเฉพาะที่และกลไกการคำนวณภายในฟังก์ชันดังกล่าว 4) ฟังก์ชันที่มี อาร์กิวเมนต์ และ คืนค่า เช่นฟังก์ชัน float distance(float x, float y) ฟังก์ชันดังกล่าว สามารถคืนค่า โดยไม่จำเป็นต้องใช้ตัวแปรเฉพาะที่ทำหน้าที่เป็นตัวแปรชั่วคราวในการคืนค่า ตัวอย่างเช่นfloat distance3D(float x, float y, float z)
{
return sqrt((x*x)+(y*y)+(z*z));
}
หน้าที่ 6 - อาเรย์ (Arrays)
Type ArrayName[size]; // Format of Blank array
Type ArrayNameInitialized[size] = {
}; // Format of initialized array
int a[5] = {0,0,0,0,0};
double air[5];
char vowel[] = {A,E,I,O,U};
ในกรณีใช้ตัวแปรดัชนี้ชี้ตำแหน่งข้อมูลในตาราง ค่าของตัวแปรที่จะชี้จะต้องอยู่ในช่วงระหว่าง 0 กับ N-1 โดยที่ N คือขนาดตารางอาเรย์ ดังตัวอย่างที่แสดงในภาพที่ 5.1
int a[4] = {9, 8, 7}; ซึ่งจะได้ค่าออกมาตรงกัย a[0] = 9; a[1] = 8; a[2] = 7; และ a[3] = 0;
กรณีที่ตารางมีหลายมิติ จะมีการเรียกใช้ตามรูปแบบตารางมิติเดียวต่อไปนี้
ตาราง 2 มิติ: type arrayname2D[size1][size2];
ตาราง 3 มิติ: type arrayname3D[size01][size02][size03];
การค้นข้อมูลในตารางอาเรย์นั้น สามารถเข้าถึงได้อย่างรวดเร็วไม่ว่าตารางจะใหญ่เพียงไหน เช่น
const int SIZE = 100; // #define SIZE 100 for C
float A[SIZE],B[SIZE],C[SIZE];
for(i = 0; i <= SIZE-1; i++)
{
C[i] = B[i] A[i];
}
ในการใช้ตัวแปรอาเรย์เป็นอาร์กิวเมนต์ให้ฟังก์ชันนั้น แบ่งได้หลายกรณีได้แก่ 1) กรณีที่จะเอาข้อมูลเฉพาะช่องตาราง จะมีการส่งผ่านข้อมูลในตารางอาเรย์ดังนี้void main()
{
float X[10], X[0] = 123.23, X[1] = 24.56, X[2] = 45.67;
float total = sum_element(X[0],X[1],X[2]);
}
float sum_element(float A, float B, float C)
{
return (A+B+C);
}
2) กรณีที่ใช้ข้อมูลทั้งตารางอาเรย์ การส่งผ่านข้อมูลในตารางลงในฟังก์ชันจะเป็นดังนี้void main()
{
float X[10], X[0] = 123.23, X[1] = 24.56, X[2] = 45.67;
float total = sum_element_array(X)
}
float sum_element_array(float A[])
{
int index; float Sum = 0;
for(index =0; index <= 3-1; index++)
{
Sum +=A[index];
}
return Sum;
}
3) กรณีที่ใช้ข้อมูลทั้งตารางเพื่อให้ได้ผลลัพธ์ออกมาเป็นตารางอาเรย์ให้ทำดังนี้void add_arrays(float ar1[], // input array 1
float ar2[], // input array 2
float ar_sum[], // Output array
int N) // Array Size
{
for(int i = 0; i <= N-1; i++)
{
ar_sum[i] = ar1[i] + ar[2];
}
}
การค้นหาข้อมูลในตาราง (Array searching) ในการค้นข้อมูลนั้นมักใช้ linear search หาข้อมูลในตารางตามที่ต้องการ โดยกำหนดเงื่อนไขว่า 1) ถ้าหาข้อมูลพบ ให้แสดงดัชนีของค่าที่ค้นพบ ก่อนออกจากวงรอบการค้นหา 2) ถ้าหาข้อมูลไม่พบ ให้ออกจากโปรแกรมแล้วคืนค่า ที่อยู่นอก ขอบเขต 0 N-1, N คือ ขนาดตารางอาเรย์ (โดยมากให้คืนค่า -1) การสับเรียงข้อมูลในตาราง (Array Sorting) การสับเรียงข้อมูลมีหลายวิธี ซึ่งจะกล่าวถึงในที่นี้พอสังเขปดังนี้ 1) Bubble Sort ซึ่งเขียนใช้งานง่ายแต่ สับตำแหน่งข้อมูลได้ผลช้าที่สุด ซึ่งมีกลไกดังนี้void BubbleSort(float list[], int N)
{
int i,j;
float temp;
for(i = N-1; i>=0; i--)
{
for(j = 1; j <=i; j++)
{
if(list[j-1] > list[j])
{
temp = list[j-1];
list[j-1] = list[j];
list[j] = temp;
}
}
}
}
2) Selection Sort ซึ่งจะเลือกค่าที่ยังไม่ได้สับเปลี่ยนที่น้อยที่สุดเป็นหลัก ในการสลับที่void SelectSort(float list[], int N)
{
int i,j, MinIndex;
float temp;
for(i = 0; i<=N-2; i--)
{
MinIndex = I;
for(j = i+1; j <=N-1; j++)
{
if(list[j] < list[MinIndex])
{
minIndex = j
}
temp = list[j-1];
list[j-1] = list[j];
list[j] = temp;
}
}
}
3) Insertion Sort ซึ่งจะเติมข้อมูลลงในตำแหน่งที่เหมาะสมในขั้นสุดท้าย ซึ่งจะต้องมีตัวแปรอาเรย์ อย่างน้อย 2 ตัว โดยที่อาเรย์ตัวแรกทำหน้าที่ เป็น List เก็บข้อมูล ต้นฉบับ (Source List) และอาเรย์ตัวหลังทำหน้าที่รับข้อมูลที่ผ่านการสับตำแหน่งแล้ว (Sorted List) ในการสับที่กันนั้น จะให้ข้อมูลปัจจุบันเคลื่อนผ่านข้อมูลที่ผ่านการสับตำแหน่งแล้ว จากนั้นจึงลงมือสลับข้อมูลอีกครั้งจนกว่าข้อมูลทั้งหมดจะเข้าที่void insert_sort(float data[], int Size)
{
int i,j;
float DatElement;
for(i=1;i<=Size-1;i++)
{
DatElement = data[i];
j = i;
while((j >= 1) && data[j-1] >DatElement)
{
data[j-1] = data[j];
j = j-1;
}
data[j] = DatElement;
}
}
หน้าที่ 7 - ตัวแปรพอยเตอร์ (Pointers)



int Num[20]; int *Ptr; การกำหนดค่าต่อไปนี้ถือว่าใช้ได้เหมือนกัน Ptr = Num; มีลักษณะเท่าเทียมกับ Ptr = &Num[0];ความแตกต่างจะเกิดขึ้นเมื่อ มีการกำหนดค่าตัวต่อไป โดยที่เราสามารถกำหนดค่าแอดเดรสใหม่ให้ตัวแปร Ptr ได้ทันที ขณะที่ ตัวแปร Num จะชี้ไปที่ตำแหน่งแรกของตัวแปรจำนวนเต็ม ซึ่งมี 20 ตำแหน่งเสมอ ดังนั้น ตัวแปร Ptr จึงเป็นตัวแปรพอยเตอร์ที่เปลี่ยนตำแหน่งการชี้ได้ (Variable Pointer) ขณะที่ตัวแปร Num หรือชื่อตัวแปรอาเรย์เป็นตัวแปรพอยเตอร์ที่ตำแหน่งการชี้คงที่ตายตัว (Constant pointer) ดังตัวอย่างต่อไปนี้
int Num[20]; int *y; int *Ptr; Ptr = Num; *(Ptr+1) จะแสดงค่า Num[1]; *(Ptr+i) จะแสดงค่า Num[i]; y = &Num[0]; y++; // ตัวแปรนี้จะชี้ไปที่ Num[1] เท่านั้นตัวอย่างต่อไปนี้แสดงให้เห็นถึงการ ใช้ตัวแปรพอยเตอร์ชี้ไปที่ตัวแปรตารางอาเรย์ ซึ่งผลที่ได้จะแสดงให้เห็นในภาพที่ 6.4

void main(void)
{
int i, j=1,k=2;
int *ptr1, *ptr2; // Declare both variables as integer pointers
float value[100], result[100];
float *ptr3, *ptr4; // Declare both variables as integer pointers
prt1 = &j; // Defining ptr1 pointing to j
ptr2 = &k; // Defining ptr2 pointing to k
ptr3 = value; // ptr3 contain the address for the 1st element of value
ptr4 = &value[0]; // ptr4 contain the address for the 1st element of value
// Value manipulation
*ptr1 = *ptr1+2 /* การบวกค่าที่ตัวแปรพอยเตอร์ ptr ชี้ไป อีก 2 */
*ptr2 = *ptr1 /* กำหนดให้ค่าที่ ตัวแปร ptr2 ชี้ เท่ากับค่าที่ตัวแปร prt1 ชี้ */
k = *ptr2 /* กำหนดให้ k มีค่าเท่ากับ ค่าที่ตัวแปร ptr2 ชี้ */
}
การเปลี่ยนแปลง ตัวแปรพอยเตอร์ด้วยวิธีการทางคณิตศาสตร์ สามารถทำได้ดังตัวอย่างต่อนี้float *ptr3, *ptr4; float table[100]; float Pi = 3.1415927;
ptr3 = &table[0]; // กำหนดให้ ptr3 เก็บค่าตำแหน่งแอดเดรส ของตาราง table ช่องแรก
ptr3++; // เปลี่ยนค่าตำแหน่งแอดเดรส ใน ptr3 เป็นแอดเดรสตาราง table ช่องที่2
*ptr3 = Pi; // ข้อมูลช่องที่ 2 ของตาราง table มีค่าเท่ากับ Pi
ptr3+=25; // กำหนดให้ ptr3 ชี้ไปที่ตำแหน่งแอดเดรสตาราง table ช่องที่ 26
*ptr3 = 2.2222; // ข้อมูล ตาราง table ช่องที่ 26 มีคาเท่ากีบ 2.2222
ptr3 = table; // กำหนดให้ ptr3 ชี้ไปที่ table ช่องแรก
for(int ii =0; ii < 100; ii++)
{
*ptr3++ = 37.0 // กำหนดให้ข้อมูลทุกช่องของ ตาราง table เท่ากับ 37
}
ptr3 = &table[0]; // ptr3 contain the address for the 1st element of value
ptr4 = &table[0]; // ptr4 contain the address for the 1st element of value
ข้อพึงระมัดระวังคือ เครื่องหมาย ++ และ - นั้นมีลำดับความสำคัญที่สูงกว่า * ดังนั้น *ptr++ มีค่าเท่ากับ *(ptr++) ซึ่งตัวแปรทั้ง 2 หมายถึงการเพิ่มตัวเลขตำแหน่ง แอดเดรส ไม่ใช้เพิ่มค่าที่ตัวพอยเตอร์ชี้ ส่วนกรณี *p++ = *q++ นั้น การกำหนดให้ค่าที่ตัวแปรพอยเตอร์ p มึค่าเท่ากับ ค่าที่ตัวแปรพอยเตอร์ q ชี้ จากน้นจึงมีการเลื่อนตำแหน่งแอดเดรสของตัวแปรพอยเตอร์ทั้ง 2 ไปอีก 1 ช่วง ดังตัวอย่างต่อไปนี้ *p = *q; p++; q++; ในการเตรียมพื้นที่ตารางแบบไดนามิกให้ตัวแปรพอยเตอร์นั้นทำได้ดังนี้ กรณี C: int *ptr; Ptr = (int *)malloc(6* sizeof(int)); กรณี C++: int *ptr; ptr = new int[6]; ส่วนการคืนหน่วยความจำเมื่อสิ้นสุดการทำงานของโปรแกรมทำได้ดังนี้ ซึ่งต้องทำทุกครั้งเมื่อใช้คำสั่งออกจากโปรแกรม มิฉะนั้นเครื่องคอมพิวเตอร์ จะเกิดอาการค้าง (Hang) เมื่อปิดโปรแกรมเพราะไม่ได้คืนหน่วยความจำอย่างที่ควรจะทำ กรณี C: free(ptr); กรณี C++: delete[] ptr; ตัวแปรพอยเตอร์และการเรียกฟังก์ชัน การเรียกฟังก์ชันมีหลายแบบ ได้แก่ 1) ฟังก์ชันที่ ไม่มีตัวแปรร่วมเป็นอาร์กิวเมนต์ และ ไม่คืนค่า (function with no parameter and no return value) ฟังกชันพวกนี้เพีบงแต่มีหน้าที่ทำงานอะไรบางอย่างตามที่ผู้เขียนโปรแกรมต้องการ เช่นกรณีฟังก์ชัน void skip3(void) เพื่อการกระโดดไปครั้งละ 3 บรรทัดเป็นต้น 2) ฟังก์ชันที่มีตัวแปรร่วมแต่ไม่คืนค่า ฟังก์ชันนี้จะทำงานตามค่าที่ตัวแปรร่วมกำหนด เช่นกรณีฟังก์ชัน void skip(int num) ซึ่งจะกระโดดครั้งละกี่บรรทัดตามจำนวนที่กำหนดลงในตัวแปร num 3) ฟังก์ชันที่ไม่มีตัวแปรร่วมแต่มีการคืนค่า ฟังก์ชันนี้มักจะให้ผู้ใช้โปรแกรมป้อนข้อมูลให้ฟังก์ชันจัดการประมวลผล ก่อนที่จะคืนค่าออกมา เช่นกรณีฟังก์ชัน float input(void) ที่จะคืนค่าหลังจากผู้ใช้โปรแกรมได้ป้อนข้อมูลให้ตามที่ฟังก์ชันสั่งให้ทำแล้ว 4) ฟังก์ชันที่มีตัวแปรร่วมและมีการ คืนค่า เช่นกรณีฟังก์ชัน float diff(float x, float y) ที่จะคืนค่าเป็นผลต่างระหว่างตัวแปร x และ ตัวแปร y ส่วนฟังก์ชันที่มีการใช้ตัวแปรร่วม นั้น มีวิธีการเรียกอยู่ 2 แบบคือ 1) กรณี เรียกตามค่า (Call by Value) กรณีนี้การเปลี่ยนค่าตัวแปรร่วมที่เกิดขึ้นในฟังก์ชัน จะไม่มีผลต่อ ค่าตัวแปรร่วมตั้งต้นดังตัวอย่างต่อไปนี้void skipline(int num)
{
int i ;
for(i = 0 ; i <=num-1 ; i++)
{
printf(n);
}
num = 100;
}
void main(void)
{
int num1 = 60;
printf(%d,num1);
skipline(num1) ;
}
กรณี เรียกตามค่านี้ ค่า num มีการเปลี่ยนแปลง แต่ไม่มีผลต่อค่า num1 ใน main function ตัวแปรร่วมในฟังก์ชันจะถือว่าเป็นกรณีเรียกตามค่า เมื่อการใช้ตัวแปรร่วมเป็นไปตามเงื่อนไขต่อไปนี้ ตัวแปรร่วมนั้นแค่ส่งผ่านข้อมูลไปให้ฟังก์ชัน ตัวแปรร่วมดังกล่าวจะไม่เป้นตัวแปรที่คืนค่าหลังสิ้นสุดการทำงานของฟังก์ชัน 2) กรณี เรียกตามการอ้างอิง (Call by Reference) ซึ่งต้องมีการเรียกใช้ตัวแปรพอยเตอร์กรณีนี้การเปลี่ยนค่าตัวแปรร่วมที่เกิดขึ้นในฟังก์ชัน จะมีผลต่อ ค่าตัวแปรร่วมตั้งต้นดังตัวอย่างต่อไปนี้void flip(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
ในการเรียกใช้ฟังก์ชัน flip นั้น จะต้องเรียกจาก แอดเดรสตัวแปร ดังนี้ flip(&a,&b) มีบางกรณีที่มีการ เรียกตามค่าและเรียกตามการอ้างอิงในฟังก์ชันเดียวกันเช่นการแก้สมการกำลัง 2bool quardsolve(float a, float b, float c, float *root1, float *root2)
{
float disc = (b*b) (4*a*c);
if(disc < 0.0)
{
return false;
}
else
{
*root1 = (-b + sqrt(disc))/(2*a);
*root2 = (-b sqrt(disc))/(2*a);
return true;
}
}
ตัวแปรดัชนี root1 และ root2 ทำหน้าที่เป็นตัวแปรร่วม Output ที่เรียกโดยการใช้อ้างอิง (Call by Reference) และ ตัวแปร a b c เป็นตัวแปรร่วม Input ที่ใช้กับการเรียกตามค่า (Call by Value) ถ้า การแก้สมการกำลัง 2 มีคำตอบให้คืนค่าเป็น true และ ค่า root1 และ root2 เป็นจำนวนจริง มิฉะนั้นให้ฟังก์ชันคืนค่า false ออกมาแทน เนื่องจาก ค่า root1 และ root2 นั้นได้รับการประกาศให้เป็น ตัวแปรร่วมอ้างอิง (Reference parameter) มีผลทำให้ฟังก์ชันต้นแบบ (Function Prototype) มีลักษณะเป็น bool quardsolve(float, float, float, float *, float *) เมื่อเรียกใช้งานฟังก์ชัน quardsolve ให้เรียกใช้งานฟังก์ชันดังนี้ float x1, y1; float test = quardsolve(1.0,2.0,1.0,&x,&y); ซึ่งการเรียกใช้ฟังก์ชันดังกล้าวคล้ายคลึงกับการเรียกใช้คำสั่ง scanf int number; scanf(%d, &number); ตัวอย่างการเรียกใช้ฟังก์ชันที่มีตัวแปรพอยเตอร์จะแสดงให้เห็นดังตัวอย่างต่อไปนี้ 1) ฟังก์ชันที่ มี ตัวแปรพอยเตอร์ที่แสดงในภาพที่ 6.5 นั้น จะอยู่ที่ฟังก์ชัน cal_cum โดยในฟังก์ชัน cal_sum มี ตัวแปร a และ b เป็น ตัวแปร input ขณะที่ตัวแปรพอยเตอร์ *r เป็นตัวแปร output เวลาเรียกใช้งานฟังก์ชัน cal_sum ในฟังก์ชัน main จะเรียกใช้งานดังนี้ double num1 = 2.4, num2 = 1.2,result; cal_cum(num1,num2,&result); แอดเดรสของตัวแปร result (&result) จะมีค่าเท่ากับชื่อตัวแปรพอยเตอร์ แม้ว่าตัวแปร result จะไม่ใช่ตัวแปรพอยเตอร์ก็ตาม 2) ฟังก์ชันที่มี ตัวแปรพอยเตอร์ที่แสดงในภาพที่ 6.6 นั้น จะอยู่ที่ฟังก์ชัน order ซึ่งใช้ตัวแปรพอยเตอร์ เป็น input และ output ทั้งคู่ ฟังก์ชัน order จะทำหน้าที่ จากเล็กไปหาใหญ่ โดยที่ ถ้า ค่าที่ตัวแปรพอยเตอร์ *small ชี้ขนาดใหญ่กว่าค่าที่ตัวแปรพอยเตอร์ *big ชี้ ให้ลงมือสับตำแหน่งการชี้ค่า
หน้าที่ 8 - ตัวแปรสตริง
S2 |A|n|o|t|h|e|r| |E|x|a|m|p|l|e|{PBODY}||?|?|?|?|
ทั้งนี้เนื่องจากการเตรียมพื้นที่ขนาด 20 ช่องตาราง แต่ใช้จริง 16 ช่อง คือตัวหนังสือ 15 ช่องและ ช่องที่ 16 เก็บตัวสิ้นสุดสตริง การตั้งต้นตัวแปรสตริง ดังตัวอย่างต่อไปนี้ถือว่าเป็นการตั้งต้นตัวแปรสตริงที่ถูกต้อง
#includeผลที่ได้การเขียนโปรแกรมเติมชื่อและนามสกุลจะแสดงให้เห็นในภาพที่ 7.1void main() { char first[100], last[100]; int i; printf("nEnter your first name:"); scanf("%s", first ); printf("nEnter your last name:"); scanf("%s", last ); printf("nYour full name is: %s %sn", first, last ); printf("First name is: "); for( i=0; (i<100 && first[i] != '{PBODY}') ; i++ ){ printf("%c ",first[i]); } printf("nLast name is: "); for( i=0; (i<100 && last[i] != '{PBODY}') ; i++ ){ printf("%c ",last[i]); } printf("n"); }

char *s;
s = (char *)malloc(sizeof(char) * 0); // - WRONG, need to allocate 1 more space
strcpy(s, "linux");
printf("%sn", s);
กรณีที่ใช้คำสั่ง strlen เพื่อหา ขนาดอาเรย์ก่อนทำ Dynamic allocation (malloc) นั้น พึงรับทราบว่า คำสั่ง strlen จะมีขนาดเพียงพอสำหรับตัวจำนวนอักษรที่ใช้ในตัวแปรสตริงเท่านั้น แต่ไม่ได้นับตัวแปร NULL ที่ใช้กำหนดจุดสิ้นสุดของสตริงด้วย โดยที่รายละเอียดเกี่ยวกับคำสั่ง strlen จะกล่าวถึงในตอนต่อไป การกำหนดค่าให้ตัวแปรสตริง (String Assignment) ตัวอย่างการกำหนดค่าให้ตัวแปรสตริงchar s[5]="SIIT"; // ใช้ได้, กำหนดค่าตัวแปรสตริงให้ตัวแปรอาเรย์
char dept[5], *d=dept; // ใช้ได้, กำหนดค่าตัวแปรสตริงให้ตัวแปรพอยเตอร์
char name[20];
name = C. Sinthanayothin"; // ผิด อย่ากำหนดตัวแปรสตริงให้ตัวแปรอาเรย์ด้วยวิธีนี้
strcpy(name,C. Sinthanayothin"); // ใช้ได้, ให้ก๊อปปี้ค่าสตริงโดยใช้คำสั่ง strcpy
strcpy(dept,"IT"); // ใช้ได้, ก๊อปปี้ค่าสตริง ลงในตัวแปร dept
printf("%s %s %sn",d,s,dept); // ใช้ได้, แสดงผลค่าสตริงด้ว printf
d = strcpy(s,"EE"); // ใช้ได้, นี่คือการคืนค่าตัวแปรสตริง ลงใน ตัวแปร d ด้วยคำสั่ง strcpy
printf("%s %s %s %sn",name,d,s,dept);
char c1[30], c2[30]=This is new c1 string;
char s[30] = "c programming ";
char str1[30]; // วิธี้ทำให้ตัวแปร str1 ไม่เป็น l-value เพราะเป็น constant array
char *str; // วิธี้ทำให้ตัวแปร str เป็น l-value เพราะเป็น ตัวแปรพอยเตอร์
strcpy(c1, c2); // ใช้ได้, ก๊อปปี้ข้อมูลใน c2 ลงใน c1
str = strcat(s,"is great!!"); // ใช้ได้, คือค่าเป็น ตัวแปรพอยเตอร์ประเภท char
str1 = strcat(s,"is great!!"); // ผิด, ฟังก์ชัน strcat ตอ้งคืนค่าด้วยตัวแปรพอยเตอร์ประเภท char ไม่ใช่ตารางอาเรย์ประเภท char
ข้อควรจำคือ: ต้องเตรียมพื้นที่หน่วยความจำไว้ให้พร้อมก่อนการกำหนดค่าให้ตัวแปรสตริงมิฉะนั้นอักษรบางตัวก็จะแหว่งหายไป ตัวแปรสตริงนั้นจะใช้ %s เป็นตัว place holder ขณะที่ใช้คำสั่ง sscanf ในการอ่านข้อมูลจำพวกสตริงแล้วจัดการแปลงข้อมูลให้อยู่รูปตามที่กำหนด ดังตัวอย่างต่อไปนี้int sscanf( const char *buffer, const char *format [, argument ] ... );
char ch, int inum, float fnum;
char buffer[100] = A10 50.0;
sscanf(buffer,%c%d%f,&ch,&inum,&fnum); /* puts A in ch, 10 in inum and 50.0 in fnum */
sscanf(" 85 96.2 hello","%d%.3lf%s",&num,&val,word);
// results: num=85, val = 96.2, word = "hello" ส่วน sprintf ใช้แสดงผลลัพธ์ที่อยู่ในรูปแบบต่างๆ ให้เป็นตัวแปรสตริงดังตัวอย่างต่อไปนี้
int sprintf( char *buffer, const char *format [, argument] ... );
char buffer[100];
sprintf(buffer,%s, %s,LastName,FirstName);
if (strlen(buffer) > 15)
printf(Long name %s %sn,FirstName,LastName);
ถ้าต้องการแปลงตัวเลขให้เป็นข้อมูลสตริงให้ใช้ฟังก์ชัน sprintf และ ตัวแปรดัชนี้ char ทำตามคำสั่งต่อไปนี้
int sscanf(char *buffer, const char *format [, argument ] ... );
char S[10]; int day, month,year;
sprintf(S,%d/%d/%d, day, month, year);
ถ้า day = 23, month = 8, year = 2001 ผลลัพธ์คือ S = 23/8/2001
ต่อไปนี้คือตัวอย่างการใช้ sprintf กับ sscanf เมื่อเปรียบเทียบกับ printf
#include
#include
int main()
{
char s[30]="85 96.2 hello";
int num, mon=8,day=23,year=2001;
double val;
char word[10]; // can we use: char *word;
// make sure your assign the proper address for pointer
sscanf(" 85 96.2 hello","%d%lf%s",&num,&val,word);
printf("num=%d val=%.3lf word=%sn",num,val,word);
sprintf(s,"%d/%d/%d", mon, day, year);
printf("s = %sn",s);
return 0;
}
ข้อทบทวน: ภาษาซี มีฟังก์ชันที่ใช้ดัดแปลงแก้ไขตัวแปรสตริง หลายแบบตามความต้องการของผู้ใช้ได้แก่:
strlen(str) คำนวณความยาวสตริง ซึ่งจะมีการนับไปเรื่อยๆ จนกว่าจะพบตัวแปร NULL ถึงจะหยุดโดยไม่มีการนับตัวแปร NULL ที่สิ้นสุดประโยคเข้าไปด้วย ดังตัวอย่างต่อไปนี้
int strlen(char *str);
char str1 = hello;
strlen(str1) จะคืนค่าออกเป็น 5 เพราะ มีอักษร 5 ตัว
strcpy(dst,src) ก็อปปี้ข้อมูลจากตัวแปรสตริง src พร้อมตัวสิ้นสุดสตริง NULL ไปที่ตัวแปรสตริง dst แต่มีเงื่อนไขว่าตัวแปร des ต้องได้รับการเตรียมพื้นที่ให้ใหญ่พอๆกับตัวแปร src และการเตรียมพื้นที่ ให้ ตัวแปร src และ ตัวแปร dst ต้องไม่ทับซ้อนกันมิฉะนั้นจะให้ผลที่คาดเดาไม่ได้ การประกาศใช้ฟังก์ชัน strcpy จะทำได้ดังนี้
char *strcpy(char *dst, char *src)
strncpy(dst,src,n) ก็อปปี้ข้อมูลจากตัวแปรสตริง src โดยไม่ก๊อปปี้ตัวสิ้นสุดสตริง NULL ไปที่ตัวแปรสตริง dst เนื่องจากมีจำนวนตัวอักษร n เป็นตัวจำกัดไว้ แต่มีเงื่อนไขว่าตัวแปร des ต้องได้รับการเตรียมพื้นที่ให้ใหญ่พอๆกับตัวแปร src และการเตรียมพื้นที่ ให้ ตัวแปร src และ ตัวแปร dst ต้องไม่ทับซ้อนกันมิฉะนั้นจะให้ผลที่คาดเดาไม่ได้ การประกาศใช้ฟังก์ชัน strncpy จะทำได้ดังนี้
char *strncpy(char *dst, char *src, int n)
strcmp(str1,str2) เปรียบเทียบข้อมูลในตัวแปร str1 กับข้อมูลในตัวแปรสตริง str2 โดยใช้อักษรตัวแรกที่เริ่มต่างกันเป็นหลักซึ่งให้ผลดังนี้
น้อยกว่า 0 -- ถ้าค่า ASCII ที่เริ่มแตกต่างใน str1 มีขนาดเล็กกว่า str2 หรือ str1 เริ่มต้นเหมือนกับ str2 แต่ str2 นั้นมีตัวอักษรมากกว่า
มากกว่า 0 -- ถ้าค่า ASCII ที่เริ่มแตกต่างใน str1 มีขนาดใหญ่กว่า str2 หรือ str1 เริ่มต้นเหมือนกับ str2 แต่ str1 นั้นมีตัวอักษรมากกว่า
0 ถ้าตัวแปรสตริงทั้ง 2 ตัวนั้นใช้ตัวอักษรเดียวกันและความยาวเท่ากัน
การประกาศใช้ฟังก์ชัน strcmp จะทำได้ดังตัวอย่างต่อไปนี้
int strcmp(char *str1, char *str2)
#include
#include
void main()
{
printf("%d n", strcmp("hello","hello")); // returns 0
printf("%d n", strcmp("yello","hello")); //returns value > 0
printf("%d n", strcmp("Hello","hello")); // returns value < 0
printf("%d n", strcmp("hello","hello there")); // returns value < 0
printf("%d n", strcmp("some diff","some dift")); //returns value<0
}
strncmp(str1,str2,n) เปรียบเทียบข้อมูลในตัวแปร str1 กับข้อมูลในตัวแปรสตริง str2 เป็นจำนวนอักษร n ตัวโดยใช้อักษรตัวแรกที่เริ่มต่างกันเป็นหลัก และ จะมีการเปรียบเทียบในกรณีที่อักษรในตัวแปรมีจำนวนน้อยกว่า n
การประกาศใช้ฟังก์ชัน strncmp จะทำได้ดังตัวอย่างต่อไปนี้
int strncmp(char *str1, char *str2,int n)
ความแตกต่างระหว่าง strcmp และ strncmp จะแสดงให้เห็นดังตัวอย่างต่อไปนี้
strcmp(some diff,some DIFF)
-- returns value > 0
strncmp(some diff,some DIFF,4)
-- returns 0
strcat(str1,str2) ใช้ในการนำข้อมูลในตัวแปร str2 ไปต่อท้ายตัวแปร str1 ซึ่งจะคืนค่าเป็น str1 ที่ได้รับการต่อให้ยาวขึ้น ตัวอย่างเช่น
char *s1 = C. , *s3 = strcat(s1,Sinthanayothin);
ผลลัพธ์: s1 = s3 = C. Sinthanayothin
การประกาศใช้ฟังก์ชัน strcat จะทำได้ดังตัวอย่างต่อไปนี้
char* strcat(char *s1, const char* s2);
strncat(str1,str2,n) ใช้ในการนำข้อมูลในตัวแปร str2 จำนวน n อักษรไปต่อท้ายตัวแปร str1 ซึ่งจะคืนค่าเป็น str1 ที่ได้รับการต่อให้ยาวขึ้น ตัวอย่างเช่น
char s1[10] = "IT ";
char *s3 = strncat(s1,"050Basic",3);
printf("%s n", s1); printf("%s n", s3);
ผลลัพธ์: s1 = s3 = IT 050
การประกาศใช้ฟังก์ชัน strncat จะทำได้ดังตัวอย่างต่อไปนี้
char* strncat(char *s1, const char* s2ม int n);
ฟังก์ชันเหล่านี้มีอยู่ในไลบรารีเฮดเดอร์ไฟล์ string.h ซึ่งต้องใช้คำสั่ง #include ถึงจะเรียกใช้ได้
เราสามารถสร้างตารางอาเรย์ให้ตัวแปรสตริง (Array of string) ดังตัวอย่างต่อไปนี้
char month[12][10] = {January, February, March, April, May, June, July, August, September, October, November, December };
แต่ถ้าต้องการให้ตารางอาเรย์สำหรับตัวแปรสตริง สามารถรองรับข้อมูลสตริงที่มีความยาวต่างกัน (Ragged array of string) ให้ดังนี้
char *MonthNames[13]; /* an array of 13 strings */
MonthNames[1] = January; /* String with 8 chars */
MonthNames[2] = February; /* String with 9 chars */
MonthNames[3] = March; /* String with 6 chars */
ตัวอย่างตารางอาเรย์ให้ตัวแปรสตริงแสดงวันทั้ง 7 แบบ Ragged array of string จะแสดงให้เห็นในตัวอย่างต่อไปนี้
#include
#include
void main()
{
char *days[7]; char TheDay[10];int day;
days[0] = "Sunday"; days[1] = "Monday";
days[2] = "Tuesday"; days[3] = "Wednesday";
days[4] = "Thursday"; days[5] = "Friday";
days[6] = "Saturday";
printf("Please enter a day: ");
scanf("%9s",TheDay);
day = 0;
while ((day < 7) && (strcmp(TheDay,days[day])))
day++;
if (day < 7) printf("%s is day %d.n",TheDay, day);
else printf("No day %s!n",TheDay);
}
ในการรับและส่งข้อมูลจำพวกสตริงนั้นทำได้หลายวิธี ได้แก่
1) ในกรณีที่ใช้คำสั่ง printf และ scanf นั้นให้ใช้ %s ในการอ่านข้อมูลและ แสดงข้อมูลสตริงออกมา
2) ใช้คำสั่ง gets ในการข้อมูลสตริงออกมาทีละบรรทัด ดังตัวอย่างต่อไปนี้
char name1[10], name2[30];
scanf(%s,name1); // Input: IT 050
gets(name2); // Input: C Programming
printf(Course is %sn,name); // Output: IT 050
printf(Detail is %sn,name2); // C Programming

การใช้งานคำสั่งกับตัวแปร อักษร (char operators)
นี่คือตัวอย่างการใช้งานฟังก์ชันที่คุมการรับส่งข้อมูลตัวอักษร
char ch;
ch = getchar(); // Input ch ใช้แทน scanf("%c",&ch);
putchar(ch); // Output ch ใช้แทน printf("Character is %cn",ch);
ch = 'S'; // ใช้ได้ ตัวอย่างการกำหนดค่าตัวอักษรให้ตัวแปร char
putchar(ch); // ผลที่ได้ออกมาคือ S
putchar('T'); // ผลที่ได้ออกมาคือ T
ฟังก์ชันที่ใช้กำหนดการทำงานให้ตัวแปร char ได้แก่
คำสั่ง: isalpha(ch);
การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง A-Z หรือ a-z
ตัวอย่าง: c = isalpha(ch); // คืนค่า TRUE ถ้า ch=M และ คืนค่า FALSE ถ้า ch=5
คำสั่ง: isdigit(ch);
การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง0-9
ตัวอย่าง: d = isdigit(ch); // คืนค่า FALSE ถ้า ch=M และคืนค่า TRUE ถ้า ch=5
คำสั่ง: islower(ch);
การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง a-z
ตัวอย่าง: c = islower(ch); // คืนค่า FALSE ถ้า ch=M return false, และคืนค่า TRUE ถ้า ch=m
คำสั่ง: isupper(ch);
การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง A-Z
ตัวอย่าง: c = isupper(ch); // คืนค่า TRUE ถ้า ch=M return false, และคืนค่า FALSE ถ้า ch=m
คำสั่ง: isspace(ch);
การใช้งาน: คืนค่า TRUE ถ้า ch คิอช่องว่างขาว (space, newline, tab )
ตัวอย่าง: c = isspace(ch); // คืนค่า TRUE ถ้า ch = n คืนค่า FALSE ถ้า ch=m
คำสั่ง: tolower(ch);
การใช้งาน: คืนค่าตัวพิมพ์เล็กจากค่าอักษรในตัวแปร ch ถ้าเป็นไปได้
ตัวอย่าง: c = tolower(ch); // คืนค่า m ให้ c ถ้า ch=M
คำสั่ง: toupper(ch);
การใช้งาน: คืนค่าตัวพิมพ์ใหญ่จากค่าอักษรในตัวแปร ch ถ้าเป็นไปได้
คำสั่ง: c = toupper(ch); // คืนค่า M ให้ c ถ้า ch=m
หน้าที่ 9 - โครงสร้างสตรักเจอร์
8. โครงสร้างสตรักเจอร์ (Structure)
สตรักเจอร์ เป็นวิธีการเก็บตัวแปรหลากชนิดให้อยู่เป็นกลุ่มก้อนเดียวกัน ทำให้สามารถแยกโปรแกรมออกเป็นหน่วย (Modular Programming) ซึ่งแก้ไขได้ง่ายเพราะสามารถแยกฟังก์ชันและตัวแปรออกเป็นหน่วยๆ ซึ่งก็เป็นประโยชน์ในการสร้างฐานข้อมูลด้วย
การตั้งต้นสร้างสตรักเจอร์ สามารถทำได้หลายรูปแบบดังตัวอย่างต่อไปนี้
1) การใช้ คำสั่ง struct สร้างตัวแปรชนิด student_a ผ่านตัวแปร student
struct student
{
char *first;
char *last;
char SSN[9];
float gpa;
char **classes;
};
struct student student_a;
2) การใช้ คำสั่ง struct สร้างตัวแปรชนิด student_a โดยตรง
struct {
char *first;
char *last;
char SSN[10];
float gpa;
char **classes;
} student_a;
3) การใช้ คำสั่ง typedef struct เพื่อสร้างตัวแปรชนิด student_a ผ่านตัวแปร student
typedef struct
{
char *first;
char *last;
char SSN[9];
float gpa;
char **classes;
} student;
student student_a;
การกำหนดชนิดตัวแปร ทำได้โดยใช้คำสั่ง typedef ตามหลักการใช้งานดังนี้
typedef type name (typedef ชื่อของชนิดตัวแปร ชื่อที่ใช้เรียกชนิดตัวแปรจริง)
ตัวอย่าง: typedef int INTEGER;
INTEGER x; /* x คือตัวแปรตระกูล INTEGER */
typedef char *STRING;
STRING sarray[10];
/* sarray คือตารางอาเรย์ ของ char* ซึ่งเทียบได้กับการประกาศว่า
char *sarray[10] */
ในโครงสร้างตัวแปรที่อยู่ในรูป structure นั้นประกอบด้วยตัวแปรที่เกี่ยวข้องในลักษณะเดียวกับตารางอาเรย์ แม้จะไม่ใช้ตัวแปรประเภทเดียวกัน โดยจะแบ่งตัวแปรออกเป็น field โดยที่กลุ่มตัวแปรใน structure จะถือว่าเป็นส่วนหนึ่งของหน่วยใหญ่หน่วยเดียวกันดังที่แสดงในภาพที่ 8.1 ส่วนการเปรียบเทียบความแตกต่างระหว่าง ตารางอาเรย์และตัวแปร struct ที่มีตัวแปรที่เป็นตารางอาเรย์ จะแสดงให้เห็นในภาพที่ 8.2
การเรียกใช้งาน สตรักเจอร์
โดยปกติการสร้างสตรักเจอร์ ทำได้โดยใช้คำสั่ง typedef และ struct ซึ่งโครงสร้างภายในของสตรักเจอร์ จะประกอบด้วยตัวแปรต่างๆ ซึ่งแยกออกเป็น field ตัวแปรชนิดต่างๆ และในแต่ละ field จะมีการกำหนดพื้นที่หน่วยความจำ จนเพียงพอสำหรับแต่ละ field ดังตัวอย่างต่อไปนี้
typedef struct {
Type1 FieldName1;
Type2 FieldName2;
Type3 FieldName3;
/* as needed */
} VarName;
VarName คือชื่อชนิดตัวแปรสตรักเจอร์ทั้งหมด
นี่คือตัวอย่างการประกาศใช้ตัวแปร struct ชนิด student_t เพื่อบันทึกข้อมูลนักเรียน พร้อมตัวอย่างการกำหนดตัวแปร ชนิด student_t ซึ่งสามารถทำได้อย่างตัวแปรทั่วไป เช่นเดียวกับ int float
#define MAX_LEN 12 /* Length of name */
typedef struct {
char name[MAX_LEN];
int id;
float gpa;
char major[10];
} student_t;
student_t s;
student_t stu1, stu2, stu3;
การเข้าถึง ตัวแปร field ภายในตัวแปร struct ทำได้โดยการใช้ จุด (.)แล้วตามด้วยชื่อ field ดังตัวอย่างกรณีการเข้าถึงตัวแปร ชนิด DATE ที่จะแสดงให้เห็นดังต่อไปนี้ และผลที่ได้จะแสดงให้เห็นในภาพที่ 8.3
หลักการเข้าถึงตัวแปร struct: VarName.FieldName
typedef struct {
int month, day, year;
} DATE;
void main() {
DATE d1;
d1.month = 12;
d1.day = 2;
d1.year = 1970;
}
ขอขอบคุณข้อมูลดีๆจากเว็บ
ไม่มีความคิดเห็น:
แสดงความคิดเห็น