20-bo‘lim
Yakuniy loyiha
Yigirma bo'lim bilimini bitta ishlaydigan dasturda birlashtirish - jurnal tahlilchisi.
Ushbu bo‘lim mundarijasi
Bu bo'limda haqiqiy dastur quramiz: server jurnalini tahlil qiluvchi vosita. U kirish faylini o'qiydi, qatorlarni ajratadi, statistika to'playdi va hisobot chiqaradi.
Har bir qadamda oldingi bo'limlarning qaysi biri ishlatilganini ko'rsatamiz.
Loyiha tuzilishi #
#include <print>
#include <string>
#include <string_view>
#include <vector>
#include <map>
#include <optional>
#include <expected>
#include <memory>
#include <algorithm>
#include <ranges>
#include <numeric>
#include <chrono>
#include <fstream>
#include <filesystem>
#include <stdexcept>
#include <charconv>
#include <concepts>
int main()
{
std::println("JURNAL TAHLILCHISI - qismlar:");
std::println("");
std::println("{:<22} {:<28} {}", "QISM", "VAZIFA", "BO'LIM");
std::println("{}", std::string(72, '-'));
std::println("{:<22} {:<28} {}", "Qator", "Bitta jurnal yozuvi", "11 sinflar");
std::println("{:<22} {:<28} {}", "QatorXatosi", "Ajratish xatosi sababi", "16 xatolar");
std::println("{:<22} {:<28} {}", "ajrat()", "Matndan Qator yasash", "6 satrlar");
std::println("{:<22} {:<28} {}", "Statistika", "To'plangan hisob", "7 konteynerlar");
std::println("{:<22} {:<28} {}", "Filtr", "Interfeys (abstrakt)", "14 polimorfizm");
std::println("{:<22} {:<28} {}", "Hisobot", "Chiqarish formati", "13 operatorlar");
std::println("{:<22} {:<28} {}", "Tahlilchi", "Hammasini birlashtiradi", "9 RAII");
std::println("");
std::println("Ishlatiladigan tamoyillar:");
std::println(" - Qiymat semantikasi, ko'chirish (12-bo'lim)");
std::println(" - std::expected bilan xato uzatish (16-bo'lim)");
std::println(" - unique_ptr bilan polimorf filtrlar (10-bo'lim)");
std::println(" - ranges bilan ma'lumot oqimi (8-bo'lim)");
std::println(" - Konsept bilan cheklangan shablon (15-bo'lim)");
return 0;
}
JURNAL TAHLILCHISI - qismlar:
QISM VAZIFA BO'LIM
------------------------------------------------------------------------
Qator Bitta jurnal yozuvi 11 sinflar
QatorXatosi Ajratish xatosi sababi 16 xatolar
ajrat() Matndan Qator yasash 6 satrlar
Statistika To'plangan hisob 7 konteynerlar
Filtr Interfeys (abstrakt) 14 polimorfizm
Hisobot Chiqarish formati 13 operatorlar
Tahlilchi Hammasini birlashtiradi 9 RAII
Ishlatiladigan tamoyillar:
- Qiymat semantikasi, ko'chirish (12-bo'lim)
- std::expected bilan xato uzatish (16-bo'lim)
- unique_ptr bilan polimorf filtrlar (10-bo'lim)
- ranges bilan ma'lumot oqimi (8-bo'lim)
- Konsept bilan cheklangan shablon (15-bo'lim)
1-qadam: ma'lumot turi va ajratuvchi #
enum class Daraja { Nosozlik, Ogohlantirish, Xato, Halokat };
std::string darajaMatni(Daraja d)
{
switch (d) {
case Daraja::Nosozlik: return "NOSOZLIK";
case Daraja::Ogohlantirish: return "OGOHLANTIRISH";
case Daraja::Xato: return "XATO";
case Daraja::Halokat: return "HALOKAT";
}
return "?";
}
std::optional<Daraja> darajaOqi(std::string_view s)
{
if (s == "INFO") return Daraja::Nosozlik;
if (s == "WARN") return Daraja::Ogohlantirish;
if (s == "ERROR") return Daraja::Xato;
if (s == "FATAL") return Daraja::Halokat;
return std::nullopt;
}
// Bitta jurnal yozuvi - qiymat turi, nol qoidasi (12-bo'lim)
struct Qator
{
std::string sana;
Daraja daraja{};
std::string manba;
std::string xabar;
int davomiylik{}; // millisekundda
auto operator<=>(const Qator&) const = default;
};
int main()
{
Qator q{"2024-09-01", Daraja::Xato, "auth", "parol noto'g'ri", 120};
std::println("sana: {}", q.sana);
std::println("daraja: {}", darajaMatni(q.daraja));
std::println("manba: {}", q.manba);
std::println("xabar: {}", q.xabar);
std::println("davomiylik: {} ms", q.davomiylik);
std::println("");
Qator nusxa = q;
std::println("nusxa tengmi: {}", nusxa == q);
nusxa.davomiylik = 200;
std::println("o'zgartirgandan keyin tengmi: {}", nusxa == q);
std::println("asl o'zgardimi: {} ms", q.davomiylik);
std::println("");
std::println("Daraja o'qish:");
for (std::string_view s : {"INFO", "ERROR", "TRACE"}) {
auto d = darajaOqi(s);
std::println(" {:<6} -> {}", s, d ? darajaMatni(*d) : "noma'lum");
}
return 0;
}
sana: 2024-09-01
daraja: XATO
manba: auth
xabar: parol noto'g'ri
davomiylik: 120 ms
nusxa tengmi: true
o'zgartirgandan keyin tengmi: false
asl o'zgardimi: 120 ms
Daraja o'qish:
INFO -> NOSOZLIK
ERROR -> XATO
TRACE -> noma'lum
2-qadam: ajratish va xatolar #
enum class Daraja { Nosozlik, Ogohlantirish, Xato, Halokat };
std::string darajaMatni(Daraja d)
{
switch (d) {
case Daraja::Nosozlik: return "NOSOZLIK";
case Daraja::Ogohlantirish: return "OGOHLANTIRISH";
case Daraja::Xato: return "XATO";
case Daraja::Halokat: return "HALOKAT";
}
return "?";
}
std::optional<Daraja> darajaOqi(std::string_view s)
{
if (s == "INFO") return Daraja::Nosozlik;
if (s == "WARN") return Daraja::Ogohlantirish;
if (s == "ERROR") return Daraja::Xato;
if (s == "FATAL") return Daraja::Halokat;
return std::nullopt;
}
struct Qator
{
std::string sana;
Daraja daraja{};
std::string manba;
std::string xabar;
int davomiylik{};
};
// Xato SABABI ham kerak - shuning uchun expected (16-bo'lim)
enum class QatorXatosi { BoshQator, KamMaydon, NomalumDaraja, YaroqsizVaqt };
std::string xatoMatni(QatorXatosi x)
{
switch (x) {
case QatorXatosi::BoshQator: return "qator bo'sh";
case QatorXatosi::KamMaydon: return "maydonlar yetarli emas";
case QatorXatosi::NomalumDaraja: return "daraja tanilmadi";
case QatorXatosi::YaroqsizVaqt: return "davomiylik son emas";
}
return "?";
}
std::vector<std::string_view> bolaklar(std::string_view s, char ajratgich, int soni)
{
std::vector<std::string_view> natija;
while (soni > 1) {
auto joy = s.find(ajratgich);
if (joy == std::string_view::npos) break;
natija.push_back(s.substr(0, joy));
s.remove_prefix(joy + 1);
--soni;
}
natija.push_back(s);
return natija;
}
std::expected<Qator, QatorXatosi> ajrat(std::string_view qator)
{
if (qator.empty()) return std::unexpected{QatorXatosi::BoshQator};
auto b = bolaklar(qator, '|', 5);
if (b.size() < 5) return std::unexpected{QatorXatosi::KamMaydon};
auto daraja = darajaOqi(b[1]);
if (!daraja) return std::unexpected{QatorXatosi::NomalumDaraja};
int ms{};
auto [oxir, xato] = std::from_chars(b[4].data(), b[4].data() + b[4].size(), ms);
if (xato != std::errc{}) return std::unexpected{QatorXatosi::YaroqsizVaqt};
return Qator{std::string{b[0]}, *daraja, std::string{b[2]},
std::string{b[3]}, ms};
}
int main()
{
std::vector<std::string> sinovlar = {
"2024-09-01|INFO|auth|foydalanuvchi kirdi|42",
"2024-09-01|ERROR|db|ulanish uzildi|1500",
"",
"2024-09-01|TRACE|api|nomalum daraja|10",
"2024-09-01|WARN|api",
"2024-09-01|INFO|api|so'rov|tez",
};
for (const auto& s : sinovlar) {
auto n = ajrat(s);
std::string qisqa = s.size() > 34 ? s.substr(0, 31) + "..." : s;
if (n) {
std::println(" {:<36} OK {} / {} ms",
std::format("'{}'", qisqa), darajaMatni(n->daraja),
n->davomiylik);
} else {
std::println(" {:<36} XATO {}",
std::format("'{}'", qisqa), xatoMatni(n.error()));
}
}
return 0;
}
'2024-09-01|INFO|auth|foydalanuv...' OK NOSOZLIK / 42 ms
'2024-09-01|ERROR|db|ulanish uzi...' OK XATO / 1500 ms
'' XATO qator bo'sh
'2024-09-01|TRACE|api|nomalum da...' XATO daraja tanilmadi
'2024-09-01|WARN|api' XATO maydonlar yetarli emas
'2024-09-01|INFO|api|so'rov|tez' XATO davomiylik son emas
string_view bilan ajratish - nusxasizbolaklar() funksiyasi std::string_view qaytaradi -
ya'ni hech qanday satr nusxalanmaydi. U faqat asl
matnning bo'laklariga ishora qiladi.
Nusxa faqat oxirida, Qator qurilayotganda olinadi:
return Qator{std::string{b[0]}, ...};
Bu 6-bo'limdagi qoidaning amaliy qo'llanishi: o'qish
uchun string_view, saqlash uchun string.
Diqqat: string_view egalik olmaydi. Agar asl satr
yo'q qilinsa yoki o'zgartirilsa - string_view
osilgan bo'lib qoladi (19-bo'lim).
Shuning uchun ajrat() string_view qaytarmaydi -
u Qator ni qiymat sifatida qaytaradi.
3-qadam: filtrlar #
enum class Daraja { Nosozlik, Ogohlantirish, Xato, Halokat };
struct Qator
{
std::string sana;
Daraja daraja{};
std::string manba;
std::string xabar;
int davomiylik{};
};
// Ish paytida tanlanadigan xatti-harakat -> virtual (14-bo'lim)
class Filtr
{
public:
virtual ~Filtr() = default;
virtual bool mos(const Qator& q) const = 0;
virtual std::string tavsif() const = 0;
};
class DarajaFiltri : public Filtr
{
Daraja eng_kam_;
public:
explicit DarajaFiltri(Daraja d) : eng_kam_(d) {}
bool mos(const Qator& q) const override { return q.daraja >= eng_kam_; }
std::string tavsif() const override { return "daraja bo'yicha"; }
};
class ManbaFiltri : public Filtr
{
std::string manba_;
public:
explicit ManbaFiltri(std::string m) : manba_(std::move(m)) {}
bool mos(const Qator& q) const override { return q.manba == manba_; }
std::string tavsif() const override { return "manba = " + manba_; }
};
class SekinFiltri : public Filtr
{
int chegara_;
public:
explicit SekinFiltri(int ms) : chegara_(ms) {}
bool mos(const Qator& q) const override { return q.davomiylik >= chegara_; }
std::string tavsif() const override
{
return std::format("davomiylik >= {} ms", chegara_);
}
};
// Kompozit - filtrlarni birlashtiradi
class HammaFiltr : public Filtr
{
std::vector<std::unique_ptr<Filtr>> ichki_;
public:
void qosh(std::unique_ptr<Filtr> f) { ichki_.push_back(std::move(f)); }
bool mos(const Qator& q) const override
{
return std::ranges::all_of(ichki_,
[&q](const auto& f) { return f->mos(q); });
}
std::string tavsif() const override
{
std::string s = "hammasi(";
for (std::size_t i = 0; i < ichki_.size(); ++i) {
if (i) s += ", ";
s += ichki_[i]->tavsif();
}
return s + ")";
}
};
int main()
{
std::vector<Qator> jurnal = {
{"2024-09-01", Daraja::Nosozlik, "auth", "kirish", 42},
{"2024-09-01", Daraja::Xato, "db", "ulanish", 1500},
{"2024-09-01", Daraja::Ogohlantirish, "db", "sekin", 900},
{"2024-09-01", Daraja::Halokat, "db", "to'xtadi", 3000},
{"2024-09-01", Daraja::Xato, "api", "404", 15},
};
std::vector<std::unique_ptr<Filtr>> filtrlar;
filtrlar.push_back(std::make_unique<DarajaFiltri>(Daraja::Xato));
filtrlar.push_back(std::make_unique<ManbaFiltri>("db"));
filtrlar.push_back(std::make_unique<SekinFiltri>(1000));
auto birlashgan = std::make_unique<HammaFiltr>();
birlashgan->qosh(std::make_unique<DarajaFiltri>(Daraja::Xato));
birlashgan->qosh(std::make_unique<ManbaFiltri>("db"));
filtrlar.push_back(std::move(birlashgan));
for (const auto& f : filtrlar) {
auto mos = jurnal | std::views::filter(
[&f](const Qator& q) { return f->mos(q); });
auto soni = std::ranges::distance(mos);
std::println("{:<38} {} ta qator", f->tavsif(), soni);
}
return 0;
}
daraja bo'yicha 3 ta qator
manba = db 3 ta qator
davomiylik >= 1000 ms 2 ta qator
hammasi(daraja bo'yicha, manba = db) 2 ta qator
4-qadam: statistika #
enum class Daraja { Nosozlik, Ogohlantirish, Xato, Halokat };
std::string darajaMatni(Daraja d)
{
switch (d) {
case Daraja::Nosozlik: return "NOSOZLIK";
case Daraja::Ogohlantirish: return "OGOHLANTIRISH";
case Daraja::Xato: return "XATO";
case Daraja::Halokat: return "HALOKAT";
}
return "?";
}
struct Qator
{
std::string sana;
Daraja daraja{};
std::string manba;
std::string xabar;
int davomiylik{};
};
class Statistika
{
std::map<Daraja, int> daraja_;
std::map<std::string, int> manba_;
std::vector<int> davomiyliklar_;
public:
void qosh(const Qator& q)
{
++daraja_[q.daraja];
++manba_[q.manba];
davomiyliklar_.push_back(q.davomiylik);
}
std::size_t soni() const { return davomiyliklar_.size(); }
double ortacha() const
{
if (davomiyliklar_.empty()) return 0.0;
long long jami = std::accumulate(davomiyliklar_.begin(),
davomiyliklar_.end(), 0LL);
return static_cast<double>(jami) /
static_cast<double>(davomiyliklar_.size());
}
int median() const
{
if (davomiyliklar_.empty()) return 0;
auto nusxa = davomiyliklar_;
std::ranges::sort(nusxa);
return nusxa[nusxa.size() / 2];
}
int eng() const
{
if (davomiyliklar_.empty()) return 0;
return *std::ranges::max_element(davomiyliklar_);
}
const std::map<Daraja, int>& darajalar() const { return daraja_; }
const std::map<std::string, int>& manbalar() const { return manba_; }
};
int main()
{
std::vector<Qator> jurnal = {
{"2024-09-01", Daraja::Nosozlik, "auth", "kirish", 42},
{"2024-09-01", Daraja::Nosozlik, "auth", "chiqish", 18},
{"2024-09-01", Daraja::Xato, "db", "ulanish", 1500},
{"2024-09-01", Daraja::Ogohlantirish, "db", "sekin", 900},
{"2024-09-01", Daraja::Halokat, "db", "to'xtadi", 3000},
{"2024-09-01", Daraja::Xato, "api", "404", 15},
{"2024-09-01", Daraja::Nosozlik, "api", "so'rov", 60},
};
Statistika s;
for (const auto& q : jurnal) s.qosh(q);
std::println("Jami qatorlar: {}", s.soni());
std::println("");
std::println("Darajalar bo'yicha:");
for (const auto& [d, n] : s.darajalar()) {
std::string ustun(static_cast<std::size_t>(n) * 3, '#');
std::println(" {:<14} {:>2} {}", darajaMatni(d), n, ustun);
}
std::println("");
std::println("Manbalar bo'yicha:");
for (const auto& [m, n] : s.manbalar()) {
std::println(" {:<6} {:>2}", m, n);
}
std::println("");
std::println("Davomiylik:");
std::println(" o'rtacha: {:.2f} ms", s.ortacha());
std::println(" median: {} ms", s.median());
std::println(" eng uzun: {} ms", s.eng());
return 0;
}
Jami qatorlar: 7
Darajalar bo'yicha:
NOSOZLIK 3 #########
OGOHLANTIRISH 1 ###
XATO 2 ######
HALOKAT 1 ###
Manbalar bo'yicha:
api 2
auth 2
db 3
Davomiylik:
o'rtacha: 790.71 ms
median: 60 ms
eng uzun: 3000 ms
Chiqishga qarang: o'rtacha va median orasida katta farq bor.
Sabab - chetdagi qiymatlar. Bitta 3000 ms lik yozuv o'rtachani yuqoriga tortadi, median esa o'zgarmaydi.
Ishlash statistikasida odatda foizli qiymatlar ishlatiladi:
| Ko'rsatkich | Nima aytadi |
|---|---|
| O'rtacha | Chetdagilarga sezgir - chalg'ituvchi |
| Median (p50) | Odatiy foydalanuvchi nima ko'radi |
| p95 | Sekin 5% qanchalik sekin |
| p99 | Eng yomon holatlar |
"O'rtacha javob vaqti 200 ms" degan hisobot ko'pincha yashiradi: foydalanuvchilarning 5% i 3 soniya kutgan bo'lishi mumkin.
Median hisoblashda diqqat: bizning median() juft
sonli to'plamda ikki o'rta qiymatning kattarog'ini
oladi. Qat'iy ta'rif bo'yicha ularning o'rtachasini
olish kerak - lekin ishlash ko'rsatkichlari uchun bu
farq ahamiyatsiz.
5-qadam: to'liq dastur #
namespace fs = std::filesystem;
enum class Daraja { Nosozlik, Ogohlantirish, Xato, Halokat };
std::string darajaMatni(Daraja d)
{
switch (d) {
case Daraja::Nosozlik: return "NOSOZLIK";
case Daraja::Ogohlantirish: return "OGOHLANTIRISH";
case Daraja::Xato: return "XATO";
case Daraja::Halokat: return "HALOKAT";
}
return "?";
}
std::optional<Daraja> darajaOqi(std::string_view s)
{
if (s == "INFO") return Daraja::Nosozlik;
if (s == "WARN") return Daraja::Ogohlantirish;
if (s == "ERROR") return Daraja::Xato;
if (s == "FATAL") return Daraja::Halokat;
return std::nullopt;
}
struct Qator
{
std::string sana;
Daraja daraja{};
std::string manba;
std::string xabar;
int davomiylik{};
};
enum class QatorXatosi { BoshQator, KamMaydon, NomalumDaraja, YaroqsizVaqt };
std::vector<std::string_view> bolaklar(std::string_view s, char ajr, int soni)
{
std::vector<std::string_view> n;
while (soni > 1) {
auto joy = s.find(ajr);
if (joy == std::string_view::npos) break;
n.push_back(s.substr(0, joy));
s.remove_prefix(joy + 1);
--soni;
}
n.push_back(s);
return n;
}
std::expected<Qator, QatorXatosi> ajrat(std::string_view qator)
{
if (qator.empty()) return std::unexpected{QatorXatosi::BoshQator};
auto b = bolaklar(qator, '|', 5);
if (b.size() < 5) return std::unexpected{QatorXatosi::KamMaydon};
auto d = darajaOqi(b[1]);
if (!d) return std::unexpected{QatorXatosi::NomalumDaraja};
int ms{};
auto [oxir, xato] = std::from_chars(b[4].data(), b[4].data() + b[4].size(), ms);
if (xato != std::errc{}) return std::unexpected{QatorXatosi::YaroqsizVaqt};
return Qator{std::string{b[0]}, *d, std::string{b[2]}, std::string{b[3]}, ms};
}
// Butun jarayonni boshqaradi - RAII, hech qanday qo'lda tozalash yo'q
class Tahlilchi
{
std::vector<Qator> qatorlar_;
int buzuq_{};
public:
void faylniOqi(const fs::path& yol)
{
std::ifstream fayl{yol};
if (!fayl) throw std::runtime_error{"fayl ochilmadi: " + yol.string()};
std::string qator;
while (std::getline(fayl, qator)) {
if (qator.empty() || qator.starts_with('#')) continue;
auto n = ajrat(qator);
if (n) qatorlar_.push_back(std::move(*n));
else ++buzuq_;
}
// fayl bu yerda avtomatik yopiladi
}
std::size_t soni() const { return qatorlar_.size(); }
int buzuq() const { return buzuq_; }
// Konsept bilan cheklangan shablon (15-bo'lim)
template <std::predicate<const Qator&> F>
std::vector<Qator> tanla(F shart) const
{
std::vector<Qator> n;
std::ranges::copy_if(qatorlar_, std::back_inserter(n), shart);
return n;
}
std::map<std::string, int> manbaHisobi() const
{
std::map<std::string, int> n;
for (const auto& q : qatorlar_) ++n[q.manba];
return n;
}
std::vector<Qator> engSekinlar(std::size_t nechta) const
{
auto nusxa = qatorlar_;
std::ranges::partial_sort(nusxa,
nusxa.begin() + static_cast<std::ptrdiff_t>(
std::min(nechta, nusxa.size())),
[](const Qator& a, const Qator& b) {
return a.davomiylik > b.davomiylik;
});
nusxa.resize(std::min(nechta, nusxa.size()));
return nusxa;
}
};
int main()
{
// Sinov faylini yaratamiz
fs::path yol{"/tmp/sr_cpp_jurnal.log"};
{
std::ofstream f{yol};
f << "# server jurnali\n";
f << "2024-09-01|INFO|auth|foydalanuvchi kirdi|42\n";
f << "2024-09-01|INFO|auth|sessiya yangilandi|18\n";
f << "2024-09-01|ERROR|db|ulanish uzildi|1500\n";
f << "2024-09-01|WARN|db|so'rov sekin|900\n";
f << "2024-09-01|FATAL|db|xizmat to'xtadi|3000\n";
f << "2024-09-01|ERROR|api|404 topilmadi|15\n";
f << "2024-09-01|INFO|api|so'rov bajarildi|60\n";
f << "2024-09-01|WARN|cache|kesh to'ldi|220\n";
f << "buzuq qator\n";
f << "2024-09-01|TRACE|api|nomalum daraja|10\n";
f << "\n";
}
Tahlilchi t;
t.faylniOqi(yol);
std::println("JURNAL HISOBOTI");
std::println("{}", std::string(52, '='));
std::println("Fayl: {}", yol.filename().string());
std::println("O'qilgan: {} qator", t.soni());
std::println("Buzuq: {} qator", t.buzuq());
std::println("");
std::println("Manbalar:");
for (const auto& [m, n] : t.manbaHisobi()) {
std::println(" {:<8} {:>2} {}", m, n, std::string(
static_cast<std::size_t>(n) * 2, '#'));
}
std::println("");
auto jiddiy = t.tanla([](const Qator& q) {
return q.daraja >= Daraja::Xato;
});
std::println("Jiddiy hodisalar ({} ta):", jiddiy.size());
for (const auto& q : jiddiy) {
std::println(" {:<8} {:<6} {}", darajaMatni(q.daraja), q.manba, q.xabar);
}
std::println("");
std::println("Eng sekin uchta:");
for (const auto& q : t.engSekinlar(3)) {
std::println(" {:>5} ms {:<6} {}", q.davomiylik, q.manba, q.xabar);
}
std::println("");
auto sekinDb = t.tanla([](const Qator& q) {
return q.manba == "db" && q.davomiylik > 1000;
});
std::println("db manbasidagi 1000 ms dan sekin: {} ta", sekinDb.size());
fs::remove(yol);
std::println("");
std::println("vaqtinchalik fayl tozalandi: {}", !fs::exists(yol));
return 0;
}
JURNAL HISOBOTI
====================================================
Fayl: sr_cpp_jurnal.log
O'qilgan: 8 qator
Buzuq: 2 qator
Manbalar:
api 2 ####
auth 2 ####
cache 1 ##
db 3 ######
Jiddiy hodisalar (3 ta):
XATO db ulanish uzildi
HALOKAT db xizmat to'xtadi
XATO api 404 topilmadi
Eng sekin uchta:
3000 ms db xizmat to'xtadi
1500 ms db ulanish uzildi
900 ms db so'rov sekin
db manbasidagi 1000 ms dan sekin: 2 ta
vaqtinchalik fayl tozalandi: true
Tahlilchi da destruktor yo'qSinf 200 qatordan iborat, fayl ochadi, vektor va lug'atlar boshqaradi - lekin destruktori yo'q.
Sabab - 12-bo'limdagi nol qoidasi:
| A'zo | Kim tozalaydi |
|---|---|
std::vector<Qator> | O'zi |
std::ifstream | O'zi (qamrovdan chiqqanda) |
std::string | O'zi |
std::map | O'zi |
Har bir a'zo o'z resursini biladi. Tahlilchi esa
faqat ularni birlashtiradi.
Natijada:
- Nusxalanadi (chuqur nusxa, avtomatik)
- Ko'chiriladi (arzon, avtomatik)
- Istisno xavfsiz (avtomatik)
- Sizib chiqmaydi (avtomatik)
Va bularning birortasi uchun kod yozilmagan.
Bu zamonaviy C++ ning asosiy g'oyasi: resursni boshqarish sinflarni kichik va maxsus qiling, qolgan hamma narsa ularni faqat ishlatsin.
Bundan keyin nima #
int main()
{
std::println("QAYERGA DAVOM ETISH");
std::println("{}", std::string(58, '='));
std::println("");
std::println("{:<26} {}", "MAVZU", "NIMA UCHUN");
std::println("{}", std::string(58, '-'));
std::println("{:<26} {}", "Modullar (C++20)", "Sarlavhalarsiz yig'ish");
std::println("{:<26} {}", "Korutinlar (C++20)", "Asinxron kod");
std::println("{:<26} {}", "Sinov ramkalari", "Catch2, doctest");
std::println("{:<26} {}", "Yig'ish tizimi", "CMake yoki Meson");
std::println("{:<26} {}", "Paket menejeri", "vcpkg yoki Conan");
std::println("{:<26} {}", "Profillash", "perf, valgrind");
std::println("{:<26} {}", "Statik tahlil", "clang-tidy");
std::println("{:<26} {}", "Formatlash", "clang-format");
std::println("");
std::println("Amaliyot g'oyalari:");
std::println(" 1. Ushbu tahlilchiga JSON chiqishini qo'shing");
std::println(" 2. Katta fayl uchun ko'p oqimli o'qish (18-bo'lim)");
std::println(" 3. Filtrlarni buyruq qatoridan o'qing");
std::println(" 4. Sana bo'yicha guruhlash qo'shing (17-bo'lim)");
std::println(" 5. Har bir qismga birlik sinovlari yozing");
std::println("");
std::println("Eng muhim maslahat:");
std::println(" Har kuni oz-ozdan yozing.");
std::println(" Har bir dasturni sanitayzer bilan ishga tushiring.");
std::println(" Kompilyator ogohlantirishlarini o'qing.");
return 0;
}
QAYERGA DAVOM ETISH
==========================================================
MAVZU NIMA UCHUN
----------------------------------------------------------
Modullar (C++20) Sarlavhalarsiz yig'ish
Korutinlar (C++20) Asinxron kod
Sinov ramkalari Catch2, doctest
Yig'ish tizimi CMake yoki Meson
Paket menejeri vcpkg yoki Conan
Profillash perf, valgrind
Statik tahlil clang-tidy
Formatlash clang-format
Amaliyot g'oyalari:
1. Ushbu tahlilchiga JSON chiqishini qo'shing
2. Katta fayl uchun ko'p oqimli o'qish (18-bo'lim)
3. Filtrlarni buyruq qatoridan o'qing
4. Sana bo'yicha guruhlash qo'shing (17-bo'lim)
5. Har bir qismga birlik sinovlari yozing
Eng muhim maslahat:
Har kuni oz-ozdan yozing.
Har bir dasturni sanitayzer bilan ishga tushiring.
Kompilyator ogohlantirishlarini o'qing.
- Tahlilchiga
--filtrbuyruq qatori parametrini qo'shing. - Chiqishni JSON formatida ham bera oladigan qiling.
Qatoruchunstd::formatterixtisoslashtiring (13-bo'lim).- Buzuq qatorlar ro'yxatini sabab bilan birga saqlang.
p95foizli ko'rsatkichni hisoblang.- Bir necha faylni birga tahlil qiling.
- Katta fayl uchun
std::asyncbilan parallel o'qing (18-bo'lim). - Sana bo'yicha guruhlab kunlik hisobot chiqaring (17-bo'lim).
- Dasturni
-fsanitize=address,undefinedbilan yig'ib sinang (19-bo'lim). -Wall -Wextra -Wpedantic -Werrorbilan yig'ing va barcha ogohlantirishlarni tuzating.
Xulosa #
- Haqiqiy dastur - alohida imkoniyatlar to'plami emas, ularning birgalikda ishlashi.
- Ma'lumot turi
structbo'lsin - invariant bo'lmasa nol qoidasi yetarli. - Ajratishda
string_viewishlating, saqlashdastringga nusxa oling. - Xato sababi kerak bo'lsa -
std::expected, kerak bo'lmasaoptional. - Ish paytida tanlanadigan xatti-harakat - virtual interfeys +
unique_ptr. - Kompozit naqsh filtrlarni birlashtirish imkonini beradi.
- Statistikada o'rtacha chalg'itadi - median va foizli ko'rsatkichlarni bering.
- Yuqori darajadagi sinf destruktor yozmasin - a'zolar o'zlarini tozalasin.
- Butun loyihada birorta
newyokideletebo'lmasligi mumkin - va bo'lmasligi kerak. - Har bir yig'ishda
-Wall -Wextra -Wpedantic, sinovlarda esa sanitayzerlar.
Darslik shu bilan yakunlandi. Endi eng muhim qadam sizniki: o'z loyihangizni yozing. C++ ni o'qib emas, yozib o'rganiladi.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.