วันจันทร์ที่ 19 กันยายน พ.ศ. 2554

การเขียนโปรแกรมแบบเงื่อนไข

1 if...else...if

การใช้ if –else  ในภาษาซี
ในบทความนี้จะพูดถึงการใช้ if , else if, else ในบทความเดียวเพื่อลดเวลาในการเรียนรู้เรื่องการตัดสินใจเงื่อนไขในภาษาซีซึ่งรูปแบบการใช้ if else ในภาษาซีนั้นจะดูเหมือนกับในภาษาต่างๆที่พัฒนามาจากภาษาซี ซึ่งถ้าเข้าใจการตัดสินเลือกเงื่อนไขการใช้ if else ในภาษาซีนั้นจะทำให้สามารถเข้าใจการใช้ if else ในภาษาที่พัฒนามาจากภาษาซีได้เร็วขึ้น ซึ่งเราก็มาดูตัวอย่างการใช้ if, else if, else ในภาษาซีดีกว่า
01.//by thaicoding.net
02.  
03.#include<stdio.h>
04.  
05.int main(){
06.  
07.int num;
08.  
09.printf("Enter number");
10.  
11.scanf("%d", &num);
12.  
13.if(num == 20)
14.  
15.printf("if case %d\n", num);
16.  
17.else if(num == 30)
18.  
19.printf("else if case %d\n", num);
20.  
21.else
22.  
23.printf("else case $d\n", num);
24.  
25.return 0;
26.  
27.}
c language, if else c, if else ภาษาซี , ภาษาซี if else, ภาษา c, ภาษาซี, สอน ภาษา c
c language, if else c, if else ภาษาซี , ภาษาซี if else, ภาษา c, ภาษาซี, สอน ภาษา c
c language, if else c, if else ภาษาซี , ภาษาซี if else, ภาษา c, ภาษาซี, สอน ภาษา c
จากผลลัพธ์จะเห็นในการรับค่าเพื่อมาเก็บในตัวแปร num แล้วมาตรวจสอบตามเงื่อนไข if , else if, else แบ่งออกเป็น 3 กรณีคือเท่ากับ 20, 30 , และนอกเหนือจากนี้ในหนังสือส่วนใหญ่มักจะสอน if , if else, if else if แต่ในความเป็นจริงแล้วมันก็เป็นเรื่องเดียวกัน คือ if จะเป็นกรณีและที่ถูกตรวจสอบแล้ว else if จะเป็นกรณีต่อมาสุดท้ายถ้าไม่ตรงกลับกรณีใดก็จะทำ else และมีเรื่องควรระวังก็คือถ้า เขียน if หลายๆอันมันจะตรวจสอบทุกอันแต่ถ้าเป็น if , else if มันจะหยุดตรวจสอบกรณีอื่นเมื่อเจอกรณีที่ตรงแล้วเช่น
1.if (num = =20)
2.  
3.printf(“if 1”);
4.  
5.if(num == 30)
6.  
7.print(“if 2”);
แต่ถ้าเป็น if else if ดังตัวอย่างจะตรวจสอบในกรณีที่ตรงเท่านั้นเช่นเมื่อ num = 20 ก็ทำในกรณีนั้นกรณีอื่นจะไม่ทำแล้วและถ้าเป็น if หลายๆๆอันมันจะตรวจสอบทุก if นั้นเอง
Tags: , , , , , ,

2 switch case

switch..case

switch..case ก็เป็นการเขียน if clause แบบหนึ่งที่ง่ายขึ้น มีรูปแบบ syntax ดังนี้
switch(<expression>) {
    case <value> : <statement>
    case <value> : <statement>
    case <value> : <statement>
    ..........................
    [default : <statement>]
}
ตรง expression นั้นจะเป็นตัวแปร หรือ method ใด ๆ ก็ได้
โดย default นั้นเปรียบเสมือน else ... ซึ่งจะเป็น option ที่จะมีก็ได้ ไม่มีก็ได้
ลองมาดูตัวอย่างเพื่อความเข้าใจดีกว่า
int grade = Int32.Parse(Console.ReadLine());
string gradeString;

switch(grade) {
    case 4 : gradeString = "A";
    case 3 : gradeString = "B";
    case 2 : gradeString = "C";
    case 1 : gradeString = "D";
    case 0 : gradeString = "F";
    default : gradeString = "Incorrect number";
}

