From 2a6c53d5bff0c9b936636a4c408797d13dbd58aee732dc50c71c11051a420397 Mon Sep 17 00:00:00 2001 From: ArchZer0 Date: Sun, 16 Aug 2026 19:15:19 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-tidy | 145 +++++++++++++++++++++++ include/bstl/big_decimal.hpp | 20 ++-- include/bstl/big_integer.hpp | 20 ++-- include/bstl/string.hpp | 72 ++++++------ src/big_decimal.cpp | 118 +++++++++---------- src/big_integer.cpp | 168 +++++++++++++-------------- src/string.cpp | 215 ++++++++++++++++------------------- tests/big_integer_test.cpp | 14 +-- 8 files changed, 451 insertions(+), 321 deletions(-) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..a5b2a41 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,145 @@ +# Generated from CLion Inspection settings +--- +Checks: '-*, +bugprone-argument-comment, +bugprone-assert-side-effect, +bugprone-bad-signal-to-kill-thread, +bugprone-branch-clone, +bugprone-copy-constructor-init, +bugprone-dangling-handle, +bugprone-dynamic-static-initializers, +bugprone-fold-init-type, +bugprone-forward-declaration-namespace, +bugprone-forwarding-reference-overload, +bugprone-inaccurate-erase, +bugprone-incorrect-roundings, +bugprone-integer-division, +bugprone-lambda-function-name, +bugprone-macro-parentheses, +bugprone-macro-repeated-side-effects, +bugprone-misplaced-operator-in-strlen-in-alloc, +bugprone-misplaced-pointer-arithmetic-in-alloc, +bugprone-misplaced-widening-cast, +bugprone-move-forwarding-reference, +bugprone-multiple-statement-macro, +bugprone-no-escape, +bugprone-parent-virtual-call, +bugprone-posix-return, +bugprone-reserved-identifier, +bugprone-sizeof-container, +bugprone-sizeof-expression, +bugprone-spuriously-wake-up-functions, +bugprone-string-constructor, +bugprone-string-integer-assignment, +bugprone-string-literal-with-embedded-nul, +bugprone-suspicious-enum-usage, +bugprone-suspicious-include, +bugprone-suspicious-memset-usage, +bugprone-suspicious-missing-comma, +bugprone-suspicious-semicolon, +bugprone-suspicious-string-compare, +bugprone-suspicious-memory-comparison, +bugprone-suspicious-realloc-usage, +bugprone-swapped-arguments, +bugprone-terminating-continue, +bugprone-throw-keyword-missing, +bugprone-too-small-loop-variable, +bugprone-undefined-memory-manipulation, +bugprone-undelegated-constructor, +bugprone-unhandled-self-assignment, +bugprone-unused-raii, +bugprone-unused-return-value, +bugprone-use-after-move, +bugprone-virtual-near-miss, +cert-dcl21-cpp, +cert-dcl58-cpp, +cert-err34-c, +cert-err52-cpp, +cert-err60-cpp, +cert-flp30-c, +cert-msc50-cpp, +cert-msc51-cpp, +cert-str34-c, +cppcoreguidelines-interfaces-global-init, +cppcoreguidelines-narrowing-conversions, +cppcoreguidelines-pro-type-member-init, +cppcoreguidelines-pro-type-static-cast-downcast, +cppcoreguidelines-slicing, +google-default-arguments, +google-runtime-operator, +hicpp-exception-baseclass, +hicpp-multiway-paths-covered, +misc-misplaced-const, +misc-new-delete-overloads, +misc-non-copyable-objects, +misc-throw-by-value-catch-by-reference, +misc-unconventional-assign-operator, +misc-uniqueptr-reset-release, +modernize-avoid-bind, +modernize-concat-nested-namespaces, +modernize-deprecated-headers, +modernize-deprecated-ios-base-aliases, +modernize-loop-convert, +modernize-make-shared, +modernize-make-unique, +modernize-pass-by-value, +modernize-raw-string-literal, +modernize-redundant-void-arg, +modernize-replace-auto-ptr, +modernize-replace-disallow-copy-and-assign-macro, +modernize-replace-random-shuffle, +modernize-return-braced-init-list, +modernize-shrink-to-fit, +modernize-unary-static-assert, +modernize-use-auto, +modernize-use-bool-literals, +modernize-use-emplace, +modernize-use-equals-default, +modernize-use-equals-delete, +modernize-use-nodiscard, +modernize-use-noexcept, +modernize-use-nullptr, +modernize-use-override, +modernize-use-transparent-functors, +modernize-use-uncaught-exceptions, +mpi-buffer-deref, +mpi-type-mismatch, +openmp-use-default-none, +performance-faster-string-find, +performance-for-range-copy, +performance-implicit-conversion-in-loop, +performance-inefficient-algorithm, +performance-inefficient-string-concatenation, +performance-inefficient-vector-operation, +performance-move-const-arg, +performance-move-constructor-init, +performance-no-automatic-move, +performance-noexcept-move-constructor, +performance-trivially-destructible, +performance-type-promotion-in-math-fn, +performance-unnecessary-copy-initialization, +performance-unnecessary-value-param, +portability-simd-intrinsics, +readability-avoid-const-params-in-decls, +readability-const-return-type, +readability-container-size-empty, +readability-convert-member-functions-to-static, +readability-delete-null-pointer, +readability-deleted-default, +readability-inconsistent-declaration-parameter-name, +readability-make-member-function-const, +readability-misleading-indentation, +readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-control-flow, +readability-redundant-declaration, +readability-redundant-function-ptr-dereference, +readability-redundant-smartptr-get, +readability-redundant-string-cstr, +readability-redundant-string-init, +readability-simplify-subscript-expr, +readability-static-accessed-through-instance, +readability-static-definition-in-anonymous-namespace, +readability-string-compare, +readability-uniqueptr-delete-release, +readability-use-anyofallof' \ No newline at end of file diff --git a/include/bstl/big_decimal.hpp b/include/bstl/big_decimal.hpp index 0ce87b6..d0e4bdc 100644 --- a/include/bstl/big_decimal.hpp +++ b/include/bstl/big_decimal.hpp @@ -18,11 +18,11 @@ public: BigDecimal(const BigDecimal& other) = default; BigDecimal& operator=(const BigDecimal& other) = default; - bool isZero() const; - int sign() const; - int getScale() const; - BigInteger getUnscaledValue() const; - std::string toString() const; + [[nodiscard]] bool isZero() const; + [[nodiscard]] int sign() const; + [[nodiscard]] int getScale() const; + [[nodiscard]] BigInteger getUnscaledValue() const; + [[nodiscard]] std::string toString() const; // Comparison operators bool operator==(const BigDecimal& other) const; @@ -59,14 +59,14 @@ public: BigDecimal operator*(const BigDecimal& other) const; BigDecimal operator/(const BigDecimal& other) const; - BigDecimal abs() const; - BigDecimal round(int scale) const; + [[nodiscard]] BigDecimal abs() const; + [[nodiscard]] BigDecimal round(int scale) const; private: - BigInteger unscaledValue_; // 去掉小数点后的值 - int scale_; // 小数点后的位数 + BigInteger m_unscaledValue; // 去掉小数点后的值 + int m_scale; // 小数点后的位数 - static void alignScale(BigInteger& lhs, int& lhsScale, + static void m_alignScale(BigInteger& lhs, int& lhsScale, BigInteger& rhs, int& rhsScale); }; diff --git a/include/bstl/big_integer.hpp b/include/bstl/big_integer.hpp index 2f6e088..5ea6e69 100644 --- a/include/bstl/big_integer.hpp +++ b/include/bstl/big_integer.hpp @@ -17,9 +17,9 @@ public: BigInteger(const BigInteger& other) = default; BigInteger& operator=(const BigInteger& other) = default; - bool isZero() const; - int sign() const; - std::string toString() const; + [[nodiscard]] bool isZero() const; + [[nodiscard]] int sign() const; + [[nodiscard]] std::string toString() const; bool operator==(const BigInteger& other) const; bool operator!=(const BigInteger& other) const; @@ -55,14 +55,14 @@ public: BigInteger operator/(const BigInteger& other) const; private: - std::string digits_; // 无符号数字,从高位到低位 - int sign_; // -1, 0, 1 + std::string m_digits; // 无符号数字,从高位到低位 + int m_sign; // -1, 0, 1 - static std::string trimLeadingZeros(const std::string& value); - static int compareAbs(const std::string& a, const std::string& b); - static std::string addAbs(const std::string& a, const std::string& b); - static std::string subAbs(const std::string& a, const std::string& b); - static std::string mulAbs(const std::string& a, const std::string& b); + static std::string m_trimLeadingZeros(const std::string& value); + static int m_compareAbs(const std::string& a, const std::string& b); + static std::string m_addAbs(const std::string& a, const std::string& b); + static std::string m_subAbs(const std::string& a, const std::string& b); + static std::string m_mulAbs(const std::string& a, const std::string& b); static std::string divAbs(const std::string& a, const std::string& b); }; diff --git a/include/bstl/string.hpp b/include/bstl/string.hpp index 37588fe..c81df7a 100644 --- a/include/bstl/string.hpp +++ b/include/bstl/string.hpp @@ -11,69 +11,69 @@ namespace bstl { class String { public: String(); - String(const std::string& str); + String(std::string str); String(const char* str); String(const String& other) = default; String& operator=(const String& other) = default; // 获取标准字符串 - std::string str() const; - const char* c_str() const; - size_t length() const; - size_t size() const; - bool empty() const; + [[nodiscard]] std::string str() const; + [[nodiscard]] const char* c_str() const; + [[nodiscard]] size_t length() const; + [[nodiscard]] size_t size() const; + [[nodiscard]] bool empty() const; // 获取/修改字符 - char at(size_t pos) const; + [[nodiscard]] char at(size_t pos) const; char operator[](size_t pos) const; char& operator[](size_t pos); // 分割 - 按分隔符分割字符串 - std::vector split(const String& delimiter = " ") const; + [[nodiscard]] std::vector split(const String& delimiter = " ") const; // 连接 - 用分隔符连接多个字符串 static String join(const std::vector& parts, const String& delimiter = ""); // 替换 - 替换第一个/所有匹配项 - String replace(const String& oldStr, const String& newStr, int count = -1) const; + [[nodiscard]] String replace(const String& oldStr, const String& newStr, int count = -1) const; // 大小写转换 - String upper() const; - String lower() const; - String capitalize() const; // 首字母大写 - String title() const; // 每个单词首字母大写 + [[nodiscard]] String upper() const; + [[nodiscard]] String lower() const; + [[nodiscard]] String capitalize() const; // 首字母大写 + [[nodiscard]] String title() const; // 每个单词首字母大写 // 判断函数 - bool startswith(const String& prefix) const; - bool endswith(const String& suffix) const; - bool contains(const String& substring) const; - bool isdigit() const; - bool isalpha() const; - bool isalnum() const; - bool isspace() const; - bool isupper() const; - bool islower() const; + [[nodiscard]] bool startswith(const String& prefix) const; + [[nodiscard]] bool endswith(const String& suffix) const; + [[nodiscard]] bool contains(const String& substring) const; + [[nodiscard]] bool isdigit() const; + [[nodiscard]] bool isalpha() const; + [[nodiscard]] bool isalnum() const; + [[nodiscard]] bool isspace() const; + [[nodiscard]] bool isupper() const; + [[nodiscard]] bool islower() const; // 查找和计数 - int find(const String& substring, size_t start = 0) const; - int rfind(const String& substring) const; // 从后往前查找 - int count(const String& substring) const; + [[nodiscard]] int find(const String& substring, size_t start = 0) const; + [[nodiscard]] int rfind(const String& substring) const; // 从后往前查找 + [[nodiscard]] int count(const String& substring) const; // 去除空格和其他字符 - String strip() const; // 去除前后空格 - String lstrip() const; // 去除前导空格 - String rstrip() const; // 去除尾部空格 - String strip(const String& chars) const; // 去除指定字符 + [[nodiscard]] String strip() const; // 去除前后空格 + [[nodiscard]] String lstrip() const; // 去除前导空格 + [[nodiscard]] String rstrip() const; // 去除尾部空格 + [[nodiscard]] String strip(const String& chars) const; // 去除指定字符 // 对齐和填充 - String ljust(size_t width, char fillchar = ' ') const; - String rjust(size_t width, char fillchar = ' ') const; - String center(size_t width, char fillchar = ' ') const; + [[nodiscard]] String ljust(size_t width, char fillchar = ' ') const; + [[nodiscard]] String rjust(size_t width, char fillchar = ' ') const; + [[nodiscard]] String center(size_t width, char fillchar = ' ') const; // 字符串转换 - int toInt() const; - long long toLongLong() const; - double toDouble() const; + [[nodiscard]] int toInt() const; + [[nodiscard]] long long toLongLong() const; + [[nodiscard]] double toDouble() const; // 运算符重载 String operator+(const String& other) const; @@ -87,7 +87,7 @@ public: bool operator>=(const String& other) const; private: - std::string data_; + std::string m_data; }; // 流运算符重载 diff --git a/src/big_decimal.cpp b/src/big_decimal.cpp index 2570da5..5e7bfc4 100644 --- a/src/big_decimal.cpp +++ b/src/big_decimal.cpp @@ -6,16 +6,16 @@ namespace bstl { -BigDecimal::BigDecimal() : unscaledValue_(0), scale_(0) {} +BigDecimal::BigDecimal() : m_unscaledValue(0), m_scale(0) {} -BigDecimal::BigDecimal(int value) : unscaledValue_(value), scale_(0) {} +BigDecimal::BigDecimal(int value) : m_unscaledValue(value), m_scale(0) {} -BigDecimal::BigDecimal(long long value) : unscaledValue_(value), scale_(0) {} +BigDecimal::BigDecimal(long long value) : m_unscaledValue(value), m_scale(0) {} -BigDecimal::BigDecimal(double value) : scale_(0) { +BigDecimal::BigDecimal(double value) : m_scale(0) { if (value == 0.0) { - unscaledValue_ = 0; - scale_ = 0; + m_unscaledValue = 0; + m_scale = 0; return; } @@ -26,7 +26,7 @@ BigDecimal::BigDecimal(double value) : scale_(0) { *this = BigDecimal(oss.str()); } -BigDecimal::BigDecimal(const std::string& value) : unscaledValue_(0), scale_(0) { +BigDecimal::BigDecimal(const std::string& value) : m_unscaledValue(0), m_scale(0) { if (value.empty()) { return; } @@ -46,12 +46,12 @@ BigDecimal::BigDecimal(const std::string& value) : unscaledValue_(0), scale_(0) // 查找小数点位置 size_t dotPos = text.find('.'); if (dotPos != std::string::npos) { - scale_ = text.size() - dotPos - 1; + m_scale = static_cast(text.size() - dotPos - 1); std::string digits = text.substr(0, dotPos) + text.substr(dotPos + 1); - unscaledValue_ = BigInteger(digits); + m_unscaledValue = BigInteger(digits); } else { - scale_ = 0; - unscaledValue_ = BigInteger(text); + m_scale = 0; + m_unscaledValue = BigInteger(text); } } @@ -59,26 +59,26 @@ BigDecimal::BigDecimal(const char* value) : BigDecimal(value == nullptr ? std::string("0") : std::string(value)) {} BigDecimal::BigDecimal(const BigInteger& unscaledValue, int scale) - : unscaledValue_(unscaledValue), scale_(scale) { + : m_unscaledValue(unscaledValue), m_scale(scale) { if (scale < 0) { throw std::invalid_argument("scale cannot be negative"); } } bool BigDecimal::isZero() const { - return unscaledValue_.isZero(); + return m_unscaledValue.isZero(); } int BigDecimal::sign() const { - return unscaledValue_.sign(); + return m_unscaledValue.sign(); } int BigDecimal::getScale() const { - return scale_; + return m_scale; } BigInteger BigDecimal::getUnscaledValue() const { - return unscaledValue_; + return m_unscaledValue; } std::string BigDecimal::toString() const { @@ -86,7 +86,7 @@ std::string BigDecimal::toString() const { return "0"; } - std::string digitStr = unscaledValue_.toString(); + std::string digitStr = m_unscaledValue.toString(); // 处理符号 bool negative = false; @@ -96,26 +96,26 @@ std::string BigDecimal::toString() const { } // 插入小数点 - if (scale_ == 0) { + if (m_scale == 0) { return (negative ? "-" : "") + digitStr; } - if (static_cast(digitStr.size()) <= scale_) { + if (static_cast(digitStr.size()) <= m_scale) { // 需要前置 "0." std::string result = "0."; - for (int i = 0; i < scale_ - static_cast(digitStr.size()); i++) { + for (int i = 0; i < m_scale - static_cast(digitStr.size()); i++) { result += "0"; } result += digitStr; return (negative ? "-" : "") + result; } - int dotPos = digitStr.size() - scale_; + int dotPos = static_cast(digitStr.size()) - m_scale; std::string result = digitStr.substr(0, dotPos) + "." + digitStr.substr(dotPos); return (negative ? "-" : "") + result; } -void BigDecimal::alignScale(BigInteger& lhs, int& lhsScale, +void BigDecimal::m_alignScale(BigInteger& lhs, int& lhsScale, BigInteger& rhs, int& rhsScale) { if (lhsScale < rhsScale) { // 左边需要扩大 @@ -134,11 +134,11 @@ void BigDecimal::alignScale(BigInteger& lhs, int& lhsScale, bool BigDecimal::operator==(const BigDecimal& other) const { if (isZero() && other.isZero()) return true; - BigInteger lhs = unscaledValue_; - BigInteger rhs = other.unscaledValue_; - int lhsScale = scale_; - int rhsScale = other.scale_; - alignScale(lhs, lhsScale, rhs, rhsScale); + BigInteger lhs = m_unscaledValue; + BigInteger rhs = other.m_unscaledValue; + int lhsScale = m_scale; + int rhsScale = other.m_scale; + m_alignScale(lhs, lhsScale, rhs, rhsScale); return lhs == rhs; } @@ -147,17 +147,17 @@ bool BigDecimal::operator!=(const BigDecimal& other) const { } bool BigDecimal::operator<(const BigDecimal& other) const { - if (unscaledValue_.sign() != other.unscaledValue_.sign()) { - return unscaledValue_.sign() < other.unscaledValue_.sign(); + if (m_unscaledValue.sign() != other.m_unscaledValue.sign()) { + return m_unscaledValue.sign() < other.m_unscaledValue.sign(); } - BigInteger lhs = unscaledValue_; - BigInteger rhs = other.unscaledValue_; - int lhsScale = scale_; - int rhsScale = other.scale_; - alignScale(lhs, lhsScale, rhs, rhsScale); + BigInteger lhs = m_unscaledValue; + BigInteger rhs = other.m_unscaledValue; + int lhsScale = m_scale; + int rhsScale = other.m_scale; + m_alignScale(lhs, lhsScale, rhs, rhsScale); - if (unscaledValue_.sign() >= 0) { + if (m_unscaledValue.sign() >= 0) { return lhs < rhs; } else { return lhs > rhs; @@ -230,9 +230,9 @@ BigDecimal BigDecimal::operator+() const { BigDecimal BigDecimal::operator-() const { if (isZero()) { - return BigDecimal(0); + return {0}; } - return BigDecimal(-unscaledValue_, scale_); + return {-m_unscaledValue, m_scale}; } BigDecimal& BigDecimal::operator+=(const BigDecimal& other) { @@ -259,13 +259,13 @@ BigDecimal BigDecimal::operator+(const BigDecimal& other) const { if (isZero()) return other; if (other.isZero()) return *this; - BigInteger lhs = unscaledValue_; - BigInteger rhs = other.unscaledValue_; - int lhsScale = scale_; - int rhsScale = other.scale_; - alignScale(lhs, lhsScale, rhs, rhsScale); + BigInteger lhs = m_unscaledValue; + BigInteger rhs = other.m_unscaledValue; + int lhsScale = m_scale; + int rhsScale = other.m_scale; + m_alignScale(lhs, lhsScale, rhs, rhsScale); - return BigDecimal(lhs + rhs, lhsScale); + return {lhs + rhs, lhsScale}; } BigDecimal BigDecimal::operator-(const BigDecimal& other) const { @@ -274,13 +274,13 @@ BigDecimal BigDecimal::operator-(const BigDecimal& other) const { BigDecimal BigDecimal::operator*(const BigDecimal& other) const { if (isZero() || other.isZero()) { - return BigDecimal(0); + return {0}; } - BigInteger result = unscaledValue_ * other.unscaledValue_; - int resultScale = scale_ + other.scale_; + BigInteger result = m_unscaledValue * other.m_unscaledValue; + int resultScale = m_scale + other.m_scale; - return BigDecimal(result, resultScale); + return {result, resultScale}; } BigDecimal BigDecimal::operator/(const BigDecimal& other) const { @@ -289,14 +289,14 @@ BigDecimal BigDecimal::operator/(const BigDecimal& other) const { } if (isZero()) { - return BigDecimal(0); + return {0}; } // 先对齐 scale,然后做整数除法 - BigInteger lhs = unscaledValue_; - BigInteger rhs = other.unscaledValue_; - int lhsScale = scale_; - int rhsScale = other.scale_; + BigInteger lhs = m_unscaledValue; + BigInteger rhs = other.m_unscaledValue; + int lhsScale = m_scale; + int rhsScale = other.m_scale; // 使用更高的精度进行除法 // 乘以 10^precision 来获得更多的精度 @@ -308,14 +308,14 @@ BigDecimal BigDecimal::operator/(const BigDecimal& other) const { BigInteger quotient = lhs / rhs; int resultScale = lhsScale - rhsScale + precision; - return BigDecimal(quotient, resultScale); + return {quotient, resultScale}; } BigDecimal BigDecimal::abs() const { - if (unscaledValue_.sign() >= 0) { + if (m_unscaledValue.sign() >= 0) { return *this; } - return BigDecimal(-unscaledValue_, scale_); + return {-m_unscaledValue, m_scale}; } BigDecimal BigDecimal::round(int scale) const { @@ -323,19 +323,19 @@ BigDecimal BigDecimal::round(int scale) const { throw std::invalid_argument("scale cannot be negative"); } - if (scale >= scale_) { + if (scale >= m_scale) { return *this; } // 简单实现:直接截断到指定小数位数 - int diff = scale_ - scale; + int diff = m_scale - scale; BigInteger divisor = BigInteger(10); for (int i = 1; i < diff; i++) { divisor = divisor * BigInteger(10); } - BigInteger rounded = unscaledValue_ / divisor; - return BigDecimal(rounded, scale); + BigInteger rounded = m_unscaledValue / divisor; + return {rounded, scale}; } std::ostream& operator<<(std::ostream& os, const BigDecimal& bd) { diff --git a/src/big_integer.cpp b/src/big_integer.cpp index 4436fd9..29576e0 100644 --- a/src/big_integer.cpp +++ b/src/big_integer.cpp @@ -7,7 +7,7 @@ namespace bstl { -std::string BigInteger::trimLeadingZeros(const std::string& value) { +std::string BigInteger::m_trimLeadingZeros(const std::string& value) { size_t pos = 0; while (pos < value.size() - 1 && value[pos] == '0') { pos++; @@ -15,16 +15,16 @@ std::string BigInteger::trimLeadingZeros(const std::string& value) { return value.substr(pos); } -int BigInteger::compareAbs(const std::string& a, const std::string& b) { - std::string ta = trimLeadingZeros(a); - std::string tb = trimLeadingZeros(b); +int BigInteger::m_compareAbs(const std::string& a, const std::string& b) { + std::string ta = m_trimLeadingZeros(a); + std::string tb = m_trimLeadingZeros(b); if (ta.size() != tb.size()) { return ta.size() < tb.size() ? -1 : 1; } return ta.compare(tb) < 0 ? -1 : (ta.compare(tb) > 0 ? 1 : 0); } -std::string BigInteger::addAbs(const std::string& a, const std::string& b) { +std::string BigInteger::m_addAbs(const std::string& a, const std::string& b) { std::string result; int carry = 0; int i = static_cast(a.size()) - 1; @@ -33,17 +33,17 @@ std::string BigInteger::addAbs(const std::string& a, const std::string& b) { int sum = carry; if (i >= 0) sum += a[i--] - '0'; if (j >= 0) sum += b[j--] - '0'; - result = char('0' + sum % 10) + result; + result.insert(result.begin(), static_cast('0' + sum % 10)); carry = sum / 10; } return result; } -std::string BigInteger::subAbs(const std::string& a, const std::string& b) { - std::string ta = trimLeadingZeros(a); - std::string tb = trimLeadingZeros(b); - if (compareAbs(ta, tb) < 0) { - return subAbs(tb, ta); +std::string BigInteger::m_subAbs(const std::string& a, const std::string& b) { + std::string ta = m_trimLeadingZeros(a); + std::string tb = m_trimLeadingZeros(b); + if (m_compareAbs(ta, tb) < 0) { + return m_subAbs(tb, ta); } std::string result; int borrow = 0; @@ -60,14 +60,14 @@ std::string BigInteger::subAbs(const std::string& a, const std::string& b) { } else { borrow = 0; } - result = char('0' + diff) + result; + result.insert(result.begin(), static_cast('0' + diff)); } - return trimLeadingZeros(result); + return m_trimLeadingZeros(result); } -std::string BigInteger::mulAbs(const std::string& a, const std::string& b) { - std::string ta = trimLeadingZeros(a); - std::string tb = trimLeadingZeros(b); +std::string BigInteger::m_mulAbs(const std::string& a, const std::string& b) { + std::string ta = m_trimLeadingZeros(a); + std::string tb = m_trimLeadingZeros(b); if (ta == "0" || tb == "0") return "0"; std::vector product(ta.size() + tb.size(), 0); @@ -79,9 +79,9 @@ std::string BigInteger::mulAbs(const std::string& a, const std::string& b) { } int carry = 0; - for (size_t i = 0; i < product.size(); i++) { - int sum = product[i] + carry; - product[i] = sum % 10; + for (int & i : product) { + int sum = i + carry; + i = sum % 10; carry = sum / 10; } @@ -89,16 +89,16 @@ std::string BigInteger::mulAbs(const std::string& a, const std::string& b) { for (int i = static_cast(product.size()) - 1; i >= 0; i--) { result += char('0' + product[i]); } - return trimLeadingZeros(result); + return m_trimLeadingZeros(result); } std::string BigInteger::divAbs(const std::string& a, const std::string& b) { - std::string tb = trimLeadingZeros(b); + std::string tb = m_trimLeadingZeros(b); if (tb == "0") { throw std::invalid_argument("division by zero"); } - std::string ta = trimLeadingZeros(a); - if (compareAbs(ta, tb) < 0) { + std::string ta = m_trimLeadingZeros(a); + if (m_compareAbs(ta, tb) < 0) { return "0"; } @@ -106,86 +106,86 @@ std::string BigInteger::divAbs(const std::string& a, const std::string& b) { std::string current; for (char digit : ta) { current += digit; - current = trimLeadingZeros(current); + current = m_trimLeadingZeros(current); int count = 0; - while (compareAbs(current, tb) >= 0) { - current = subAbs(current, tb); + while (m_compareAbs(current, tb) >= 0) { + current = m_subAbs(current, tb); count++; } quotient += char('0' + count); } - return trimLeadingZeros(quotient); + return m_trimLeadingZeros(quotient); } -BigInteger::BigInteger() : digits_("0"), sign_(0) {} +BigInteger::BigInteger() : m_digits("0"), m_sign(0) {} -BigInteger::BigInteger(int value) : digits_("0"), sign_(1) { +BigInteger::BigInteger(int value) : m_digits("0"), m_sign(1) { if (value == 0) { - digits_ = "0"; - sign_ = 0; + m_digits = "0"; + m_sign = 0; return; } if (value < 0) { - sign_ = -1; + m_sign = -1; value = -value; } - digits_.clear(); + m_digits.clear(); while (value > 0) { - digits_ = char('0' + value % 10) + digits_; + m_digits = char('0' + value % 10) + m_digits; value /= 10; } } -BigInteger::BigInteger(long long value) : digits_("0"), sign_(1) { +BigInteger::BigInteger(long long value) : m_digits("0"), m_sign(1) { if (value == 0) { - digits_ = "0"; - sign_ = 0; + m_digits = "0"; + m_sign = 0; return; } if (value < 0) { - sign_ = -1; + m_sign = -1; value = -value; } - digits_.clear(); + m_digits.clear(); while (value > 0) { - digits_ = char('0' + value % 10) + digits_; + m_digits = char('0' + value % 10) + m_digits; value /= 10; } } -BigInteger::BigInteger(unsigned long long value) : digits_("0"), sign_(1) { +BigInteger::BigInteger(unsigned long long value) : m_digits("0"), m_sign(1) { if (value == 0) { - digits_ = "0"; - sign_ = 0; + m_digits = "0"; + m_sign = 0; return; } - digits_.clear(); + m_digits.clear(); while (value > 0) { - digits_ = char('0' + value % 10) + digits_; + m_digits = char('0' + value % 10) + m_digits; value /= 10; } } -BigInteger::BigInteger(const std::string& value) : digits_("0"), sign_(1) { +BigInteger::BigInteger(const std::string& value) : m_digits("0"), m_sign(1) { if (value.empty()) { - digits_ = "0"; - sign_ = 0; + m_digits = "0"; + m_sign = 0; return; } std::string text = value; - sign_ = 1; + m_sign = 1; if (text[0] == '-') { - sign_ = -1; + m_sign = -1; text = text.substr(1); } else if (text[0] == '+') { text = text.substr(1); } if (text.empty()) { - digits_ = "0"; - sign_ = 0; + m_digits = "0"; + m_sign = 0; return; } @@ -195,9 +195,9 @@ BigInteger::BigInteger(const std::string& value) : digits_("0"), sign_(1) { } } - digits_ = trimLeadingZeros(text); - if (digits_ == "0") { - sign_ = 0; + m_digits = m_trimLeadingZeros(text); + if (m_digits == "0") { + m_sign = 0; } } @@ -205,21 +205,21 @@ BigInteger::BigInteger(const char* value) : BigInteger(value == nullptr ? std::string("0") : std::string(value)) {} bool BigInteger::isZero() const { - return sign_ == 0 || digits_ == "0"; + return m_sign == 0 || m_digits == "0"; } int BigInteger::sign() const { - return isZero() ? 0 : sign_; + return isZero() ? 0 : m_sign; } std::string BigInteger::toString() const { if (isZero()) return "0"; - return (sign_ < 0 ? "-" : "") + digits_; + return (m_sign < 0 ? "-" : "") + m_digits; } bool BigInteger::operator==(const BigInteger& other) const { if (isZero() && other.isZero()) return true; - return sign_ == other.sign_ && digits_ == other.digits_; + return m_sign == other.m_sign && m_digits == other.m_digits; } bool BigInteger::operator!=(const BigInteger& other) const { @@ -227,10 +227,10 @@ bool BigInteger::operator!=(const BigInteger& other) const { } bool BigInteger::operator<(const BigInteger& other) const { - if (sign_ != other.sign_) return sign_ < other.sign_; - if (sign_ == 0) return false; - int cmp = compareAbs(digits_, other.digits_); - return sign_ > 0 ? cmp < 0 : cmp > 0; + if (m_sign != other.m_sign) return m_sign < other.m_sign; + if (m_sign == 0) return false; + int cmp = m_compareAbs(m_digits, other.m_digits); + return m_sign > 0 ? cmp < 0 : cmp > 0; } bool BigInteger::operator>(const BigInteger& other) const { @@ -298,9 +298,9 @@ BigInteger BigInteger::operator+() const { } BigInteger BigInteger::operator-() const { - if (isZero()) return BigInteger(0); + if (isZero()) return {0}; BigInteger result(*this); - result.sign_ = -result.sign_; + result.m_sign = -result.m_sign; return result; } @@ -329,23 +329,23 @@ BigInteger BigInteger::operator+(const BigInteger& other) const { if (other.isZero()) return *this; BigInteger result; - if (sign_ == other.sign_) { - result.digits_ = addAbs(digits_, other.digits_); - result.sign_ = sign_; + if (m_sign == other.m_sign) { + result.m_digits = m_addAbs(m_digits, other.m_digits); + result.m_sign = m_sign; } else { - int cmp = compareAbs(digits_, other.digits_); + int cmp = m_compareAbs(m_digits, other.m_digits); if (cmp == 0) { - result.digits_ = "0"; - result.sign_ = 0; + result.m_digits = "0"; + result.m_sign = 0; } else if (cmp > 0) { - result.digits_ = subAbs(digits_, other.digits_); - result.sign_ = sign_; + result.m_digits = m_subAbs(m_digits, other.m_digits); + result.m_sign = m_sign; } else { - result.digits_ = subAbs(other.digits_, digits_); - result.sign_ = other.sign_; + result.m_digits = m_subAbs(other.m_digits, m_digits); + result.m_sign = other.m_sign; } } - if (result.digits_ == "0") result.sign_ = 0; + if (result.m_digits == "0") result.m_sign = 0; return result; } @@ -354,11 +354,11 @@ BigInteger BigInteger::operator-(const BigInteger& other) const { } BigInteger BigInteger::operator*(const BigInteger& other) const { - if (isZero() || other.isZero()) return BigInteger(0); + if (isZero() || other.isZero()) return {0}; BigInteger result; - result.digits_ = mulAbs(digits_, other.digits_); - result.sign_ = (sign_ * other.sign_); - if (result.digits_ == "0") result.sign_ = 0; + result.m_digits = m_mulAbs(m_digits, other.m_digits); + result.m_sign = (m_sign * other.m_sign); + if (result.m_digits == "0") result.m_sign = 0; return result; } @@ -366,11 +366,11 @@ BigInteger BigInteger::operator/(const BigInteger& other) const { if (other.isZero()) { throw std::invalid_argument("division by zero"); } - if (isZero()) return BigInteger(0); + if (isZero()) return {0}; BigInteger result; - result.digits_ = divAbs(digits_, other.digits_); - result.sign_ = (sign_ * other.sign_); - if (result.digits_ == "0") result.sign_ = 0; + result.m_digits = divAbs(m_digits, other.m_digits); + result.m_sign = (m_sign * other.m_sign); + if (result.m_digits == "0") result.m_sign = 0; return result; } diff --git a/src/string.cpp b/src/string.cpp index e1e2a1a..068cfda 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -2,54 +2,55 @@ #include #include +#include namespace bstl { -String::String() : data_("") {} +String::String() = default; -String::String(const std::string& str) : data_(str) {} +String::String(std::string str) : m_data(std::move(str)) {} -String::String(const char* str) : data_(str == nullptr ? "" : str) {} +String::String(const char* str) : m_data(str == nullptr ? "" : str) {} std::string String::str() const { - return data_; + return m_data; } const char* String::c_str() const { - return data_.c_str(); + return m_data.c_str(); } size_t String::length() const { - return data_.length(); + return m_data.length(); } size_t String::size() const { - return data_.size(); + return m_data.size(); } bool String::empty() const { - return data_.empty(); + return m_data.empty(); } char String::at(size_t pos) const { - if (pos >= data_.size()) { + if (pos >= m_data.size()) { throw std::out_of_range("String::at: index out of range"); } - return data_[pos]; + return m_data[pos]; } char String::operator[](size_t pos) const { - return data_[pos]; + return m_data[pos]; } char& String::operator[](size_t pos) { - return data_[pos]; + return m_data[pos]; } std::vector String::split(const String& delimiter) const { std::vector result; - if (data_.empty()) { + if (m_data.empty()) { return result; } @@ -61,25 +62,25 @@ std::vector String::split(const String& delimiter) const { size_t start = 0; size_t pos = 0; - while ((pos = data_.find(delimiter.data_, start)) != std::string::npos) { - result.push_back(String(data_.substr(start, pos - start))); + while ((pos = m_data.find(delimiter.m_data, start)) != std::string::npos) { + result.emplace_back(m_data.substr(start, pos - start)); start = pos + delimiter.size(); } - result.push_back(String(data_.substr(start))); + result.emplace_back(m_data.substr(start)); return result; } String String::join(const std::vector& parts, const String& delimiter) { if (parts.empty()) { - return String(""); + return {""}; } std::string result = parts[0].str(); for (size_t i = 1; i < parts.size(); i++) { result += delimiter.str() + parts[i].str(); } - return String(result); + return {result}; } String String::replace(const String& oldStr, const String& newStr, int count) const { @@ -87,140 +88,124 @@ String String::replace(const String& oldStr, const String& newStr, int count) co return *this; } - std::string result = data_; + std::string result = m_data; size_t pos = 0; int replaced = 0; - while ((pos = result.find(oldStr.data_, pos)) != std::string::npos && (count < 0 || replaced < count)) { + while ((pos = result.find(oldStr.m_data, pos)) != std::string::npos && (count < 0 || replaced < count)) { result.replace(pos, oldStr.size(), newStr.str()); pos += newStr.size(); replaced++; } - return String(result); + return {result}; } String String::upper() const { - std::string result = data_; + std::string result = m_data; std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::toupper(c); }); - return String(result); + return {result}; } String String::lower() const { - std::string result = data_; + std::string result = m_data; std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::tolower(c); }); - return String(result); + return {result}; } String String::capitalize() const { - if (data_.empty()) { + if (m_data.empty()) { return *this; } - std::string result = data_; - result[0] = std::toupper(static_cast(result[0])); + std::string result = m_data; + result[0] = static_cast(std::toupper(static_cast(result[0]))); for (size_t i = 1; i < result.size(); i++) { - result[i] = std::tolower(static_cast(result[i])); + result[i] = static_cast(std::tolower(static_cast(result[i]))); } - return String(result); + return {result}; } String String::title() const { - std::string result = data_; + std::string result = m_data; bool newWord = true; - for (size_t i = 0; i < result.size(); i++) { - if (std::isspace(static_cast(result[i]))) { + for (char & i : result) { + if (std::isspace(static_cast(i))) { newWord = true; } else { if (newWord) { - result[i] = std::toupper(static_cast(result[i])); + i = static_cast(std::toupper(static_cast(i))); newWord = false; } else { - result[i] = std::tolower(static_cast(result[i])); + i = static_cast(std::tolower(static_cast(i))); } } } - return String(result); + return {result}; } bool String::startswith(const String& prefix) const { - if (prefix.size() > data_.size()) { + if (prefix.size() > m_data.size()) { return false; } - return data_.compare(0, prefix.size(), prefix.data_) == 0; + return m_data.compare(0, prefix.size(), prefix.m_data) == 0; } bool String::endswith(const String& suffix) const { - if (suffix.size() > data_.size()) { + if (suffix.size() > m_data.size()) { return false; } - return data_.compare(data_.size() - suffix.size(), suffix.size(), suffix.data_) == 0; + return m_data.compare(m_data.size() - suffix.size(), suffix.size(), suffix.m_data) == 0; } bool String::contains(const String& substring) const { - return data_.find(substring.data_) != std::string::npos; + return m_data.find(substring.m_data) != std::string::npos; } bool String::isdigit() const { - if (data_.empty()) return false; - for (unsigned char c : data_) { - if (!std::isdigit(c)) return false; - } - return true; + return !m_data.empty() && + std::all_of(m_data.begin(), m_data.end(), + [](unsigned char c) { return std::isdigit(c) != 0; }); } bool String::isalpha() const { - if (data_.empty()) return false; - for (unsigned char c : data_) { - if (!std::isalpha(c)) return false; - } - return true; + return !m_data.empty() && + std::all_of(m_data.begin(), m_data.end(), + [](unsigned char c) { return std::isalpha(c) != 0; }); } bool String::isalnum() const { - if (data_.empty()) return false; - for (unsigned char c : data_) { - if (!std::isalnum(c)) return false; - } - return true; + return !m_data.empty() && + std::all_of(m_data.begin(), m_data.end(), + [](unsigned char c) { return std::isalnum(c) != 0; }); } bool String::isspace() const { - if (data_.empty()) return false; - for (unsigned char c : data_) { - if (!std::isspace(c)) return false; - } - return true; + return !m_data.empty() && + std::all_of(m_data.begin(), m_data.end(), + [](unsigned char c) { return std::isspace(c) != 0; }); } bool String::isupper() const { - if (data_.empty()) return false; - for (unsigned char c : data_) { - if (std::isalpha(c) && !std::isupper(c)) { - return false; - } - } - return true; + return !m_data.empty() && + std::all_of(m_data.begin(), m_data.end(), + [](unsigned char c) { return !std::isalpha(c) || std::isupper(c) != 0; }); } bool String::islower() const { - if (data_.empty()) return false; - for (unsigned char c : data_) { - if (std::isalpha(c) && !std::islower(c)) { - return false; - } - } - return true; + return !m_data.empty() && + std::all_of(m_data.begin(), m_data.end(), + [](unsigned char c) { return !std::isalpha(c) || std::islower(c) != 0; }); } int String::find(const String& substring, size_t start) const { - size_t pos = data_.find(substring.data_, start); + size_t pos = m_data.find(substring.m_data, start); return pos == std::string::npos ? -1 : static_cast(pos); } int String::rfind(const String& substring) const { - size_t pos = data_.rfind(substring.data_); + size_t pos = m_data.rfind(substring.m_data); return pos == std::string::npos ? -1 : static_cast(pos); } @@ -228,7 +213,7 @@ int String::count(const String& substring) const { if (substring.empty()) return 0; int count = 0; size_t pos = 0; - while ((pos = data_.find(substring.data_, pos)) != std::string::npos) { + while ((pos = m_data.find(substring.m_data, pos)) != std::string::npos) { count++; pos += substring.size(); } @@ -237,126 +222,126 @@ int String::count(const String& substring) const { String String::strip() const { size_t start = 0; - size_t end = data_.size(); + size_t end = m_data.size(); - while (start < end && std::isspace(static_cast(data_[start]))) { + while (start < end && std::isspace(static_cast(m_data[start]))) { start++; } - while (end > start && std::isspace(static_cast(data_[end - 1]))) { + while (end > start && std::isspace(static_cast(m_data[end - 1]))) { end--; } - return String(data_.substr(start, end - start)); + return {m_data.substr(start, end - start)}; } String String::lstrip() const { size_t start = 0; - while (start < data_.size() && std::isspace(static_cast(data_[start]))) { + while (start < m_data.size() && std::isspace(static_cast(m_data[start]))) { start++; } - return String(data_.substr(start)); + return {m_data.substr(start)}; } String String::rstrip() const { - size_t end = data_.size(); - while (end > 0 && std::isspace(static_cast(data_[end - 1]))) { + size_t end = m_data.size(); + while (end > 0 && std::isspace(static_cast(m_data[end - 1]))) { end--; } - return String(data_.substr(0, end)); + return {m_data.substr(0, end)}; } String String::strip(const String& chars) const { size_t start = 0; - size_t end = data_.size(); + size_t end = m_data.size(); - while (start < end && chars.data_.find(data_[start]) != std::string::npos) { + while (start < end && chars.m_data.find(m_data[start]) != std::string::npos) { start++; } - while (end > start && chars.data_.find(data_[end - 1]) != std::string::npos) { + while (end > start && chars.m_data.find(m_data[end - 1]) != std::string::npos) { end--; } - return String(data_.substr(start, end - start)); + return {m_data.substr(start, end - start)}; } String String::ljust(size_t width, char fillchar) const { - if (data_.size() >= width) { + if (m_data.size() >= width) { return *this; } - std::string result = data_; - result.append(width - data_.size(), fillchar); - return String(result); + std::string result = m_data; + result.append(width - m_data.size(), fillchar); + return {result}; } String String::rjust(size_t width, char fillchar) const { - if (data_.size() >= width) { + if (m_data.size() >= width) { return *this; } - std::string result(width - data_.size(), fillchar); - result.append(data_); - return String(result); + std::string result(width - m_data.size(), fillchar); + result.append(m_data); + return {result}; } String String::center(size_t width, char fillchar) const { - if (data_.size() >= width) { + if (m_data.size() >= width) { return *this; } - size_t totalPad = width - data_.size(); + size_t totalPad = width - m_data.size(); size_t leftPad = totalPad / 2; size_t rightPad = totalPad - leftPad; std::string result(leftPad, fillchar); - result.append(data_); + result.append(m_data); result.append(rightPad, fillchar); - return String(result); + return {result}; } int String::toInt() const { - return std::stoi(data_); + return std::stoi(m_data); } long long String::toLongLong() const { - return std::stoll(data_); + return std::stoll(m_data); } double String::toDouble() const { - return std::stod(data_); + return std::stod(m_data); } String String::operator+(const String& other) const { - return String(data_ + other.data_); + return {m_data + other.m_data}; } String String::operator+(const char* str) const { - return String(data_ + (str == nullptr ? "" : str)); + return {m_data + (str == nullptr ? "" : str)}; } String& String::operator+=(const String& other) { - data_ += other.data_; + m_data += other.m_data; return *this; } bool String::operator==(const String& other) const { - return data_ == other.data_; + return m_data == other.m_data; } bool String::operator!=(const String& other) const { - return data_ != other.data_; + return m_data != other.m_data; } bool String::operator<(const String& other) const { - return data_ < other.data_; + return m_data < other.m_data; } bool String::operator>(const String& other) const { - return data_ > other.data_; + return m_data > other.m_data; } bool String::operator<=(const String& other) const { - return data_ <= other.data_; + return m_data <= other.m_data; } bool String::operator>=(const String& other) const { - return data_ >= other.data_; + return m_data >= other.m_data; } std::ostream& operator<<(std::ostream& os, const String& str) { diff --git a/tests/big_integer_test.cpp b/tests/big_integer_test.cpp index 701a353..a2ad16e 100644 --- a/tests/big_integer_test.cpp +++ b/tests/big_integer_test.cpp @@ -7,19 +7,19 @@ int main() { using bstl::BigInteger; - BigInteger a("12345678901234567890"); - BigInteger b("98765432109876543210"); - BigInteger c = a + b; - BigInteger d = b - a; - BigInteger e = a * BigInteger("2"); - BigInteger f = BigInteger("100000000000000000000000") / BigInteger("1000000000000000000"); + const BigInteger a("12345678901234567890"); + const BigInteger b("98765432109876543210"); + const BigInteger c = a + b; + const BigInteger d = b - a; + const BigInteger e = a * BigInteger("2"); + const BigInteger f = BigInteger("100000000000000000000000") / BigInteger("1000000000000000000"); assert(c.toString() == "111111111011111111100"); assert(d.toString() == "86419753208641975320"); assert(e.toString() == "24691357802469135780"); assert(f.toString() == "100000"); - BigInteger zero("0"); + const BigInteger zero("0"); assert((a == a) == true); assert((a != b) == true); assert((zero == 0) == true);