Tutorial

C Language 101 – นานาสาระกับการ Input (EP.6)

By Arnon Puitrakul - 09 มิถุนายน 2015

C Language 101 – นานาสาระกับการ Input (EP.6)

จากรอบที่แล้วนะครับ ที่เราได้เรียนรู้เรื่องของ ตัวแปร การเก็บค่า Output อะไรกันไปแล้ว วันนี้เราจะมาเรียนอีกเรื่องนึง ที่ผมลืมพูดไปเลย นั่นคือเรื่องของ Input
คำสั่งที่เราใช้ในการ Input ค่าเข้าโปรแกรมเราหลัก ๆ ก็มีหลายคำสั่งนะ แต่ก่อนอื่นเรามาลองอันที่ง่ายที่สุดก่อน นั่นคือ scanf(); Syntax ของมันคือ

scanf("String_Format",Variable_Address_List);

อย่างที่เขียนด้านบนครับ ก่อนอื่นเราก็ต้องมี String Format ก่อน เช่นพวก %d %f อะไรแบบนี้ เวลาใส่เรียง เราก็ต้องเรียงตามรูปแบบ Input ที่เราต้องการ เช่น ถ้าเราต้องการ Input เป็น
1 2 3 เพราะฉะนั้น String Format ของเราก็ควรจะเป็น %d %d %d อะไรแบบนี้ (เหมือนตอน printf เลย ! )
เสร็จก็ใส่ , (comma) แล้วตามด้วย Address ของตัวแปร

ปัญหาเกิด งานงอก เราจะเอา Address ของตัวแปรมากจากไหน ?

ไม่ยากครับ ในภาษา C มันจะมี Operator ตัวนึง เขาเรียกว่า Address Sign ครับ ถ้าเขียนในโค๊ตก็คือ & (Ampersand) นั่นเอง
จากตอนแรก ถ้าเราบอกว่า int a = 10;
แล้วเราบอกว่า printf("%d",a); เราก็จะได้ 10 ออกมาให้มั้ยครับ
แต่ถ้าเราบอกว่า printf("%p",&a); เราก็จะได้เลข Address ออกมาแทนทั้ง ๆ ที่เราเรียก a เหมือนกับบรรทัดข้างบนเลย นั่นเพราะเราใส่ Ampersand ไว้ก่อนหน้าตัวแปรนั่นเอง
Note: เราจะใช้ %p กับตัวแปร Pointer (แสดง Address) ส่วน Pointer เดี๋ยวไว้ EP. หลัง ๆ เลย เพราะมันค่อนข้างเข้าใจยาก

ลองมาดูตัวอย่าง การใช้ scanf(); กัน

ในตัวอย่างนี้ เราจะมีตัวแปร 3 ตัวนั่นคือ a,b และ c เป็น integer ส่วน Input เราจะให้มันรับค่าเข้ามาบรรทัดเดียว เรียงกัน 3 ตัวเป็น a b c เลย แล้วให้มันแสดงค่าของ a,b และ c ออกมาผ่าน printf();

#include <stdio.h>

int main ()
{
   int a,b,c;
   scanf("%d %d %d",&a,&b,&c);
   printf("%d %d %d",a,b,c);
   return 0;
}

จากโปรแกรมด้านบนก็เป็นเหมือนที่อธิบายด้านบนเลย ก่อนอื่น เราก็ประกาศตัวแปร a, b และ c ขึ้นมาก่อน ซึ่งเราบอกว่าให้มันเป็น Integer หรือจำนวนเต็มนั่นเอง
บรรทัดถัดมา เราก็มาใช้คำสั่งของวันนี้กันนั่นคือ scanf อย่างที่บอกไปว่า เราต้องการ Input ทั้ง 3 ตัวแปรเรียงกันอยู่ในบรรทัดเดียวกันเข้ามารวดเดียวเลย เพราะฉะนั้น เราก็ต้องจัด String Format เป็น %d %d %d
ถามต่อว่า ทำไมเราจะต้องวรรคระหว่าง %d ด้วย นั่นเพราะว่า ถ้าเราไม่แบ่งเนี่ย เวลาเรา Input เข้ามามันจะ งง เช่น เราบอกว่า 104567 มันก็จะเข้าแค่ตัวเดียวนั่นคือ 104567 แล้ว b,c ก็จะไม่ได้รับค่าอะไรเลย
หลังจากนั้นเราก็ printf ตามปกติเลย สุดท้ายก็ return 0; เป็นอันจบโปรแกรม
เพิ่มเติม : เราสามารถที่จะใช้ String Format เป็น %s ได้ด้วยนะ เหมือนเรารับค่าเข้ามาเป็น String แต่จริง ๆ แล้ว ภาษา C มันไม่มี String แต่มันเป็น Array of Char แทน เช่น เราต้องการรับชื่อเราเข้าไป

