2.2 จัดความกว้างและตาราง
นาฬิกาดิจิทัลแสดง 07:05 ไม่ใช่ 7:5 ใบเสร็จร้านค้าเรียงราคาให้ตรงกันเป็นคอลัมน์ โจทย์หลายข้อสั่งรูปแบบแบบนี้มาตรงๆ เช่น "พิมพ์เวลาเป็นเลขสองหลัก" หรือ "พิมพ์ตารางตามตัวอย่าง" หน้านี้ใช้ตัวเลขที่ใส่ไว้หลัง % กำหนดว่าแต่ละช่องกว้างเท่าไร ชิดซ้ายหรือขวา และเติมอะไรลงในที่ว่าง
กำหนดความกว้างขั้นต่ำ
ตัวอย่างนี้ใส่ [ กับ ] ครอบไว้ จะได้มองเห็นว่าช่องว่างอยู่ตรงไหน
#include <stdio.h>
int main()
{
int score = 42;
printf("[%d]\n", score);
printf("[%5d]\n", score);
printf("[%-5d]\n", score);
printf("[%05d]\n", score);
printf("[%3d]\n", 123456);
return 0;
}
[42]
[ 42]
[42 ]
[00042]
[123456]
| เขียน | ความหมาย | 42 ได้ |
|---|---|---|
%5d | กว้างอย่างน้อย 5 ตัว ชิดขวา เติมช่องว่างด้านซ้าย | [ 42] |
%-5d | กว้างอย่างน้อย 5 ตัว ชิดซ้าย เติมช่องว่างด้านขวา | [42 ] |
%05d | กว้างอย่างน้อย 5 ตัว เติมเลข 0 ด้านซ้ายแทนช่องว่าง | [00042] |
บรรทัดที่ 10 สำคัญ ตัวเลขที่ยาวกว่าความกว้าง ไม่ถูกตัด printf พิมพ์ครบทั้ง 6 หลัก ความกว้างจึงเป็นแค่ความกว้างขั้นต่ำ ถ้าค่าในตารางยาวเกินช่อง คอลัมน์จะเบี้ยว ต้องเลือกความกว้างจากขอบเขตของข้อมูลในโจทย์
เลข 0 นำหน้า
โปรแกรมแปลงนาทีเป็นชั่วโมงในหน้า 1.2 พิมพ์ 7 hours 5 minutes ถ้าอยากได้แบบนาฬิกาดิจิทัล ใช้ %02d คือกว้าง 2 ตัว เติม 0 ข้างหน้า
#include <stdio.h>
int main()
{
int total;
scanf("%d", &total);
int hours = total / 60;
int minutes = total % 60;
printf("%02d:%02d\n", hours, minutes);
return 0;
}
425
07:05
ค่าที่มีสองหลักอยู่แล้วอย่าง 45 ก็พิมพ์ 45 ตามปกติ เลข 0 เติมเฉพาะตอนที่หลักไม่พอ รูปแบบเดียวกันใช้กับวันที่ 05/03/2569 หรือรหัสนักเรียน %05d ที่ต้องยาว 5 หลักเสมอ
ใช้กับชนิดอื่น
ความกว้างใส่ได้กับทุกตัวกำหนด ส่วน %f ใส่ได้ทั้งความกว้างและจำนวนทศนิยมพร้อมกัน เช่น %8.2f คือกว้าง 8 ตัว ทศนิยม 2 ตำแหน่ง
#include <stdio.h>
int main()
{
printf("[%8.2f]\n", 3.14159);
printf("[%-8.2f]\n", 3.14159);
printf("[%10s]\n", "Mali");
printf("[%-10s]\n", "Mali");
printf("[%3c]\n", 'A');
printf("[%05d]\n", -42);
return 0;
}
[ 3.14]
[3.14 ]
[ Mali]
[Mali ]
[ A]
[-0042]
- ความกว้างของ
%8.2fนับทุกตัวอักษร3.14ยาว 4 ตัวรวมจุด จึงเติมช่องว่างอีก 4 ช่อง - เครื่องหมายลบก็นับในความกว้าง
-42กับ%05dได้-0042ยาว 5 ตัวพอดี
จัดตาราง
ตารางคะแนนที่แต่ละคอลัมน์ตรงกัน ทำได้ด้วยการให้ทุกบรรทัดใช้ความกว้างชุดเดียวกัน
#include <stdio.h>
int main()
{
printf("%-10s%6s%6s%8s\n", "Name", "Math", "Sci", "Avg");
printf("%-10s%6d%6d%8.2f\n", "Mali", 78, 91, (78 + 91) / 2.0);
printf("%-10s%6d%6d%8.2f\n", "Somchai", 85, 62, (85 + 62) / 2.0);
printf("%-10s%6d%6d%8.2f\n", "Kanokwan", 100, 97, (100 + 97) / 2.0);
return 0;
}
Name Math Sci Avg
Mali 78 91 84.50
Somchai 85 62 73.50
Kanokwan 100 97 98.50
วิธีคิด
- คอลัมน์ชื่อเป็นข้อความ คนอ่านชินกับข้อความชิดซ้าย จึงใช้
%-10sกว้างกว่าชื่อที่ยาวที่สุด (8 ตัว) เพื่อให้มีช่องว่างคั่นคอลัมน์ถัดไป - คอลัมน์ตัวเลขชิดขวา หลักหน่วยจะตรงกัน เทียบค่ามากน้อยง่าย
- หัวตารางใช้ความกว้างเดียวกับข้อมูลในคอลัมน์นั้น
"Math"ใช้%6sคู่กับ%6dจึงชิดขวาตรงกับตัวเลข
ตอนนี้ต้องเขียน printf ทีละแถว พอเรียนวนซ้ำในบทที่ 4 และอาเรย์ในบทที่ 5 จะพิมพ์ตารางกี่แถวก็ได้ด้วยคำสั่งชุดเดียว แต่วิธีกำหนดความกว้างยังเป็นแบบนี้
ลองทำให้พัง
แบบที่ 1 ลืมเลข 0
ในโปรแกรม clock เขียน %2d แทน %02d
#include <stdio.h>
int main()
{
int total;
scanf("%d", &total);
printf("%2d:%2d\n", total / 60, total % 60);
return 0;
}
425
7: 5
กว้าง 2 ตัวครบ แต่เติมด้วยช่องว่าง ไม่มีคำเตือนใดๆ บนจอมองผ่านๆ แทบไม่เห็นช่องว่างหน้าเลข 7 แต่ grader เห็น ข้อนี้ได้ผิด ถ้ามองด้วยตาไม่ออก ลองพิมพ์ [ ] ครอบแบบตัวอย่างแรกของหน้านี้ แล้วค่อยลบออกก่อนส่ง
แบบที่ 2 จัดตารางด้วย \t
ในหน้า 2.1 \t ทำให้คอลัมน์ตรงกันได้ ลองใช้กับตารางคะแนนแทนความกว้าง
#include <stdio.h>
int main()
{
printf("Name\tMath\tSci\n");
printf("Mali\t78\t91\n");
printf("Somchai\t85\t62\n");
printf("Kanokwan\t100\t97\n");
return 0;
}
Name Math Sci
Mali 78 91
Somchai 85 62
Kanokwan 100 97
สามแถวแรกตรงกัน แต่ Kanokwan ยาว 8 ตัว ไปถึงจุดหยุด tab แรกพอดี \t จึงกระโดดไปจุดหยุดถัดไปแทน ทั้งแถวเลื่อนไปหนึ่งคอลัมน์ \t ใช้ได้ถ้ารู้แน่ว่าข้อความทุกตัวสั้นกว่าระยะ tab ถ้าไม่แน่ใจ ใช้ความกว้างแบบตัวอย่าง table ที่คุมได้ทุกตัวอักษร
อีกเรื่องคือโจทย์ที่ตัวอย่างผลลัพธ์ดูเหมือนเว้นหลายช่อง อาจเป็นช่องว่างหลายตัวหรือ tab ตัวเดียวก็ได้ ซึ่ง grader ถือว่าต่างกัน ถ้าโจทย์ไม่ได้บอกชัด ให้คัดลอกตัวอย่างผลลัพธ์มาดูว่าเป็นอะไร
แบบที่ 3 ลืมจุดใน %.2f
#include <stdio.h>
int main()
{
double average = 81.666667;
printf("%2f\n", average);
return 0;
}
81.666667
ตั้งใจจะได้ 81.67 แต่ได้ทศนิยม 6 ตำแหน่ง และไม่มีคำเตือน เพราะ %2f ถูกไวยากรณ์ แปลว่า "กว้างอย่างน้อย 2 ตัว ทศนิยมตามปกติ" ตัวเลขหน้าจุดคือความกว้าง ตัวเลขหลังจุดคือจำนวนทศนิยม จุดตัวเดียวเปลี่ยนความหมายทั้งหมด
สรุป
%5dชิดขวา%-5dชิดซ้าย%05dเติม 0 ทั้งหมดคือกว้างอย่างน้อย 5 ตัว- ค่าที่ยาวกว่าความกว้างพิมพ์ครบ ไม่ถูกตัด
%02dใช้กับเวลาและวันที่%8.2fคือกว้าง 8 ทศนิยม 2- จัดตารางด้วยความกว้างชุดเดียวกันทุกแถว ข้อความชิดซ้าย ตัวเลขชิดขวา
\tเบี้ยวเมื่อข้อความยาวถึงระยะ tab ความกว้างคุมได้แน่นอนกว่า