Console.WriteLine(gradeString);
ก็ควรจะมีผลเหมือนกับ
int grade = Int32.Parse(Console.ReadLine());
string gradeString;

if(grade == 4) {
    gradeString = "A";
} else if(grade == 3) {
    gradeString = "B";
} else if(grade == 2) {
    gradeString = "C";
} else if(grade == 1) {
    gradeString = "D";
} else if(grade == 0) {
    gradeString = "F";
} else {
    gradeString = "Incorrect number";
}

Console.WriteLine(gradeString);
ถ้านำตัวอย่างนี้ไปรันในภาษาอย่าง C,C++ หรือ Java แล้วสมมุติว่าใส่ input เป็น 3 ผลที่ได้คือ
B
C
D
F
Incorrect number
นั่นเพราะว่า ถ้า case ใดตรงกับค่าใน switch expression มันก็จะทำงานที่ case อื่น ๆ ข้างล่างทั้งหมดเลย ดังนั้น C# จึงแก้ความสับสนนี้ โดยการให้ code ด้านบนนั้นไม่ผ่านการ compile

วิธีแก้ปัญหากรณีนี้ก็คือใส่ประโยค break; ลงไปในแต่ละ case ดังนี้
int grade = Int32.Parse(Console.ReadLine());
string gradeString;

switch(grade) {
    case 4 :
        gradeString = "A";
        break;
    case 3 :
        gradeString = "B";
        break;
    case 2 :
        gradeString = "C";
        break;
    case 1 :
        gradeString = "D";
        break;
    case 0 :
        gradeString = "F";
        break;
    default :
        gradeString = "Incorrect number";
}

Console.WriteLine(gradeString);
คนที่เคยเขียน pascal มาแล้วคงสงสัย ว่าทำไมต้องใส่ break ด้วยล่ะ ทำไมไม่ทำ ประโยค switch..case ให้มันทำงานแค่ case เดียวแล้วออกเลย นั่นเพราะมันมีประโยชน์บ้างครับ ลองมาดูกัน
int grade = Int32.Parse(Console.ReadLine());
string message;

switch(grade) {
    case 4 :
    case 3 :
        message = "You 're good";
        break;
    case 2 :
    case 1 :
        message = "You should pratice more";
        break;
    case 0 :
        message = "try try and try";
        break;
    default :
        message = "Incorrect number";
}

Console.WriteLine(message);
นั่นคือถ้าได้เกรด 4 หรือเกรด 3 message ก็จะเป็นข้อความว่า You 're good แต่ถ้าได้ 2 หรือ 1 ก็จะเป็นข้อความว่า You should pratice more

*ในภาษาอื่น ๆ นั้นตรง expression นั้นต้องเป็น integral type เท่านั้น นั่นคือจะต้องเป็นพวก int short,... หรือ char แต่ว่าใน C# นั้นสามารถใส่ expression เป็น string ได้ด้วย
string gradeString = Int32.Parse(Console.ReadLine());
string message;

switch(gradeString.ToUpper()) {
    case "A" :
        message = "Excellent";
        break;
    case "B" :
        message = "Good";
        break;
    case "C" :
        message = "Cool";
        break;
    case "D" :
        message = "Try";
        break;
    case "F" :
        message = "Get out!!";
        break;
    default :
        message = "Incorrect grade";
}

Console.WriteLine(message);

Formatting String

คุ้น ๆ code ด้านล่างนี้ใช่มั้ยครับ
Console.WriteLine("Hi {0}\nYou 're {1} years old", name, age);
มันมาจาก tutorial ตอนที่ 1 เป็นสไตล์การเขียนแบบ C ครับ ถ้าเป็นใน C ก็คงเป็นอย่างนี้
printf("Hi %s\nYou 're %s years old\n", name, age);
โดย %s บอกว่าให้เอา string มาใส่ตรงนี้นะ(s คือ string ถ้าเป็น int ก็จะเป็น %d, float ก็ %f, char ก็ %c)

การเขียนอย่างนี้ไม่ได้ช่วยให้การอ่านประโยคนั้นต่อเนื่องเพียงอย่างเดียว แต่มันยังสามารถจะ format ได้อีกด้วย ลองดูตัวอย่างกัน
Console.WriteLine("{0,5}{1,5}", 123, 456);     // Right-aligned
Console.WriteLine("{0,-5}{1,-5}", 123, 456);   // Left-aligned
ผลลัพธ์
  123  456