char name[20];
scanf("%s"name);

ก็ปกติเลย ก่อนอื่นเรารสร้าง Array ของ Char ขึ้นมาก่อน ให้ชื่อว่า name แล้วเราก็ scanf(); เข้ามา โดยใช้ String Format เป็น "%s" แต่ ๆ ๆ ทำไมที่ name ถึงไม่มี Ampersand ล่ะ ? เรื่องนี้เก็บไว้เล่าในเรื่อง Pointer ล่ะกัน เพราะมันเกี่ยวข้องกันอยู่ ตอนนี้เอาเป็นว่า ถ้าเราใช้ %s แล้วข้างหลังเป็น Array ของ char ก็ไม่ต้องใส่ Ampersand ไปก่อนล่ะกัน ถ้าอธิบายเดี่ยวจะยาวเวอร์ !

แต่เดี๋ยวก่อน ! ! !

นอกจาก scanf(); แล้ว ตัวภาษา C ยังมีคำสั่งอื่นอีกที่ใช้รับค่าเข้ามานอกจาก scanf(); นั่นคือ getchar(), getch(), getche() มาดูกันทีล่ะตัวกันเลย

  • getchar() - เจ้านี่จะทำงานคล้าย ๆ กับ scanf() เลย แต่ต่างกันแค่มันรับได้แค่ตัวอักษร (char) เท่านั้นและมันยังรับได้ตัวเดียวอีก น่าเศร้าแท้ Syntax ของมันก็คือ getchar(ตัวแปร); ย้ำว่าตัวแปรนะ ไม่ใช้ Address เพราะฉะนั้นไม่ต้องใส่ Ampersand
  • getch() - อันนี้จะต่างจาก getchar() นิดหน่อย เมื่อตอน getchar(); เวลาเรากด แล้วมันก็จะขึ้นบนหน้าจอ เสร็จแล้วเราก็ต้องกด Enter ด้วย แต่ getch(); แปลกกว่าชาวบ้าน กดปุ๊บไปปุ๊บ ไม่ขึ้นอะไรทั้งนัน ไม่ต้องกด Enter แค่กดปุ่มตามที่เราต้องการเอง
  • getche() - มันจะต่างจาก getch(); นิดหน่อยตรงที่ getch() นั้นเวลาเรากดแล้วมันก็ไม่แสดงอะไร แต่โปรแกรมเราไปเลย แต่เจ้า getche() มันจะแสดงบนหน้าจอว่าเรากดอะไรเข้าไป แต่เราก็ยังไม่ต้องกด Enter เหมือนเดิมนะ

แต่ก็ยังไม่จบอยู่ดี แฮะ ๆ ๆ

เพราะเรายังเหลืออีกคำสั่งเพิ่มขึ้นมา นั่นคือ gets(); หรือก็ย่อมาจาก Get String นั่นเอง หน้าที่ของมันก็ตามชื่อเลย Get String เข้ามานั่นเอง มันจะรับค่าเข้ามาตั้งแต่เริ่มบรรทัดจนสุดบรรทัดเลยทีเดียว มาลองใช้กัน

#include <stdio.h>

int main ()
{
   char name [20];
   gets(name);
}

วิธีใช้ก็ง่ายมาก ๆ เลย เราก็แค่เรียกคำสั่ง gets แล้วข้างในก็เป็นชื่อตัวแปรของเราได้เลย เป็นอันจบ

gets() ต่างจาก scanf(); ยังไง ?

#include <stdio.h>
int main ()
{
   char name[20];

   //using scanf();
   scanf("%s",name);
   printf("%s"name);

   //using gets();
   gets(name);
   printf("%s"name);

   return 0;
}

