15.6 แบบฝึกหัด
เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น
ข้อ 1 เรียงวันที่ใหม่
ใบสมัครค่ายให้น้องกรอกวันเกิดแบบ วัน/เดือน/ปี เช่น 05/03/2010 แต่ระบบของค่ายเรียงข้อมูลตามวันที่ได้ก็ต่อเมื่อเขียนแบบ ปี-เดือน-วัน คือ 2010-03-05 ให้แปลงวันเกิดทุกรายการให้เป็นรูปแบบใหม่ โดยเลข 0 ที่อยู่ข้างหน้าต้องอยู่ครบเหมือนเดิม
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)
อีก N บรรทัด บรรทัดละหนึ่งวันที่ในรูปแบบ DD/MM/YYYY ยาว 10 ตัวพอดี วันและเดือนเป็นเลขสองหลักเสมอ ปีเป็นเลขสี่หลักเสมอ ทุกวันที่เป็นวันที่ที่มีอยู่จริง
ข้อมูลออก
N บรรทัด บรรทัดที่ i คือวันที่ของบรรทัดที่ i ในรูปแบบ YYYY-MM-DD
3
05/03/2010
28/11/2009
14/02/20112010-03-05
2009-11-28
2011-02-14ดูคำใบ้
อ่านทั้งวันที่เป็น string ด้วย cin >> แล้วตัดสามส่วนด้วย substr แบบตัวอย่างวันที่ในหน้า 15.4 วันอยู่ช่อง 0 ยาว 2 ตัว เดือนอยู่ช่อง 3 ปีอยู่ช่อง 6 ยาว 4 ตัว ถ้าอ่านเป็นตัวเลขด้วย int เลข 0 ข้างหน้าจะหายไป
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string date;
cin >> date;
cout << date.substr(6, 4) << '-' << date.substr(3, 2) << '-' << date.substr(0, 2) << '\n';
}
return 0;
}ข้อ 2 จัดรูปแบบชื่อบนป้าย
ค่ายจะพิมพ์ป้ายชื่อให้นักเรียนทุกคน แต่ตอนกรอกใบสมัคร แต่ละคนพิมพ์ชื่อมาไม่เหมือนกัน บางคนพิมพ์ตัวพิมพ์ใหญ่ทั้งหมด บางคนพิมพ์ตัวพิมพ์เล็กทั้งหมด บางคนกดสลับไปมา ป้ายชื่อต้องเป็นรูปแบบเดียวกันทุกใบ คือชื่อที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่และที่เหลือเป็นตัวพิมพ์เล็ก ตามด้วยช่องว่างหนึ่งช่อง ตามด้วยอักษรตัวแรกของนามสกุลเป็นตัวพิมพ์ใหญ่และจุด เช่น sOMCHAI jaidee ต้องเป็น Somchai J.
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)
อีก N บรรทัด บรรทัดละหนึ่งคน มีชื่อและนามสกุลคั่นด้วยช่องว่าง ทั้งสองเป็นตัวอักษรภาษาอังกฤษล้วน ตัวพิมพ์ใหญ่หรือเล็กก็ได้ ยาวคำละ 1 ถึง 20 ตัว
ข้อมูลออก
N บรรทัด บรรทัดที่ i คือป้ายชื่อของคนที่ i
3
sOMCHAI jaidee
MALEE Srisuk
ploy WONGSomchai J.
Malee S.
Ploy W.ดูคำใบ้
อ่านชื่อกับนามสกุลเป็น string สองตัว เปลี่ยนชื่อทั้งคำเป็นตัวพิมพ์เล็กก่อนด้วย for (char &c : first) กับ tolower แล้วค่อยเปลี่ยน first[0] เป็นตัวพิมพ์ใหญ่ ส่วนนามสกุลใช้แค่ toupper(last[0]) ระวังว่า toupper คืนค่าเป็น int ถ้าส่งให้ cout ตรงๆ จะได้ตัวเลข ต้องเก็บใส่ตัวแปร char ก่อน หรือเขียน (char)toupper(last[0])
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string first, last;
cin >> first >> last;
for (char &c : first) {
c = tolower(c);
}
first[0] = toupper(first[0]);
char initial = toupper(last[0]);
cout << first << ' ' << initial << ".\n";
}
return 0;
}ข้อ 3 คนที่ได้คะแนนสูงสุด
หลังสอบย่อยวิชาคอมพิวเตอร์ ครูประจำวิชามีรายชื่อนักเรียน N คนพร้อมคะแนน ครูอยากรู้สองอย่าง คือคะแนนเฉลี่ยของห้อง และชื่อของคนที่ได้คะแนนสูงสุด ถ้ามีหลายคนได้คะแนนสูงสุดเท่ากัน ให้ตอบคนที่อยู่ก่อนในรายชื่อ
ข้อนี้คล้ายข้อใครได้รางวัลในบทที่ 11 และตั้งใจให้ฝึกย้ายโค้ดภาษา C มาเป็น C++ ให้เก็บชื่อด้วย string อ่านเขียนด้วย cin cout แทน char อาเรย์ strcpy และ printf
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)
อีก N บรรทัด บรรทัดละหนึ่งคน มีชื่อและคะแนนคั่นด้วยช่องว่าง ชื่อเป็นตัวอักษรภาษาอังกฤษ ยาว 1 ถึง 20 ตัว ไม่มีช่องว่าง คะแนนเป็นจำนวนเต็มตั้งแต่ 0 ถึง 100
ข้อมูลออก
บรรทัดแรกคือคะแนนเฉลี่ย เป็นทศนิยม 2 ตำแหน่ง บรรทัดที่สองคือชื่อของคนที่ได้คะแนนสูงสุด
3
Malee 72
Somchai 85
Ploy 6473.67
Somchai6
Anan 90
Nok 95
Kitti 95
Wan 88
Pim 70
Ton 8186.50
Nokดูคำใบ้
เก็บคะแนนสูงสุดที่เจอไว้ใน int และชื่อของคนนั้นไว้ใน string เจอคนที่คะแนนมากกว่าค่าเดิมเมื่อไรค่อยเปลี่ยน ใช้ = คัดลอกชื่อได้เลย ไม่ต้องใช้ strcpy ถ้าใช้ >= จะได้คนสุดท้ายที่ได้คะแนนเท่ากัน ค่าเฉลี่ยต้องหารแบบทศนิยม แล้วพิมพ์ด้วย fixed กับ setprecision(2) ตามหน้า 15.2
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
int total = 0;
int best_score = -1;
string best_name;
for (int i = 0; i < n; i++) {
string name;
int score;
cin >> name >> score;
total += score;
if (score > best_score) {
best_score = score;
best_name = name;
}
}
cout << fixed << setprecision(2);
cout << (double)total / n << '\n';
cout << best_name << '\n';
return 0;
}ข้อ 4 ตรวจรหัสผ่าน
เว็บส่งงานของโรงเรียนให้นักเรียนตั้งรหัสผ่านใหม่ รหัสผ่านต้องผ่านกฎสี่ข้อนี้ ระบบจะตรวจตามลำดับ และบอกเฉพาะข้อแรกที่ไม่ผ่าน
- ยาวอย่างน้อย 8 ตัว ถ้าไม่ผ่านให้ตอบ
TOO SHORT - มีตัวพิมพ์ใหญ่ A ถึง Z อย่างน้อยหนึ่งตัว ถ้าไม่ผ่านให้ตอบ
NO UPPERCASE - มีตัวพิมพ์เล็ก a ถึง z อย่างน้อยหนึ่งตัว ถ้าไม่ผ่านให้ตอบ
NO LOWERCASE - มีตัวเลข 0 ถึง 9 อย่างน้อยหนึ่งตัว ถ้าไม่ผ่านให้ตอบ
NO DIGIT
ถ้าผ่านครบทั้งสี่ข้อให้ตอบ OK ให้ตรวจรหัสผ่านที่นักเรียนส่งมาทั้งหมด
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)
อีก N บรรทัด บรรทัดละหนึ่งรหัสผ่าน ยาว 1 ถึง 50 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข และเครื่องหมาย เช่น ! @ # $ % _ - . ไม่มีช่องว่าง
ข้อมูลออก
N บรรทัด บรรทัดที่ i คือผลการตรวจรหัสผ่านที่ i
5
abc
school2026
School2026
SCHOOL2026
SchoolDaysTOO SHORT
NO UPPERCASE
OK
NO LOWERCASE
NO DIGITดูคำใบ้
ใช้ตัวแปร bool สามตัว เช่น has_upper has_lower has_digit ตั้งเป็น false ก่อน แล้วเดินทีละตัวด้วย for (char c : password) เจอตัวแบบไหนก็ตั้งตัวแปรนั้นเป็น true จากนั้นใช้ if else if ไล่ตามลำดับกฎ ความยาวต้องตรวจก่อนข้ออื่นเสมอ แม้รหัสสั้นจะไม่มีตัวพิมพ์ใหญ่ด้วยก็ตอบแค่ TOO SHORT
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string password;
cin >> password;
bool has_upper = false, has_lower = false, has_digit = false;
for (char c : password) {
if (c >= 'A' && c <= 'Z') {
has_upper = true;
} else if (c >= 'a' && c <= 'z') {
has_lower = true;
} else if (c >= '0' && c <= '9') {
has_digit = true;
}
}
if ((int)password.size() < 8) {
cout << "TOO SHORT\n";
} else if (!has_upper) {
cout << "NO UPPERCASE\n";
} else if (!has_lower) {
cout << "NO LOWERCASE\n";
} else if (!has_digit) {
cout << "NO DIGIT\n";
} else {
cout << "OK\n";
}
}
return 0;
}ข้อ 5 อีเมลโรงเรียน
ครูเปิดฟอร์มให้นักเรียนส่งอีเมลมาเพื่อเพิ่มเข้ากลุ่มของห้อง แต่กลุ่มนี้รับเฉพาะอีเมลของโรงเรียน ซึ่งลงท้ายด้วยโดเมน D เช่น school.ac.th นักเรียนบางคนพิมพ์อีเมลส่วนตัวมา บางคนพิมพ์ผิด ครูอยากได้รายชื่อผู้ใช้ของอีเมลโรงเรียนที่ถูกต้องเท่านั้น
ข้อความหนึ่งรายการถือเป็นอีเมลโรงเรียนที่ถูกต้องเมื่อครบทุกข้อต่อไปนี้
- มีเครื่องหมาย
@หนึ่งตัวพอดี - ส่วนหน้า
@ซึ่งเรียกว่าชื่อผู้ใช้ ยาวอย่างน้อยหนึ่งตัว - ส่วนหลัง
@เหมือนกับ D ทุกตัวอักษร ตัวพิมพ์ใหญ่กับตัวพิมพ์เล็กถือว่าต่างกัน
เช่น ถ้า D คือ school.ac.th แล้ว malee@school.ac.th ถูกต้อง แต่ malee@myschool.ac.th malee@school.ac.th.com และ malee@School.ac.th ไม่ถูกต้อง
ข้อมูลเข้า
บรรทัดแรกคือโดเมน D ยาว 1 ถึง 30 ตัว ไม่มีเครื่องหมาย @
บรรทัดที่สองมีจำนวนเต็ม N (1 ≤ N ≤ 1000)
อีก N บรรทัด บรรทัดละหนึ่งรายการ ยาว 1 ถึง 60 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข และเครื่องหมาย . _ - @ ไม่มีช่องว่าง
ข้อมูลออก
ชื่อผู้ใช้ของทุกรายการที่เป็นอีเมลโรงเรียนที่ถูกต้อง บรรทัดละหนึ่งชื่อ เรียงตามลำดับในข้อมูลเข้า แล้วบรรทัดสุดท้ายคือจำนวนรายการที่ถูกต้อง ถ้าไม่มีเลยให้พิมพ์แค่ 0
school.ac.th
5
malee@school.ac.th
somchai@gmail.com
ploy.w@school.ac.th
nok@myschool.ac.th
ananmalee
ploy.w
2school.ac.th
2
boy@School.ac.th
kitti@school.ac.th.com0ดูคำใบ้
หาตำแหน่งของ @ ด้วย find เก็บใน size_t แล้วเทียบกับ string::npos ตามหน้า 15.4 ถ้าเจอ ให้หาต่อด้วย find('@', at + 1) ว่ามีตัวที่สองไหม จากนั้นตัดสองส่วนด้วย substr แล้วเทียบส่วนหลังกับ D ด้วย == ทั้งคำ อย่าใช้ find(D) หาว่า D อยู่ในข้อความไหม เพราะ @myschool.ac.th ก็มี school.ac.th อยู่ข้างใน
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string domain;
int n;
cin >> domain >> n;
int valid = 0;
for (int i = 0; i < n; i++) {
string email;
cin >> email;
size_t at = email.find('@');
if (at == string::npos || at == 0) {
continue;
}
if (email.find('@', at + 1) != string::npos) {
continue;
}
if (email.substr(at + 1) == domain) {
cout << email.substr(0, at) << '\n';
valid++;
}
}
cout << valid << '\n';
return 0;
}ข้อ 6 ยอดเงินสะสม
ร้านค้าสหกรณ์ของโรงเรียนจดยอดเงินเข้าออกทุกรายการตลอดปีการศึกษา รายการที่ i เป็นจำนวนเต็ม ai บาท ถ้าเป็นบวกคือเงินเข้า ถ้าเป็นลบคือเงินออก ฝ่ายบัญชีอยากเห็นยอดเงินสะสมหลังแต่ละรายการ คือหลังรายการที่ k ยอดสะสมเท่ากับ a1 + a2 + ... + ak และอยากรู้ด้วยว่าจนถึงรายการนั้น ยอดสะสมเคยต่ำที่สุดเท่าไร เพื่อดูว่าร้านเคยติดลบหนักแค่ไหน
ข้อนี้ข้อมูลเข้ามีได้ถึงหนึ่งล้านรายการ และต้องพิมพ์ออกหนึ่งล้านบรรทัด ภายในเวลา 1 วินาที
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000000)
บรรทัดที่สองมีจำนวนเต็ม a1 a2 ... aN คั่นด้วยช่องว่าง (-1000000000 ≤ ai ≤ 1000000000)
ข้อมูลออก
N บรรทัด บรรทัดที่ k มีจำนวนเต็มสองตัวคั่นด้วยช่องว่าง ตัวแรกคือยอดเงินสะสมหลังรายการที่ k ตัวที่สองคือยอดสะสมที่ต่ำที่สุดในบรรดายอดสะสมหลังรายการที่ 1 ถึงรายการที่ k
5
500 -200 1000 -1300 50500 500
300 300
1300 300
0 0
50 0ดูคำใบ้
บวกสะสมไปแล้วพิมพ์ทุกรอบ ไม่ต้องเก็บอาเรย์ เก็บยอดที่ต่ำที่สุดไว้อีกตัวแปรหนึ่ง แล้วเทียบกับยอดใหม่ทุกรอบ ค่าเริ่มต้นของมันต้องเป็นยอดหลังรายการแรก ถ้าเริ่มที่ 0 ร้านที่ยอดเป็นบวกตลอดจะได้ 0 ซึ่งไม่เคยเป็นยอดสะสมเลย ยอดสะสมได้ถึง ±106 × 109 = ±1015 ทั้งสองตัวต้องเป็น long long ส่วนที่ยากคือเวลา หน้า 15.3 วัดไว้ว่า cin cout แบบปกติกับข้อมูลขนาดนี้ใช้กว่า 3 วินาที ต้องใส่ ios::sync_with_stdio(false); กับ cin.tie(nullptr); ไว้ต้น main และขึ้นบรรทัดด้วย '\n' ไม่ใช่ endl
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
long long total = 0;
long long lowest = 0;
for (int i = 0; i < n; i++) {
int amount;
cin >> amount;
total += amount;
if (i == 0 || total < lowest) {
lowest = total;
}
cout << total << ' ' << lowest << '\n';
}
return 0;
}ข้อ 7 กันสปอยล์
ชมรมภาพยนตร์มีกลุ่มแชตที่ห้ามสปอยล์ ประธานชมรมรวบรวมคำต้องห้ามไว้ K คำ เช่นชื่อตัวร้ายหรือชื่อฉากสำคัญ ก่อนข้อความจะขึ้นในกลุ่ม ระบบจะเปลี่ยนทุกคำที่ตรงกับคำต้องห้ามเป็นเครื่องหมาย * ที่ยาวเท่าคำนั้น
คำในข้อความคือกลุ่มตัวอักษรที่ติดกันโดยไม่มีช่องว่างคั่น ระบบเปลี่ยนเฉพาะคำที่ตรงกับคำต้องห้ามทั้งคำ เท่านั้น ถ้าคำต้องห้ามเป็นแค่ส่วนหนึ่งของคำที่ยาวกว่าจะไม่ถูกเปลี่ยน เช่น ถ้า cat เป็นคำต้องห้าม คำว่า catch ยังอยู่เหมือนเดิม ช่องว่างในข้อความต้องอยู่ครบทุกช่องเหมือนเดิม
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม K (1 ≤ K ≤ 100)
บรรทัดที่สองมีคำต้องห้าม K คำ คั่นด้วยช่องว่าง แต่ละคำเป็นตัวพิมพ์เล็กภาษาอังกฤษ ยาว 1 ถึง 20 ตัว อาจมีคำซ้ำกัน
บรรทัดที่สามคือข้อความ ยาว 1 ถึง 100000 ตัว ประกอบด้วยตัวพิมพ์เล็กภาษาอังกฤษและช่องว่างเท่านั้น มีตัวอักษรอย่างน้อยหนึ่งตัว ระหว่างคำและหน้าข้อความอาจมีช่องว่างหลายช่อง แต่ท้ายข้อความไม่มีช่องว่าง
ข้อมูลออก
ข้อความหลังเปลี่ยนคำต้องห้ามแล้ว หนึ่งบรรทัด
2
vader father
darth vader is luke fatherdarth ***** is luke ******1
cat
the cat can catch a catthe *** can catch a ***ดูคำใบ้
ข้อความมีช่องว่าง ต้องรับด้วย getline และเพราะบรรทัดก่อนหน้าอ่านด้วย cin >> ต้องมี cin.ignore(1000000, '\n'); ก่อน ไม่อย่างนั้นจะได้ข้อความว่าง เก็บคำต้องห้ามไว้ในอาเรย์ string banned[100] แล้วเดินในข้อความด้วย i เจอตัวอักษรที่ช่อง i ให้เดินต่อด้วย j จนสุดคำ ตัดคำออกมาด้วย substr(i, j - i) ถ้าเท่ากับคำต้องห้ามสักคำ ให้เปลี่ยนช่อง i ถึง j - 1 เป็น '*' แล้วไปต่อที่ j อย่าใช้ find หาคำต้องห้ามในข้อความตรงๆ เพราะจะไปเจอข้างในคำที่ยาวกว่า
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
string banned[100];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int k;
cin >> k;
for (int i = 0; i < k; i++) {
cin >> banned[i];
}
cin.ignore(1000000, '\n');
string text;
getline(cin, text);
int n = text.size();
int i = 0;
while (i < n) {
if (text[i] == ' ') {
i++;
continue;
}
int j = i;
while (j < n && text[j] != ' ') {
j++;
}
string word = text.substr(i, j - i);
bool hide = false;
for (int b = 0; b < k; b++) {
if (word == banned[b]) {
hide = true;
}
}
if (hide) {
for (int p = i; p < j; p++) {
text[p] = '*';
}
}
i = j;
}
cout << text << '\n';
return 0;
}ข้อ 8 เลือกตั้งประธานนักเรียน
โรงเรียนเลือกตั้งประธานนักเรียน มีผู้สมัคร K คน นักเรียนทุกคนเขียนชื่อผู้สมัครที่ตัวเองเลือกลงบัตรหนึ่งใบ บัตรถูกพิมพ์เข้าระบบตามที่เขียนมา บางใบเขียนตัวพิมพ์ใหญ่ บางใบตัวพิมพ์เล็ก บางใบปนกัน ซึ่งถือเป็นชื่อเดียวกันหมด เช่น Malee MALEE และ malee คือคะแนนของ malee ส่วนบัตรที่ชื่อไม่ตรงกับผู้สมัครคนไหนเลย แม้จะสะกดผิดไปตัวเดียว ถือเป็นบัตรเสีย
ให้นับคะแนนของผู้สมัครแต่ละคน นับบัตรเสีย และประกาศผู้ชนะ ผู้ชนะคือคนที่ได้คะแนนมากที่สุดเพียงคนเดียว ถ้ามีหลายคนได้คะแนนมากที่สุดเท่ากัน ให้ประกาศว่าเสมอ
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม K (1 ≤ K ≤ 10)
บรรทัดที่สองมีชื่อผู้สมัคร K ชื่อ คั่นด้วยช่องว่าง แต่ละชื่อเป็นตัวพิมพ์เล็กภาษาอังกฤษ ยาว 1 ถึง 15 ตัว และไม่ซ้ำกัน
บรรทัดที่สามมีจำนวนเต็ม N (1 ≤ N ≤ 1000000) คือจำนวนบัตร
อีก N บรรทัด บรรทัดละหนึ่งบัตร เป็นตัวอักษรภาษาอังกฤษล้วน ตัวพิมพ์ใหญ่หรือเล็กก็ได้ ยาว 1 ถึง 15 ตัว
ข้อมูลออก
K บรรทัดแรก บรรทัดที่ i มีชื่อผู้สมัครคนที่ i ตามลำดับในข้อมูลเข้า ตามด้วยช่องว่างและคะแนนของคนนั้น
บรรทัดถัดมาคือคำว่า invalid ตามด้วยช่องว่างและจำนวนบัตรเสีย
บรรทัดสุดท้ายคือชื่อผู้ชนะ ถ้าคะแนนสูงสุดเสมอกันตั้งแต่สองคนขึ้นไป ให้พิมพ์ TIE
3
malee somchai ploy
7
Malee
SOMCHAI
malee
plooy
Ploy
mALEE
somchaimalee 3
somchai 2
ploy 1
invalid 1
malee2
anan nok
5
Anan
NOK
anann
nok
ANANanan 2
nok 2
invalid 1
TIEดูคำใบ้
เก็บชื่อผู้สมัครในอาเรย์ string name[10] และคะแนนใน int votes[10] เขียนฟังก์ชัน void make_lower(string &word) ที่รับ reference แล้วเปลี่ยนทุกตัวเป็นตัวพิมพ์เล็กด้วย for (char &c : word) พออ่านบัตรมาแล้วเรียกฟังก์ชันนี้ก่อน แล้วค่อยเทียบกับชื่อผู้สมัครทีละคนด้วย == ไม่ตรงใครเลยคือบัตรเสีย ตอนหาผู้ชนะ ให้หาคะแนนสูงสุดก่อน แล้วนับว่ามีกี่คนที่ได้คะแนนเท่านั้น บัตรมีได้ถึงล้านใบ อย่าลืมสองบรรทัดจากหน้า 15.3
ดูเฉลย
#include <bits/stdc++.h>
using namespace std;
string name[10];
int votes[10];
void make_lower(string &word)
{
for (char &c : word) {
c = tolower(c);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int k;
cin >> k;
for (int i = 0; i < k; i++) {
cin >> name[i];
}
int n;
cin >> n;
int invalid = 0;
for (int b = 0; b < n; b++) {
string ballot;
cin >> ballot;
make_lower(ballot);
bool counted = false;
for (int i = 0; i < k; i++) {
if (ballot == name[i]) {
votes[i]++;
counted = true;
}
}
if (!counted) {
invalid++;
}
}
int best = 0;
for (int i = 0; i < k; i++) {
cout << name[i] << ' ' << votes[i] << '\n';
if (votes[i] > votes[best]) {
best = i;
}
}
cout << "invalid " << invalid << '\n';
int winners = 0;
for (int i = 0; i < k; i++) {
if (votes[i] == votes[best]) {
winners++;
}
}
if (winners == 1) {
cout << name[best] << '\n';
} else {
cout << "TIE\n";
}
return 0;
}