พื้นฐานโปรแกรมภาษา C
หน้าที่ 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) มีบางกรณีที่มีการ เรียกตามค่าและเรียกตามการอ้างอิงในฟังก์ชันเดียวกันเช่นการแก้สมการกำลัง 2
bool 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ข้อทบทวน: ภาษาซี มีฟังก์ชันที่ใช้ดัดแปลงแก้ไขตัวแปรสตริง หลายแบบตามความต้องการของผู้ใช้ได้แก่: 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 จะทำได้ดังตัวอย่างต่อไปนี้#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; } int strcmp(char *str1, char *str2) #includestrncmp(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#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 } ถึงจะเรียกใช้ได้ เราสามารถสร้างตารางอาเรย์ให้ตัวแปรสตริง (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ในการรับและส่งข้อมูลจำพวกสตริงนั้นทำได้หลายวิธี ได้แก่ 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#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); } การใช้งานคำสั่งกับตัวแปร อักษร (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; }ขอขอบคุณข้อมูลดีๆจากเว็บ
ไม่มีความคิดเห็น:
แสดงความคิดเห็น