ในโค๊ตด้านบน เราทดลองเปรียบเทียบ การใช้ scanf() และ gets() ทีนี้ ถ้าเรา Input เข้าไปเหมือนกันทั้ง 2 รอบ โดยผมจะ Input เป็น ชื่อ สกุล ผมล่ะกัน (Arnon Puitrakul)
รอบแรกทาง scanf() เสร็จ printf() ออกมาผลก็จะเป็นแค่ Arnon เท่านั้น เพราะ scanf(); พอเจอ ช่องว่างมันก็ถือว่าจบแล้ว ฉะนั้นนามสกุลผมเลยหายไป
แต่พอมา gets ออกมากลายเป็น Arnon Puitrakul เลยเพราะว่า gets มันอ่านทั้งบรรทัดเลย ไม่สนว่าจะมีช่องว่างอะไรมั้ย เอาให้มันจบบรรทัดไปเลย

สรุป ! ! !

และก็จบอีกเรื่องแล้วกับการ Input สรุปนะครับ คำสั่งที่เราใช้ในการ Input มีหลายคำสั่งมาก ๆ เลย แต่เราก็ต้องเลือกให้เข้ากับงานของเราที่จะเขียนด้วย ถ้างานของเราเป็นรับอะไรง่าย ๆ เช่นตัวเลข scanf(); ก็เป็นทางเลือกที่ไม่เลวเลย แต่ถ้า เราต้องการให้ User เลือก Y/N เราก็ควรที่จะต้องใช้ getche() ก็น่าจะโอเคใช่มั้ยครับ ฉะนั้น อย่างที่บอก เวลาเราใช้ก็ต้องเลือกใช้ดี ๆ นะครับ สวัสดีครับ

Read Next...

จัดการเรื่องแต่ละมื้อ แต่ละเดย์ด้วย Obsidian

จัดการเรื่องแต่ละมื้อ แต่ละเดย์ด้วย Obsidian

Obsidian เป็นโปรแกรมสำหรับการจด Note ที่เรียกว่า สารพัดประโยชน์มาก ๆ เราสามารถเอามาทำอะไรได้เยอะมาก ๆ หนึ่งในสิ่งที่เราเอามาทำคือ นำมาใช้เป็นระบบสำหรับการจัดการ Todo List ในแต่ละวันของเรา ทำอะไรบ้าง วันนี้เราจะมาเล่าให้อ่านกันว่า เราจัดการะบบอย่างไร...

Loop แท้ไม่มีอยู่จริง มีแต่ความจริงซึ่งคนโง่ยอมรับไม่ได้

Loop แท้ไม่มีอยู่จริง มีแต่ความจริงซึ่งคนโง่ยอมรับไม่ได้

อะ อะจ๊ะเอ๋ตัวเอง เป็นยังไงบ้างละ เมื่อหลายเดือนก่อน เราไปเล่าเรื่องกันขำ ๆ ว่า ๆ จริง ๆ แล้วพวก Loop ที่เราใช้เขียนโปรแกรมกันอยู่ มันไม่มีอยู่จริง สิ่งที่เราใช้งานกันมันพยายาม Abstract บางอย่างออกไป วันนี้เราจะมาถอดการทำงานของ Loop จริง ๆ กันว่า มันทำงานอย่างไรกันแน่ ผ่านภาษา Assembly...

Monitor การทำงาน MySQL ด้วย Prometheus และ Grafana

Monitor การทำงาน MySQL ด้วย Prometheus และ Grafana

นอกจากการทำให้ Application รันได้แล้ว อีกเรื่องที่สำคัญไม่แพ้กันคือการวางระบบ Monitoring ที่ดี วันนี้เราจะมาแนะนำวิธีการ Monitor การทำงานของ MySQL ผ่านการสร้าง Dashboard บน Grafana กัน...

เสริมความ"แข็งแกร่ง" ให้ SSH ด้วย fail2ban

เสริมความ"แข็งแกร่ง" ให้ SSH ด้วย fail2ban

จากตอนที่แล้ว เราเล่าในเรื่องของการ Harden Security ของ SSH Service ของเราด้วยการปรับการตั้งค่าบางอย่างเพื่อลด Attack Surface ที่อาจจะเกิดขึ้นได้ หากใครยังไม่ได้อ่านก็ย้อนกลับไปอ่านกันก่อนเด้อ วันนี้เรามาเล่าวิธีการที่มัน Advance มากขึ้น อย่างการใช้ fail2ban...