123  456
อันนี้คือการจัดชิดซ้ายชิดขวา โดยการระบุความกว้าง(จำนวนตัวอักษร)ลงไป
ถ้าเป็น C จะเขียนอย่างนี้ (ใน C ถ้าจะขึ้นบรรทัดใหม่ ต้องใส่ '\n' เองเสมอ)
printf("%5d%5d\n", 123, 456);     // Right-aligned
printf("%-5d%-5d\n", 123, 456);   // Left-aligned
ถ้าเป็น Pascal
writeln(123:5, 456:5); { Right-aligned }
writeln(123:-5, 456:-5); { Left-aligned }
ประโยชน์ที่เห็นได้จากการจัดความกว้างก็เช่นการโชว์ข้อมูลเป็นบล็อก ๆ ให้ตรงกัน เพื่อความสวยงาม
Console.WriteLine("{0,-10}{1,-3}", "Name","Salary");
Console.WriteLine("----------------");
Console.WriteLine("{0,-10}{1,6}", "Bill", 123456);
Console.WriteLine("{0,-10}{1,6}", "Polly", 7890);
Name      Salary
----------------
Bill      123456
Polly       7890

นอกจากการกำหนดความกว้างแล้ว เรายังกำหนดรูปแบบได้อีกด้วย โดยการใส่ :(colon) แล้วตามด้วยตัวอักษรลงไปหลังตัวเลขระบุตำแหน่ง ดังนี้

Characterความหมาย
C หรือ cCurrency(เงิน)
D หรือ dDecimal(แปลว่าเลขฐาน 10 นะ อย่าสับสนกับ ตัวแปรประเภท decimal)
E หรือ eExponent(ระบบวิทยาศาสตร์)
Fหรือ fFloating poing(ทศนิยม)
G หรือ gGeneral
N หรือ nNumber(เหมือน F แต่จะใส่ comma คั่นตัวเลขทุก ๆ 3 หลัก
P หรือ pPercentage
R หรือ rRound-trip ใช้กับ floating-point value เท่านั้น โดยจะ guaruntee ว่าค่าที่ถูกเปลี่ยนไปจะมีค่าเท่ากับตัวเดิม
X หรือ xHexadecimal(เลขฐาน 16)

int i = 123456;
Console.WriteLine("{0:C}", i);
Console.WriteLine("{0:D}", i);
Console.WriteLine("{0:E}", i);
Console.WriteLine("{0:F}", i);
Console.WriteLine("{0:G}", i);
Console.WriteLine("{0:N}", i);
Console.WriteLine("{0:P}", i);
Console.WriteLine("{0:X}", i);
฿123,456.00
123456
1.234560E+005
123456.00
123456
123,456.00
12,345,600.00 %
1E240


Console.WriteLine("{0:D6} {1:D4}", 123, 456);
000123 0456

เราสามารถรวมการจัดความกว้างและฟอร์แม็ตไปพร้อม ๆ กันได้ดังนี้
Console.WriteLine("{0,-10:D6}{1,-10:F4}", 123, 456.0000);
Console.WriteLine("{0,-12:N2}{1,9:X4}", 1234567, 240);
000123     456.0000
1,234,567.00   00F0

อ้อ ลองมาดูความแตกต่างของ F กับ R กันตรงนี้เลยครับ
double d = 1.2345678901234567890;
Console.WriteLine("{0:F16}", d);
Console.WriteLine("{0:R16}", d);
1.2345678901234600
1.2345678901234567
ตาม definition ของ R เป็นอย่างนี้ครับ
The R (round-trip) format works only with floating-point values: the value is first tested using the general format, with 15 spaces of precision for a Double and seven spaces of precision for a Single. If the value is successfully parsed back to the same numeric value, its formatted using the general format specifier. On the other hand, if the value isnt successfully parsed back to the same numeric value, the value is formatted using 17 digits of precision for a Double and nine digits of precision for a Single. Although a precision specifier can be appended to the round-trip format specifier, its ignored.
อย่าสนใจเลย แปะไว้งั้น ๆ แหละ

การจัด format สามารถทำได้ตอนสร้าง string ขึ้นมาตัวหนึ่งเลยก็ได้ ดังนี้ โดยใช้ method Format ของคลาส String ดังนี้