Chapter 3 More on Input & Output
Program Input ข้อมูลมาจากที่อยู่ภายนอกโปรแกรม input ทุกชนิดใน C อยู่ในรูป stream
Program Output ข้อมูลที่ถูกส่งไปภายนอกโปรแกรม output ทุกชนิดใน C อยู่ในรูป stream
Stream Stream คือ อักขระ หรือ ไบต์ข้อมูลที่เรียงต่อกัน Input stream คือ ไบต์ข้อมูล ที่ไหลเข้าไปในโปรแกรม Output stream คือ ไบต์ข้อมูล ที่ไหลออกจากโปรแกรม ข้อดีของ stream คือ device independent ช่วยให้ไม่ต้องเขียนฟังก์ชันเพื่อนำเข้าหรือส่งออกข้อมูลให้กับแต่ละอุปกรณ์ อาทิ แป้นพิมพ์ ดิสก์ โปรแกรมสามารถมองเห็น input/output ได้โดยไม่สนใจว่าจะมาจากหรือไปที่ไหน C stream ถูกเชื่อมต่อกับแฟ้ม โดยที่แฟ้มถูกใช้เป็นตัวกลางระหว่าง stream และ อุปกรณ์นำเข้าหรือส่งออก โดยมีระบบปฏิบัติการและไลบราลีฟังก์ชัน ช่วยในการเชื่อมต่อประสาน
Text vs Binary Streams C streams มี 2 โหมด คือ text และ binary text stream ประกอบด้วยเฉพาะอักขระเท่านั้นยาวได้ถึง 255 อักขระ และจบด้วยเครื่องหมาย end-of-line หรือ newline บางอักขระใน text stream มีความหมายพิเศษ อาทิ อักขระnewline binary stream ประกอบด้วยข้อมูลชนิดต่างๆ อาทิ อักขระ ไบต์ข้อมูล ข้อมูลเหล่านี้มีความหมายตรงตามลักษณะที่ปรากฎ ไม่สามารถตีความหมายเป็นอื่นได้ ส่วนใหญ่จะใช้กับ แฟ้มในดิสก์
Predefined streams ANSI C (American standard national institute for the C programming language) กำหนดไว้ 5 streams ได้แก่ stdin standard input keyboard stdout standard output screen stderr standard error screen stdprn standard printer printer (LPT1) stdaux standard auxilary Serial port (COM1) ทั้ง 5 stream มาตรฐานนี้ เป็น text-mode streams บางครั้งเรียก stream เหล่านี้ว่า standard input/output files
Standard stream เมื่อมีการใช้ฟังก์ชัน printf() หรือ puts() เพื่อแสดงข้อความบนจอภาพ หมายถึงว่า มีการใช้ stdout stream เมื่อมีการใช้ฟังก์ชัน scanf() หรือ gets() เพื่ออ่านข้อมูลจากแป้นพิมพ์ หมายถึงว่า มีการใช้ stdin stream Standard stream จะถูกเปิดโดยอัตโนมัติ Stream อื่น จะเปิดเมื่อมีการสั่งให้เปิด
C’s Stream Functions C standard library มีหลายฟังก์ชันที่ใช้ติดต่อกับ stream input และ output ฟังก์ชันเหล่านี้ ส่วนใหญ่แล้วมี 2 แบบ ใช้ stream มาตรฐาน โปรแกรมเมอร์ต้องกำหนด stream
ใช้ stream มาตรฐาน ต้องกำหนด ชื่อ stream การกระทำ printf() fprintf() formatted output vprintf() vfprint() with variable argument list puts() fputs() string output putchar() putc(),fputc() character output scanf() fscanf() formatted input gets() fgets() string input getchar() getc(),fgetc() character input perror - string output to stderr only
Equivalence of streams input output gets() ใช้เพื่อป้อนข้อความ 1 บรรทัดจากแป้นพิมพ์ (stdin) gets() คืนค่าตัวชี้ให้ string และถูกใช้เป็นพารามิเตอร์ของ puts() เพื่อแสดง string บนจอภาพ (stdout)
Accepting Keyboard Input Input functions แบ่งเป็น 3 ระดับ Character input Line input Formatted input
Character input อ่าน input จาก stream ครั้งละ 1 อักขระ เมื่อฟังก์ชันถูกเรียก จะส่งอักขระถัดไปใน stream หรือ ถ้าถึงท้ายแฟ้มไม่มีอักขระ หรือมีข้อผิดพลาด จะส่ง EOF กลับมาให้ EOF เป็น ค่าคงที่ ถูกกำหนดไว้ใน stdio.h มีค่าเท่ากับ -1
Character input function Character input function จะทำงานแตกต่างกันในลักษณะของการใช้ buffer หรือ echo buffered ระบบปฏิบัติการเก็บทุกอักขระไว้ในความจำชั่วคราวจนกระทั่งกดแป้น Enter จึงส่งอักขระไปยัง stdin stream unbuffered แต่ละอักขระถูกส่งไปยัง stdin ทันทีที่กดแป้นพิมพ์ echoing อักขระถูกส่งไปยัง stdout โดยอัตโนมัติทันทีที่ได้รับ non-echoing อักขระถูกส่งไปยัง stdin (ไม่ใช่ stdout เพราะ stdout ถูกกำหนดให้จอภาพ)
getchar() : buffered with echo 1. getchar () ถูกเรียก และ รอรับอักขระจากแป้นพิมพ์ แต่ getchar () เป็น buffered input function จึงไม่ได้รับอักขระใดๆจนกว่าจะมีการกด Enter และ ทุกแป้นที่กดจะถูก echo บนจอภาพ
getchar() : buffered with echo 2. เมื่อกดแป้น Enter ระบบปฏิบัติการจะส่งทุกอักขระที่ป้อนเข้าไปรวมทั้งอักขระ newline ไปยัง stdin ฟังก์ชัน getchar () คืนค่าครั้งละ 1 อักขระ แล้วนำไปเก็บไว้ใน c
getchar() : buffered with echo 3. เปรียบเทียบอักขระกับอักขระ newline ถ้าไม่ใช่อักขระ newline ฟังก์ชัน putchar จะแสดงอักขระบนจอภาพ ถ้าใช่อักขระ newline จะจบการวนซ้ำ
getchar() : input an entire line of text
getch () : unbuffered without echo output getch () ถูกเรียก เมื่อได้รับอักขระจากแป้นพิมพ์ จะส่งอักขระนั้นกลับไปทันทีโดยไม่รอให้กด enter และไม่มี echo จึงไม่มีการแสดงอักขระที่ป้อน
Buffered character input function เมื่อกด enter แป้นพิมพ์จะส่ง carriage return ไปให้ stdin และจะแปลความหมายเป็น newline (\n) จึงต้องทดสอบกับ \n เพื่อดูว่ามีการกด enter หรือไม่ Unbuffered character input function carriage return ถูกป้อนเข้าไปเป็น \r และไม่มีการแปลความหมาย
getch () : input an entire line of text อักขระที่ป้อนจะไม่ถูกแสดง เมื่อกดEnter จึงแสดง buffer
getche() เหมือน getch() ต่างกันเพียงecho อักขระไปที่ stdout อักขระตัวหนึ่ง echo ของ getche() อีกตัวหนึ่งเกิดจาก putchar
getc() & fgetc() ไม่สามารถทำงานกับ stdin ได้โดยอัตโนมัติ จะต้องมีการกำหนด input stream ใช้สำหรับอ่านอักขระจากแฟ้มในดิสก์
Getting Special Keys F1-F10 arrow keys key combination ctrl + PgDn alt +1 คีย์เหล่านี้แตกต่างจากคีย์อักขระปกติ
How special keys work คีย์เหล่านี้ส่ง 2 ค่า ไปยัง stdin ตัวอย่าง ค่าแรก อักขระ null เป็น เลขศูนย์ ค่าที่ 2 เป็นตัวเลขที่แสดงถึงคีย์ที่กด ตัวอย่าง กด F1 จะส่งค่า 0 และ 59 กด Home จะส่งค่า 0 และ 71 คีย์ที่คืน รหัสของ 2 อักขระ เรียกว่า extended keys รหัสของคีย์ เรียกว่า extended key codes
Symbolic constants for extended keys defined in conio.h #define _KB_F1 59 #define _KB_F2 60 #define _KB_F10 68 #define _KB_HOME 71 #define _KB_UP 72 #define _KB_PGUP 73 #define _KB_LEFT 75 #define _KB_RIGHT 77 #define _KB_END 79
How does a program deal with extended key input? รับอักขระจาก stdin จนกระทั่งได้รับอักขระ 0 หรือ \0 ซึ่งถือว่าเป็นการส่งสัญญาณว่า จะรับอักขระพิเศษ ค่าถัดไปจะเป็นตัวแสดงว่า กดคีย์ใด
Line Input อ่านทีละบรรทัดจาก input stream gets() อ่านอักขระจาก stdin จนกว่าจะพบ \n แล้วนำไปเก็บใน string fgets() คล้าย gets() แต่ยืดหยุ่นกว่า มักใช้ในการอ่านข้อมูลจากแฟ้มในดิสก์
Single character input getchar function เป็น standard C I/O library คืนค่า อักขระตัวเดียว จากอุปกรณ์รับข้อมูลมาตรฐาน (แป้นพิมพ์) character variable = getchar(); ตัวอย่าง char c; … c = getchar();
กรณีอ่านข้อมูลจากแฟ้ม แล้วพบ end-of-file จะคืนค่าคงที่ EOF (ค่านี้กำหนดไว้ใน stdio.h) ซึ่งปกติจะเป็น -1 ขึ้นกับคอมไพเลอร์ กรณีอ่านข้อมูลทีละตัวอักษรหลายตัว ให้ใช้การวนซ้ำ
Single character output putchar function เป็น standard C I/O library ส่งอักขระตัวเดียวไปยัง อุปกรณ์แสดงผลมาตรฐาน (จอภาพ) char c; … putchar (c);
Entering input data scanf (control string, arg1, arg2, …, argn) format specifiers ขึ้นต้นด้วย % เป็น string ที่ประกอบด้วยรายละเอียดของรูปแบบ arg1, arg2,…, argn - เป็นที่อยู่ของตัวแปรในหน่วยความจำ ซึ่งเป็นที่เก็บของค่าที่อ่านเข้ามา
Format specifiers ขึ้นต้นด้วย % ตามด้วย type conversion character
Type conversion characters Format specifier Data Type %c character %d decimal integer %i %f floating point, decimal %e floating point, exponential %o octal integer %s string of characters %x hexadecimal character %u unsign decimal integer
item เป็นที่อยู่ของตัวแปรแถวลำดับ item เพื่อนำค่าที่อ่านเข้ามาไปเก็บ หน่วยความจำ ที่อยู่ item unit price abcd 12 5.75 8760 8764 8768 scanf (“%s %d %f”, item, &unit, &price); item เป็นที่อยู่ของตัวแปรแถวลำดับ item เพื่อนำค่าที่อ่านเข้ามาไปเก็บ &unit เป็นที่อยู่ของตัวแปร unit เพื่อนำค่าที่อ่านเข้ามาไปเก็บ &price เป็นที่อยู่ของตัวแปร price เพื่อนำค่าที่อ่านเข้ามาไปเก็บ
scanf() & String control string ที่ขึ้นต้นด้วยการอ่านข้อมูลชนิด char ควรขึ้นต้นด้วย blank space ซึ่งจะทำให้ การป้อนข้อมูลก่อนหน้านี้(เช่นการกดแป้น enter) ไม่มีผลต่อ การป้อนข้อมูลให้ฟังก์ชัน scanf () การป้อนอักขระเข้าไปใน s-type ต้องจบด้วย space การป้อนข้อความที่ลงท้ายด้วย space ต้องใช้ getchar() แล้ววนซ้ำ
เมื่อพบอักขระแรกที่ไม่ตรงกับใน [] จะหยุดรับอักขระ แล้วเพิ่ม \0 เข้าที่ท้าย string
scanf() & String
scanf() & String
scanf() with maximum field width
Writing output data printf (control string, arg1, arg2, …, argn) format specifiers ขึ้นต้นด้วย % เป็น string ที่ประกอบด้วยรายละเอียดของรูปแบบ arg1, arg2,…, argn - เป็นที่อยู่ของตัวแปรในหน่วยความจำ ซึ่งเป็นที่เก็บของค่าที่อ่านเข้ามา
printf (“control string”,argument list); printf () function printf (“control string”,argument list); control string ประกอบด้วย 2 ส่วน ตัวอักขระที่จะแสดง format specifiers ขึ้นต้นด้วย % argument list : ชื่อของตัวแปรที่จะแสดง printf (“Name : %s”, name); printf (“No : %d Score : %6.2f”, n, score);
#include <stdio.h> main () { int i, j, k; i = 368; j = 02456; k = 0x2ab9; printf (“Decimal Octal Hexadecimal”); printf (“ %d %o %x”, i, i, i); printf (“ %d %o %x”, j, j, j); printf (“ %d %o %x, k, k, k); return 0; } Decimal Octal Hexadecimal 368 560 170 1326 2456 52e 10937 25271 2ab9
#include <stdio.h> main () { float i, j; double m,n; j = 4.345678e2; m = 12.145678903045; n = 2.3459012345e-10 printf (“\n\n Fixed point format”); printf (“\n i=%f j=%f m=%f n=%f”, i, j, m, n); printf (“\n\n Exponential format”, i, j, m, n); printf (“\n i=%e j=%e, m=%e n=%e”, i, j, m, n); return 0; } Fixed point format i=100.123456 j=434.567810, m=12.145679, n=0.000000 Exponential format i=1.00123e+02 j=4.34568e+02 m=1.21457e+01 n=2.34590e-10
%-10.3f 245634.567 904.340 --- ชิดซ้าย จำนวนหลักทศนิยม จำนวนหลัก หรือ ความกว้างทั้งหมด รวมจุด และ ทศนิยม 245634.567 904.340 --- 3 blank space
printf (“\n%-f”,1.234); printf (“\n%-10.3f”,10.2346); printf (“\n%-12.5f”,1000.34567); 1.234000 10.235 1000.34567
%+10.3f +45634.567 +904.340--- ขึ้นต้นด้วยเครื่องหมาย จำนวนหลักทศนิยม จำนวนหลัก หรือ ความกว้างทั้งหมด รวมจุด และ ทศนิยม +45634.567 +904.340---
gets(str) อ่านอักขระ (รวมที่ว่าง) จาก stdin แล้วนำไปไว้ใน str จนพบเครื่องหมาย newline หรือ EOF จากนั้นจะเติม \0 ไว้หลังอักขระใน str puts(str) นำอักขระจาก str ไปแสดงที่ stdout