6.6 แบบฝึกหัด
เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น
ข้อ 1 ป้ายตัวพิมพ์ใหญ่
ครูให้น้องเขียนชื่อกิจกรรมลงป้ายหน้าห้อง ป้ายต้องใช้ตัวพิมพ์ใหญ่ทั้งหมดจะได้อ่านจากไกลๆ ได้ ให้รับชื่อกิจกรรม S ที่เป็นคำเดียว แล้วพิมพ์ออกมาเป็นตัวพิมพ์ใหญ่ทั้งคำ
ข้อมูลเข้า
คำ S หนึ่งคำ ประกอบด้วยตัวอักษรภาษาอังกฤษพิมพ์ใหญ่หรือพิมพ์เล็กเท่านั้น ไม่มีช่องว่าง ความยาวของ S อยู่ระหว่าง 1 ถึง 100 ตัว
ข้อมูลออก
S ที่เปลี่ยนเป็นตัวพิมพ์ใหญ่ทุกตัว
SportsSPORTSดูคำใบ้
วนทีละช่องจนเจอ '\0' ถ้าช่องนั้นเป็นตัวพิมพ์เล็ก ให้เปลี่ยนด้วย c - 'a' + 'A' หรือ toupper จากหน้า 6.1 ตัวที่เป็นตัวพิมพ์ใหญ่อยู่แล้วต้องไม่เปลี่ยน อาเรย์ต้องมีอย่างน้อย 101 ช่อง
ดูเฉลย
#include <stdio.h>
int main()
{
char word[105];
scanf("%s", word);
for (int i = 0; word[i] != '\0'; i++) {
if (word[i] >= 'a' && word[i] <= 'z') {
word[i] = word[i] - 'a' + 'A';
}
}
printf("%s\n", word);
return 0;
}ข้อ 2 ผลบวกเลขโดดของเลขยักษ์
ครูเขียนตัวเลขยาวมากเต็มกระดาน แล้วถามว่าถ้าเอาเลขโดดทุกหลักมาบวกกันจะได้เท่าไร เช่น 2569 ได้ 2 + 5 + 6 + 9 = 22 ให้เขียนโปรแกรมตอบคำถามนี้
ข้อมูลเข้า
จำนวนเต็มบวก N หนึ่งตัว ไม่มีเลข 0 นำหน้า N มีจำนวนหลักตั้งแต่ 1 ถึง 1000 หลัก
ข้อมูลออก
ผลบวกของเลขโดดทุกหลักของ N
256922ดูคำใบ้
เลข 1000 หลักใหญ่เกินกว่า long long ที่เก็บได้แค่ 19 หลัก ให้รับเป็นสตริงด้วย %s แล้วแปลงทีละตัวด้วย c - '0' ผลบวกมากสุดคือ 9 × 1000 ซึ่ง int เก็บได้สบาย
ดูเฉลย
#include <stdio.h>
int main()
{
char number[1005];
scanf("%s", number);
int sum = 0;
for (int i = 0; number[i] != '\0'; i++) {
sum += number[i] - '0';
}
printf("%d\n", sum);
return 0;
}ข้อ 3 นับชนิดตัวอักษร
ครูพิมพ์ประกาศหนึ่งบรรทัดก่อนส่งเข้ากลุ่มของห้อง แล้วอยากรู้ว่าในประกาศนั้นมีตัวพิมพ์ใหญ่ ตัวพิมพ์เล็ก ตัวเลข และช่องว่าง อย่างละกี่ตัว
ข้อมูลเข้า
ข้อความหนึ่งบรรทัด ยาว 1 ถึง 1000 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข ช่องว่าง และเครื่องหมายวรรคตอน ข้อความอาจขึ้นต้นหรือลงท้ายด้วยช่องว่าง
ข้อมูลออก
บรรทัดเดียว มีจำนวนเต็มสี่ตัวคั่นด้วยช่องว่าง คือจำนวนตัวพิมพ์ใหญ่ จำนวนตัวพิมพ์เล็ก จำนวนตัวเลข และจำนวนช่องว่าง ตัวขึ้นบรรทัดใหม่ท้ายข้อความไม่นับเป็นช่องว่าง
Bus 8 leaves at 7:45 AM.3 10 4 5ดูคำใบ้
ข้อความมีช่องว่าง %s จะได้แค่คำแรก ต้องรับด้วย fgets ตามหน้า 6.3 ระวังตัว '\n' ที่ fgets ติดมา ถ้านับช่องว่างด้วย isspace จะนับ '\n' เกินมาหนึ่งตัว เทียบกับ ' ' ตรงๆ ปลอดภัยกว่า
ดูเฉลย
#include <stdio.h>
int main()
{
char line[1005];
fgets(line, sizeof line, stdin);
int upper = 0, lower = 0, digits = 0, spaces = 0;
for (int i = 0; line[i] != '\0'; i++) {
char c = line[i];
if (c >= 'A' && c <= 'Z') {
upper++;
} else if (c >= 'a' && c <= 'z') {
lower++;
} else if (c >= '0' && c <= '9') {
digits++;
} else if (c == ' ') {
spaces++;
}
}
printf("%d %d %d %d\n", upper, lower, digits, spaces);
return 0;
}ข้อ 4 หัวแถวท้ายแถว
ครูจะเรียงใบรายชื่อนักเรียนตามลำดับในพจนานุกรม แบบเดียวกับที่ strcmp ใช้ ก่อนเรียง ครูอยากรู้ว่าชื่อไหนจะอยู่บนสุด และชื่อไหนจะอยู่ล่างสุด
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N คือจำนวนนักเรียน โดยที่ 1 ≤ N ≤ 1000
อีก N บรรทัด บรรทัดละหนึ่งชื่อ ชื่อประกอบด้วยตัวพิมพ์เล็กภาษาอังกฤษเท่านั้น ยาว 1 ถึง 20 ตัว ชื่ออาจซ้ำกันได้
ข้อมูลออก
บรรทัดแรกพิมพ์ชื่อที่มาก่อนทุกชื่อ บรรทัดที่สองพิมพ์ชื่อที่มาหลังทุกชื่อ
5
somchai
malee
anan
wichai
kanokwananan
wichaiดูคำใบ้
เหมือนหาค่ามากสุดและน้อยสุดในบทที่ 5 แต่เทียบด้วย strcmp และเก็บด้วย strcpy เพราะใช้ < กับ = กับสตริงไม่ได้ ให้ค่าเริ่มต้นของทั้งสองตัวเป็นชื่อแรกที่อ่านได้
ดูเฉลย
#include <stdio.h>
#include <string.h>
int main()
{
int n;
char name[25], first[25], last[25];
scanf("%d", &n);
scanf("%s", name);
strcpy(first, name);
strcpy(last, name);
for (int i = 1; i < n; i++) {
scanf("%s", name);
if (strcmp(name, first) < 0) {
strcpy(first, name);
}
if (strcmp(name, last) > 0) {
strcpy(last, name);
}
}
printf("%s\n%s\n", first, last);
return 0;
}ข้อ 5 ประโยคกระจก
ประโยคบางประโยคอ่านจากหลังมาหน้าได้เหมือนเดิม ถ้าไม่สนใจช่องว่าง เครื่องหมาย ตัวเลข และตัวพิมพ์ใหญ่เล็ก เช่น Was it a car or a cat I saw? เหลือเฉพาะตัวอักษรเป็น wasitacaroracatisaw ซึ่งกลับหลังแล้วเหมือนเดิม ให้ตรวจว่าประโยคที่ได้รับเป็นประโยคแบบนี้หรือไม่
ข้อมูลเข้า
ข้อความหนึ่งบรรทัด ยาว 1 ถึง 100000 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข ช่องว่าง และเครื่องหมายวรรคตอน มีตัวอักษรภาษาอังกฤษอย่างน้อยหนึ่งตัว
ข้อมูลออก
พิมพ์ YES ถ้าตัวอักษรภาษาอังกฤษในข้อความ เมื่อไม่สนตัวพิมพ์ใหญ่เล็ก อ่านจากหลังมาหน้าได้เหมือนจากหน้าไปหลัง ไม่อย่างนั้นพิมพ์ NO ตัวอื่นที่ไม่ใช่ตัวอักษรให้ข้ามไปทั้งหมด
Was it a car or a cat I saw?YESHello, WorldNOดูคำใบ้
ทำสองขั้น ขั้นแรกเดินทั้งบรรทัด เก็บเฉพาะตัวอักษรที่ผ่าน isalpha แปลงเป็นตัวพิมพ์เล็กด้วย tolower ลงอีกอาเรย์หนึ่ง ขั้นที่สองเช็ก palindrome กับอาเรย์ใหม่นั้นแบบในหน้า 6.5 บรรทัดยาวได้หนึ่งแสนตัว ประกาศอาเรย์ทั้งสองไว้นอก main
ดูเฉลย
#include <stdio.h>
#include <ctype.h>
char line[100005];
char letters[100005];
int main()
{
fgets(line, sizeof line, stdin);
int length = 0;
for (int i = 0; line[i] != '\0'; i++) {
if (isalpha(line[i])) {
letters[length] = tolower(line[i]);
length++;
}
}
int is_palindrome = 1;
for (int i = 0; i < length / 2; i++) {
if (letters[i] != letters[length - 1 - i]) {
is_palindrome = 0;
}
}
if (is_palindrome) {
printf("YES\n");
} else {
printf("NO\n");
}
return 0;
}ข้อ 6 ตัวอักษรยอดนิยม
ชมรมภาษาอังกฤษอยากรู้ว่าในข้อความหนึ่งบรรทัด ตัวอักษรตัวไหนถูกใช้บ่อยที่สุด โดยถือว่าตัวพิมพ์ใหญ่กับตัวพิมพ์เล็กเป็นตัวเดียวกัน เช่น B กับ b และไม่นับตัวที่ไม่ใช่ตัวอักษร
ข้อมูลเข้า
ข้อความหนึ่งบรรทัด ยาว 1 ถึง 100000 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข ช่องว่าง และเครื่องหมายวรรคตอน มีตัวอักษรภาษาอังกฤษอย่างน้อยหนึ่งตัว
ข้อมูลออก
บรรทัดเดียว พิมพ์ตัวอักษรที่พบบ่อยที่สุดเป็นตัวพิมพ์เล็ก ตามด้วยช่องว่างหนึ่งช่อง แล้วตามด้วยจำนวนครั้งที่พบ ถ้ามีหลายตัวที่พบบ่อยเท่ากัน ให้ตอบตัวที่มาก่อนในลำดับ a ถึง z
Banana Breada 4abc, cba!a 2ดูคำใบ้
นับด้วย int count[26] แบบในหน้า 6.5 ต้อง tolower ก่อนเสมอ ไม่อย่างนั้น M กับ m จะถูกนับแยกกัน แล้วหาช่องที่มากที่สุด ถ้าเทียบด้วย > ไม่ใช่ >= และไล่จากช่อง 0 ขึ้นไป ตัวที่เจอก่อนจะชนะเมื่อเสมอกันเอง
ดูเฉลย
#include <stdio.h>
#include <ctype.h>
char line[100005];
int main()
{
int count[26] = {0};
fgets(line, sizeof line, stdin);
for (int i = 0; line[i] != '\0'; i++) {
if (isalpha(line[i])) {
count[tolower(line[i]) - 'a']++;
}
}
int best = 0;
for (int i = 1; i < 26; i++) {
if (count[i] > count[best]) {
best = i;
}
}
printf("%c %d\n", 'a' + best, count[best]);
return 0;
}ข้อ 7 ถอดรหัสซีซาร์
น้องได้รับข้อความลับจากเพื่อน เพื่อนเข้ารหัสด้วยการเลื่อนตัวอักษรทุกตัวไปข้างหน้า K ตัวแบบวนรอบ เลยจาก z กลับมาที่ a และเลยจาก Z กลับมาที่ A ตัวพิมพ์ใหญ่ยังเป็นตัวพิมพ์ใหญ่ ตัวพิมพ์เล็กยังเป็นตัวพิมพ์เล็ก ส่วนตัวเลข ช่องว่าง และเครื่องหมายไม่ถูกเปลี่ยน ให้ถอดรหัสกลับเป็นข้อความเดิม
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม K โดยที่ 0 ≤ K ≤ 1000000000
บรรทัดที่สองคือข้อความที่เข้ารหัสแล้ว ยาว 1 ถึง 1000 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข ช่องว่าง และเครื่องหมายวรรคตอน
ข้อมูลออก
ข้อความเดิมก่อนเข้ารหัส หนึ่งบรรทัด
3
Vhh brx dw wkh jdwh dw 7 sp.See you at the gate at 7 pm.29
Cheud dqg bdnZebra and yakดูคำใบ้
มีกับดักสามจุด จุดแรก บรรทัดแรกเป็นตัวเลข บรรทัดที่สองเป็นข้อความที่มีช่องว่าง ต้องอ่านทิ้งให้ถึง '\n' ก่อนเรียก fgets ตามหน้า 6.3 จุดที่สอง K ใหญ่ถึง 109 ให้ % 26 ก่อน จุดที่สาม การถอยหลัง K ตัวเท่ากับเดินหน้า 26 - K % 26 ตัว ใช้สูตร (c - 'a' + shift) % 26 + 'a' ใน int อย่าบวกลบใน char ตรงๆ
ดูเฉลย
#include <stdio.h>
char text[1005];
int main()
{
int key;
scanf("%d", &key);
while (getchar() != '\n') {
}
fgets(text, sizeof text, stdin);
int shift = (26 - key % 26) % 26;
for (int i = 0; text[i] != '\0'; i++) {
char c = text[i];
if (c >= 'a' && c <= 'z') {
text[i] = (c - 'a' + shift) % 26 + 'a';
} else if (c >= 'A' && c <= 'Z') {
text[i] = (c - 'A' + shift) % 26 + 'A';
} else if (c == '\n' || c == '\r') {
text[i] = '\0';
}
}
printf("%s\n", text);
return 0;
}ข้อ 8 นับคำและคำที่ยาวที่สุด
ครูให้นักเรียนเขียนเรียงความภาษาอังกฤษหนึ่งย่อหน้า แล้วพิมพ์ส่งมาเป็นบรรทัดเดียว นักเรียนบางคนเคาะช่องว่างเกินหลายครั้ง ครูอยากรู้ว่าย่อหน้านั้นมีกี่คำ และคำที่ยาวที่สุดยาวกี่ตัวอักษร
ข้อมูลเข้า
ข้อความหนึ่งบรรทัด ยาว 1 ถึง 100000 ตัว ประกอบด้วยตัวพิมพ์เล็กภาษาอังกฤษและช่องว่างเท่านั้น คำคือกลุ่มตัวอักษรที่ติดกันโดยไม่มีช่องว่างคั่น ระหว่างคำอาจมีช่องว่างหลายช่อง และหัวหรือท้ายบรรทัดอาจมีช่องว่าง
ข้อมูลออก
บรรทัดเดียว มีจำนวนคำ ตามด้วยช่องว่าง แล้วตามด้วยความยาวของคำที่ยาวที่สุด ถ้าไม่มีคำเลยให้พิมพ์ 0 0
my school has a big library6 7 hello 1 5ดูคำใบ้
นับจุดเริ่มคำแบบในหน้า 6.5 ไม่ใช่นับช่องว่าง เพราะช่องว่างติดกันได้หลายช่องและอาจอยู่หัวหรือท้ายบรรทัด ความยาวคำปัจจุบันเพิ่มทีละหนึ่งเมื่อเจอตัวอักษร และกลับเป็น 0 เมื่อเจอช่องว่าง อย่าลืมกรณีที่บรรทัดมีแต่ช่องว่าง
ดูเฉลย
#include <stdio.h>
char line[100005];
int main()
{
fgets(line, sizeof line, stdin);
int words = 0, current = 0, longest = 0;
for (int i = 0; line[i] != '\0'; i++) {
if (line[i] >= 'a' && line[i] <= 'z') {
if (current == 0) {
words++;
}
current++;
if (current > longest) {
longest = current;
}
} else {
current = 0;
}
}
printf("%d %d\n", words, longest);
return 0;
}ข้อ 9 ขยายรหัสย่อ
โปรแกรมส่งข้อความรุ่นเก่าประหยัดเนื้อที่ด้วยการย่อตัวอักษรที่ซ้ำติดกัน เขียนตัวอักษรหนึ่งตัวตามด้วยจำนวนครั้งที่ซ้ำ เช่น aaabcc ย่อเป็น a3b1c2 น้องได้รับข้อความที่ย่อแล้ว ให้ขยายกลับเป็นข้อความเต็ม
ข้อมูลเข้า
ข้อความย่อหนึ่งบรรทัด ยาว 2 ถึง 10000 ตัว ประกอบด้วยกลุ่มต่อกันไปเรื่อยๆ แต่ละกลุ่มคือตัวพิมพ์เล็กภาษาอังกฤษหนึ่งตัว ตามด้วยจำนวนเต็มบวกที่ไม่มีเลข 0 นำหน้า กลุ่มที่อยู่ติดกันอาจเป็นตัวอักษรเดียวกันได้ ข้อความเต็มหลังขยายยาวไม่เกิน 100000 ตัว
ข้อมูลออก
ข้อความเต็มหนึ่งบรรทัด
a3b1c2aaabccx12y5xxxxxxxxxxxxyyyyyดูคำใบ้
ใช้ตัวชี้ตำแหน่ง i เดินไปทีละกลุ่ม อ่านตัวอักษรหนึ่งตัว แล้วอ่านตัวเลขที่ตามมาทุกหลักด้วย count = count * 10 + (c - '0') แบบในหน้า 6.1 จนเจอตัวที่ไม่ใช่ตัวเลข ระวังตัวเลขหลายหลักอย่าง 12 หรือ 100000 และตัวเลขที่มี 0 อยู่ข้างในอย่าง 10
ดูเฉลย
#include <stdio.h>
char code[10005];
int main()
{
scanf("%s", code);
int i = 0;
while (code[i] != '\0') {
char letter = code[i];
i++;
int count = 0;
while (code[i] >= '0' && code[i] <= '9') {
count = count * 10 + (code[i] - '0');
i++;
}
for (int k = 0; k < count; k++) {
printf("%c", letter);
}
}
printf("\n");
return 0;
}ข้อ 10 สลับอักษร
เกมทายคำในค่ายให้คำมาสองคำ แล้วถามว่าคำที่สองได้จากการสลับตำแหน่งตัวอักษรของคำแรกหรือไม่ เช่น listen สลับเป็น silent ได้ ตัวอักษรแต่ละตัวต้องใช้ครบทุกตัวและใช้ได้ตัวละครั้งเดียว
ข้อมูลเข้า
บรรทัดแรกคือคำแรก บรรทัดที่สองคือคำที่สอง ทั้งสองคำประกอบด้วยตัวพิมพ์เล็กภาษาอังกฤษเท่านั้น แต่ละคำยาว 1 ถึง 100000 ตัว สองคำอาจยาวไม่เท่ากัน
ข้อมูลออก
พิมพ์ YES ถ้าสลับตัวอักษรของคำแรกแล้วได้คำที่สองได้ ไม่อย่างนั้นพิมพ์ NO
listen
silentYEScat
cutNOดูคำใบ้
วิธีตรงไปตรงมาคือไล่ตัวอักษรของคำแรกทีละตัว แล้วค้นหาตัวเดียวกันในคำที่สองที่ยังไม่ถูกใช้ ซึ่งต้องค้นทั้งคำทุกครั้ง คำยาวหนึ่งแสนตัวจึงเป็นงานราว 1010 ก้าว ช้าเกินไปมาก ลองนับแทน ใช้อาเรย์ 26 ช่องนับตัวอักษรของแต่ละคำแบบในหน้า 6.5 แล้วเทียบอาเรย์ทั้งสองทีละช่อง
ดูเฉลย
#include <stdio.h>
char first[100005], second[100005];
int main()
{
scanf("%s %s", first, second);
int count[26] = {0};
for (int i = 0; first[i] != '\0'; i++) {
count[first[i] - 'a']++;
}
for (int i = 0; second[i] != '\0'; i++) {
count[second[i] - 'a']--;
}
int same = 1;
for (int i = 0; i < 26; i++) {
if (count[i] != 0) {
same = 0;
}
}
if (same) {
printf("YES\n");
} else {
printf("NO\n");
}
return 0;
}