1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <vector>
#include <sstream>
#include <numeric>
#include <limits>
#include <cctype>
#include <type_traits>
template<typename T = int>
typename std::enable_if_t< std::is_integral_v<T>, T>
getInp(const std::string& prm)
{
const auto notsp {[&]() {while (std::isspace(static_cast<unsigned char>(std::cin.peek())) && std::cin.peek() != '\n') std::cin.ignore(); return std::cin.peek() != '\n'; }};
T n {};
while ((std::cout << prm) && (!(std::cin >> n) || notsp())) {
std::cout << "Invalid input. Not a(n) " << typeid(T).name() << '\n';
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return n;
}
template<typename T = int>
typename std::enable_if_t< std::is_integral_v<T>, T>
getInp(const std::string& prm, T low, T upper = std::numeric_limits<T>::max())
{
T num {};
do {
num = getInp<T>(prm);
} while ((num < low || num > upper) && (std::cout << "Input not in range\n"));
return num;
}
constexpr const char* const subnames[] {"BM", "BI", "BC", "Math", "Sci", "Sejarah", "Geo"};
struct Student {
std::string id;
std::string name;
unsigned form {};
unsigned scores[std::size(subnames)] {};
};
using Students = std::vector<Student>;
using Reqs = std::vector<unsigned>;
std::istream& operator>>(std::istream& is, Student& s)
{
if (is) {
std::getline(is >> std::ws, s.id);
std::getline(is, s.name);
is >> s.form;
for (size_t i = 0; i < std::size(subnames); ++i)
is >> s.scores[i];
}
return is;
}
bool display(const Student& s, const Reqs& req)
{
if (!req.empty()) {
std::cout << "\nStudent ID: " << s.id << "\nStudent Name: " << s.name << "\nForm: " << s.form << '\n';
for (const auto& r : req)
std::cout << subnames[r] << ": " << s.scores[r] << '\n';
return true;
}
return false;
}
bool display(const Student& s)
{
Reqs req(std::size(subnames));
std::iota(req.begin(), req.end(), 0);
return display(s, req);
}
void display(const Students& stds)
{
for (const auto& s : stds)
display(s);
}
auto filter(const Students& stds)
{
const auto fm {getInp<unsigned>("Form: ")};
std::string subs;
std::cout << "Subject(s): ";
std::getline(std::cin, subs);
std::istringstream iss(subs);
Reqs req;
for (std::string sub; iss >> sub;)
if (const auto fidx {std::ranges::find(subnames, sub)}; fidx == std::end(subnames))
std::cout << "Invalid subject - " << sub << '\n';
else
req.push_back(static_cast<unsigned>(std::distance(subnames, fidx)));
size_t cnt {};
for (const auto& s : stds)
if (s.form == fm)
cnt += display(s, req);
std::cout << '\n';
return cnt;
}
auto search(const Students& stds)
{
std::string part;
size_t cnt {};
std::cout << "Enter partial name: ";
std::getline(std::cin, part);
for (const auto& s : stds)
if (!std::ranges::search(s.name, part).empty())
cnt += display(s);
std::cout << '\n';
return cnt;
}
int main()
{
std::ifstream ifs("students.txt");
if (!ifs)
return (std::cout << "Cannot open input file\n"), 1;
Students students;
unsigned choice {};
for (Student s; ifs >> s; students.emplace_back(s));
do {
std::cout << '\n' <<
"1. Filter by form/subject(s)\n" <<
"2. Search by partial name\n" <<
"3. Display all students\n" <<
"0. Exit\n\n";
switch (choice = getInp<unsigned>("Choice: ", 0, 3); choice) {
case 1:
std::cout << '\n' << filter(students) << " record(s) found.\n";
break;
case 2:
std::cout << '\n' << search(students) << " record(s) found.\n";
break;
case 3:
display(students);
break;
}
} while (choice);
}
|