Compare commits

11 Commits
Author SHA256 Message Date
ArchZer0 ceb7c3fa44 stdio支持 2026-08-16 16:28:12 +08:00
ArchZer0 1f8fa26d73 best string 2026-08-16 16:04:27 +08:00
ArchZer0 b3ab9e9429 Merge branch 'main' into archzero_dev
merge main
2026-08-16 15:40:20 +08:00
ArchZer0 86191b5eb0 Fix some 2026-08-16 15:24:33 +08:00
ArchZer0 c145fa8d05 Merge branch 'main' into wcjbr_dev 2026-08-16 15:21:50 +08:00
CupWater feac230fef merge 2026-08-16 15:20:11 +08:00
ArchZer0 32a43f6161 fix some 2026-08-16 15:07:40 +08:00
CupWater 83a75d4e76 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	include/bstl/bstl.hpp
#	src/BigDecimal.cpp
#	src/BigInteger.cpp
2026-08-16 15:02:29 +08:00
CupWater fb2b24bc72 修改bstlint 2026-08-16 15:00:09 +08:00
ArchZer0 5828ec6f4b Merge branch 'main' of 192.168.50.182:ZeroOSProject/BetterSTL 2026-08-16 14:57:18 +08:00
ArchZer0 5b3320e65c Biginteger/decimal 2026-08-16 14:55:25 +08:00
20 changed files with 1807 additions and 10 deletions
+52 -3
View File
@@ -1,7 +1,56 @@
cmake_minimum_required(VERSION 3.10.0) cmake_minimum_required(VERSION 3.10.0)
project(BetterSTL VERSION 0.1.0 LANGUAGES C CXX) project(BetterSTL VERSION 0.1.0 LANGUAGES C CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(BetterSTL src/BigInteger.cpp # 定义源文件
src/BigDecimal.cpp) set(BETTERSTL_SOURCES
src/big_integer.cpp
src/big_decimal.cpp
src/string.cpp)
# 生成静态库 (.a 文件)
add_library(BetterSTL_static STATIC ${BETTERSTL_SOURCES})
target_include_directories(BetterSTL_static PUBLIC include)
set_target_properties(BetterSTL_static PROPERTIES
OUTPUT_NAME BetterSTL
PREFIX lib)
# 生成动态库 (.so 文件)
add_library(BetterSTL_shared SHARED ${BETTERSTL_SOURCES})
target_include_directories(BetterSTL_shared PUBLIC include)
set_target_properties(BetterSTL_shared PROPERTIES
OUTPUT_NAME BetterSTL
PREFIX lib)
# 默认链接到静态库
add_library(BetterSTL ALIAS BetterSTL_static)
enable_testing()
add_executable(BigIntegerTests tests/big_integer_test.cpp)
target_include_directories(BigIntegerTests PRIVATE include)
target_link_libraries(BigIntegerTests PRIVATE BetterSTL_static)
add_test(NAME BigIntegerTests COMMAND BigIntegerTests)
add_executable(BigDecimalTests tests/big_decimal_test.cpp)
target_include_directories(BigDecimalTests PRIVATE include)
target_link_libraries(BigDecimalTests PRIVATE BetterSTL_static)
add_test(NAME BigDecimalTests COMMAND BigDecimalTests)
add_executable(StringTests tests/StringTest.cpp)
target_include_directories(StringTests PRIVATE include)
target_link_libraries(StringTests PRIVATE BetterSTL_static)
add_test(NAME StringTests COMMAND StringTests)
add_executable(IOTests tests/IOTest.cpp)
target_include_directories(IOTests PRIVATE include)
target_link_libraries(IOTests PRIVATE BetterSTL_static)
add_test(NAME IOTests COMMAND IOTests)
# 生成导出信息用于外部使用
install(TARGETS BetterSTL_static BetterSTL_shared
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin)
install(DIRECTORY include/ DESTINATION include)
include_directories(include)
+91
View File
@@ -0,0 +1,91 @@
# BetterSTL cin/cout 支持
现在三个核心类都支持标准输入输出:
## BigInteger - 高精度整数
```cpp
#include <bstl/big_integer.hpp>
#include <iostream>
bstl::BigInteger bi;
std::cout << "Enter a large integer: ";
std::cin >> bi;
std::cout << "You entered: " << bi << std::endl;
```
支持任意精度的整数输入输出,不受 `long long` 限制。
## BigDecimal - 高精度浮点数
```cpp
#include <bstl/big_decimal.hpp>
#include <iostream>
bstl::BigDecimal bd;
std::cout << "Enter a decimal number: ";
std::cin >> bd;
std::cout << "You entered: " << bd << std::endl;
```
支持任意精度的浮点数输入输出,精度不丢失。
## String - 增强字符串
```cpp
#include <bstl/string.hpp>
#include <iostream>
bstl::String str;
std::cout << "Enter a word: ";
std::cin >> str;
std::cout << "You entered: " << str << std::endl;
// 可以使用 Python 风格的方法
std::cout << "Uppercase: " << str.upper() << std::endl;
std::cout << "Split: ";
auto parts = str.split("_");
```
## 使用示例
编译和运行演示程序:
```bash
cd /home/archzero/C++/BetterSTL
cmake -S . -B out/build -G Ninja
cmake --build out/build
# 运行库测试
ctest --test-dir out/build
# 运行演示(需要在终端交互)
./out/build/IOTests
```
## 实现细节
### operator<<(输出)
- BigInteger: 通过 `toString()` 输出
- BigDecimal: 通过 `toString()` 输出
- String: 通过 `str()` 输出
### operator>>(输入)
- BigInteger: 读取字符串,创建新对象
- BigDecimal: 读取字符串,创建新对象
- String: 读取字符串,创建新对象
所有运算符都定义在 `bstl` 命名空间中。
## 编译链接
在编译你的程序时:
```bash
g++ your_program.cpp -I/path/to/include -L/path/to/lib -lBetterSTL -o your_program
```
或者使用静态库:
```bash
g++ your_program.cpp -I/path/to/include /path/to/libBetterSTL.a -o your_program
```
+41
View File
@@ -0,0 +1,41 @@
#include <bstl/big_integer.hpp>
#include <bstl/big_decimal.hpp>
#include <bstl/string.hpp>
#include <iostream>
int main() {
using bstl::BigInteger;
using bstl::BigDecimal;
using bstl::String;
std::cout << "=== BetterSTL cin/cout Demo ===\n\n";
// BigInteger 示例
std::cout << "BigInteger Example:\n";
std::cout << "Enter a large integer: ";
BigInteger bi;
std::cin >> bi;
std::cout << "You entered: " << bi << "\n";
std::cout << "Doubled: " << (bi * BigInteger(2)) << "\n\n";
// BigDecimal 示例
std::cout << "BigDecimal Example:\n";
std::cout << "Enter a decimal number: ";
BigDecimal bd;
std::cin >> bd;
std::cout << "You entered: " << bd << "\n";
std::cout << "Doubled: " << (bd * BigDecimal(2)) << "\n\n";
// String 示例
std::cout << "String Example:\n";
std::cout << "Enter a word: ";
String str;
std::cin >> str;
std::cout << "You entered: " << str << "\n";
std::cout << "Uppercase: " << str.upper() << "\n";
std::cout << "Lowercase: " << str.lower() << "\n\n";
std::cout << "Demo completed!\n";
return 0;
}
Executable
BIN
View File
Binary file not shown.
-6
View File
@@ -1,6 +0,0 @@
#ifndef BETTERSTL_BSTL_HPP
#define BETTERSTL_BSTL_HPP
#include <bstlint.hpp>
#endif //BETTERSTL_BSTL_HPP
+79
View File
@@ -0,0 +1,79 @@
#ifndef BETTERSTL_BIG_DECIMAL_H
#define BETTERSTL_BIG_DECIMAL_H
#include <string>
#include <iostream>
#include <bstl/big_integer.hpp>
namespace bstl {
class BigDecimal {
public:
BigDecimal();
BigDecimal(int value);
BigDecimal(long long value);
BigDecimal(double value);
explicit BigDecimal(const std::string& value);
explicit BigDecimal(const char* value);
BigDecimal(const BigInteger& unscaledValue, int scale);
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;
// Comparison operators
bool operator==(const BigDecimal& other) const;
bool operator!=(const BigDecimal& other) const;
bool operator<(const BigDecimal& other) const;
bool operator>(const BigDecimal& other) const;
bool operator<=(const BigDecimal& other) const;
bool operator>=(const BigDecimal& other) const;
bool operator==(int value) const;
bool operator!=(int value) const;
bool operator<(int value) const;
bool operator>(int value) const;
bool operator<=(int value) const;
bool operator>=(int value) const;
bool operator==(double value) const;
bool operator!=(double value) const;
bool operator<(double value) const;
bool operator>(double value) const;
bool operator<=(double value) const;
bool operator>=(double value) const;
// Arithmetic operators
BigDecimal operator+() const;
BigDecimal operator-() const;
BigDecimal& operator+=(const BigDecimal& other);
BigDecimal& operator-=(const BigDecimal& other);
BigDecimal& operator*=(const BigDecimal& other);
BigDecimal& operator/=(const BigDecimal& other);
BigDecimal operator+(const BigDecimal& other) const;
BigDecimal operator-(const BigDecimal& other) const;
BigDecimal operator*(const BigDecimal& other) const;
BigDecimal operator/(const BigDecimal& other) const;
BigDecimal abs() const;
BigDecimal round(int scale) const;
private:
BigInteger unscaledValue_; // 去掉小数点后的值
int scale_; // 小数点后的位数
static void alignScale(BigInteger& lhs, int& lhsScale,
BigInteger& rhs, int& rhsScale);
};
// 流运算符重载
std::ostream& operator<<(std::ostream& os, const BigDecimal& bd);
std::istream& operator>>(std::istream& is, BigDecimal& bd);
} // namespace bstl
#endif //BETTERSTL_BIG_DECIMAL_H
+75
View File
@@ -0,0 +1,75 @@
#ifndef BETTERSTL_BIG_INTEGER_HPP
#define BETTERSTL_BIG_INTEGER_HPP
#include <string>
#include <iostream>
namespace bstl {
class BigInteger {
public:
BigInteger();
BigInteger(int value);
BigInteger(long long value);
BigInteger(unsigned long long value);
explicit BigInteger(const std::string& value);
explicit BigInteger(const char* value);
BigInteger(const BigInteger& other) = default;
BigInteger& operator=(const BigInteger& other) = default;
bool isZero() const;
int sign() const;
std::string toString() const;
bool operator==(const BigInteger& other) const;
bool operator!=(const BigInteger& other) const;
bool operator<(const BigInteger& other) const;
bool operator>(const BigInteger& other) const;
bool operator<=(const BigInteger& other) const;
bool operator>=(const BigInteger& other) const;
bool operator==(int value) const;
bool operator!=(int value) const;
bool operator<(int value) const;
bool operator>(int value) const;
bool operator<=(int value) const;
bool operator>=(int value) const;
bool operator==(long long value) const;
bool operator!=(long long value) const;
bool operator<(long long value) const;
bool operator>(long long value) const;
bool operator<=(long long value) const;
bool operator>=(long long value) const;
BigInteger operator+() const;
BigInteger operator-() const;
BigInteger& operator+=(const BigInteger& other);
BigInteger& operator-=(const BigInteger& other);
BigInteger& operator*=(const BigInteger& other);
BigInteger& operator/=(const BigInteger& other);
BigInteger operator+(const BigInteger& other) const;
BigInteger operator-(const BigInteger& other) const;
BigInteger operator*(const BigInteger& other) const;
BigInteger operator/(const BigInteger& other) const;
private:
std::string digits_; // 无符号数字,从高位到低位
int 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 divAbs(const std::string& a, const std::string& b);
};
// 流运算符重载
std::ostream& operator<<(std::ostream& os, const BigInteger& bi);
std::istream& operator>>(std::istream& is, BigInteger& bi);
} // namespace bstl
#endif //BETTERSTL_BIG_INTEGER_HPP
+7
View File
@@ -0,0 +1,7 @@
#ifndef BETTERSTL_BIG_NUMBERS_HPP
#define BETTERSTL_BIG_NUMBERS_HPP
#include <bstl/big_integer.hpp>
#include <bstl/big_decimal.hpp>
#endif // BETTERSTL_BIG_NUMBERS_HPP
+8
View File
@@ -0,0 +1,8 @@
#ifndef BETTERSTL_BSTL_HPP
#include<bstl/big_decimal.hpp>
#include<bstl/big_integer.hpp>
#include <bstl/bstlint.hpp>
#define BETTERSTL_BSTL_HPP
#endif //BETTERSTL_BSTL_HPP
@@ -2,7 +2,6 @@
#define BETTERSTL_BSTLINT_HPP #define BETTERSTL_BSTLINT_HPP
#include <cstdint> #include <cstdint>
#include <>
typedef std::int8_t i8; typedef std::int8_t i8;
typedef std::int16_t i16; typedef std::int16_t i16;
+97
View File
@@ -0,0 +1,97 @@
#pragma once
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <iostream>
namespace bstl {
class String {
public:
String();
String(const 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;
// 获取/修改字符
char at(size_t pos) const;
char operator[](size_t pos) const;
char& operator[](size_t pos);
// 分割 - 按分隔符分割字符串
std::vector<String> split(const String& delimiter = " ") const;
// 连接 - 用分隔符连接多个字符串
static String join(const std::vector<String>& parts, const String& delimiter = "");
// 替换 - 替换第一个/所有匹配项
String replace(const String& oldStr, const String& newStr, int count = -1) const;
// 大小写转换
String upper() const;
String lower() const;
String capitalize() const; // 首字母大写
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;
// 查找和计数
int find(const String& substring, size_t start = 0) const;
int rfind(const String& substring) const; // 从后往前查找
int count(const String& substring) const;
// 去除空格和其他字符
String strip() const; // 去除前后空格
String lstrip() const; // 去除前导空格
String rstrip() const; // 去除尾部空格
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;
// 字符串转换
int toInt() const;
long long toLongLong() const;
double toDouble() const;
// 运算符重载
String operator+(const String& other) const;
String operator+(const char* str) const;
String& operator+=(const String& other);
bool operator==(const String& other) const;
bool operator!=(const String& other) const;
bool operator<(const String& other) const;
bool operator>(const String& other) const;
bool operator<=(const String& other) const;
bool operator>=(const String& other) const;
private:
std::string data_;
};
// 流运算符重载
std::ostream& operator<<(std::ostream& os, const String& str);
std::istream& operator>>(std::istream& is, String& str);
} // namespace bstl
View File
View File
+352
View File
@@ -0,0 +1,352 @@
#include <bstl/big_decimal.hpp>
#include <stdexcept>
#include <sstream>
#include <cmath>
namespace bstl {
BigDecimal::BigDecimal() : unscaledValue_(0), scale_(0) {}
BigDecimal::BigDecimal(int value) : unscaledValue_(value), scale_(0) {}
BigDecimal::BigDecimal(long long value) : unscaledValue_(value), scale_(0) {}
BigDecimal::BigDecimal(double value) : scale_(0) {
if (value == 0.0) {
unscaledValue_ = 0;
scale_ = 0;
return;
}
// 将浮点数转换为字符串,然后解析
std::ostringstream oss;
oss.precision(15);
oss << value;
*this = BigDecimal(oss.str());
}
BigDecimal::BigDecimal(const std::string& value) : unscaledValue_(0), scale_(0) {
if (value.empty()) {
return;
}
std::string text = value;
// 去掉前后空格
size_t start = 0, end = text.size();
while (start < end && text[start] == ' ') start++;
while (end > start && text[end - 1] == ' ') end--;
text = text.substr(start, end - start);
if (text.empty()) {
return;
}
// 查找小数点位置
size_t dotPos = text.find('.');
if (dotPos != std::string::npos) {
scale_ = text.size() - dotPos - 1;
std::string digits = text.substr(0, dotPos) + text.substr(dotPos + 1);
unscaledValue_ = BigInteger(digits);
} else {
scale_ = 0;
unscaledValue_ = BigInteger(text);
}
}
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) {
if (scale < 0) {
throw std::invalid_argument("scale cannot be negative");
}
}
bool BigDecimal::isZero() const {
return unscaledValue_.isZero();
}
int BigDecimal::sign() const {
return unscaledValue_.sign();
}
int BigDecimal::getScale() const {
return scale_;
}
BigInteger BigDecimal::getUnscaledValue() const {
return unscaledValue_;
}
std::string BigDecimal::toString() const {
if (isZero()) {
return "0";
}
std::string digitStr = unscaledValue_.toString();
// 处理符号
bool negative = false;
if (digitStr[0] == '-') {
negative = true;
digitStr = digitStr.substr(1);
}
// 插入小数点
if (scale_ == 0) {
return (negative ? "-" : "") + digitStr;
}
if (static_cast<int>(digitStr.size()) <= scale_) {
// 需要前置 "0."
std::string result = "0.";
for (int i = 0; i < scale_ - static_cast<int>(digitStr.size()); i++) {
result += "0";
}
result += digitStr;
return (negative ? "-" : "") + result;
}
int dotPos = digitStr.size() - scale_;
std::string result = digitStr.substr(0, dotPos) + "." + digitStr.substr(dotPos);
return (negative ? "-" : "") + result;
}
void BigDecimal::alignScale(BigInteger& lhs, int& lhsScale,
BigInteger& rhs, int& rhsScale) {
if (lhsScale < rhsScale) {
// 左边需要扩大
for (int i = 0; i < rhsScale - lhsScale; i++) {
lhs = lhs * BigInteger(10);
}
lhsScale = rhsScale;
} else if (lhsScale > rhsScale) {
// 右边需要扩大
for (int i = 0; i < lhsScale - rhsScale; i++) {
rhs = rhs * BigInteger(10);
}
rhsScale = 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);
return lhs == rhs;
}
bool BigDecimal::operator!=(const BigDecimal& other) const {
return !(*this == other);
}
bool BigDecimal::operator<(const BigDecimal& other) const {
if (unscaledValue_.sign() != other.unscaledValue_.sign()) {
return unscaledValue_.sign() < other.unscaledValue_.sign();
}
BigInteger lhs = unscaledValue_;
BigInteger rhs = other.unscaledValue_;
int lhsScale = scale_;
int rhsScale = other.scale_;
alignScale(lhs, lhsScale, rhs, rhsScale);
if (unscaledValue_.sign() >= 0) {
return lhs < rhs;
} else {
return lhs > rhs;
}
}
bool BigDecimal::operator>(const BigDecimal& other) const {
return other < *this;
}
bool BigDecimal::operator<=(const BigDecimal& other) const {
return *this < other || *this == other;
}
bool BigDecimal::operator>=(const BigDecimal& other) const {
return other <= *this;
}
bool BigDecimal::operator==(int value) const {
return *this == BigDecimal(value);
}
bool BigDecimal::operator!=(int value) const {
return !(*this == value);
}
bool BigDecimal::operator<(int value) const {
return *this < BigDecimal(value);
}
bool BigDecimal::operator>(int value) const {
return *this > BigDecimal(value);
}
bool BigDecimal::operator<=(int value) const {
return *this <= BigDecimal(value);
}
bool BigDecimal::operator>=(int value) const {
return *this >= BigDecimal(value);
}
bool BigDecimal::operator==(double value) const {
return *this == BigDecimal(value);
}
bool BigDecimal::operator!=(double value) const {
return !(*this == value);
}
bool BigDecimal::operator<(double value) const {
return *this < BigDecimal(value);
}
bool BigDecimal::operator>(double value) const {
return *this > BigDecimal(value);
}
bool BigDecimal::operator<=(double value) const {
return *this <= BigDecimal(value);
}
bool BigDecimal::operator>=(double value) const {
return *this >= BigDecimal(value);
}
BigDecimal BigDecimal::operator+() const {
return *this;
}
BigDecimal BigDecimal::operator-() const {
if (isZero()) {
return BigDecimal(0);
}
return BigDecimal(-unscaledValue_, scale_);
}
BigDecimal& BigDecimal::operator+=(const BigDecimal& other) {
*this = *this + other;
return *this;
}
BigDecimal& BigDecimal::operator-=(const BigDecimal& other) {
*this = *this - other;
return *this;
}
BigDecimal& BigDecimal::operator*=(const BigDecimal& other) {
*this = *this * other;
return *this;
}
BigDecimal& BigDecimal::operator/=(const BigDecimal& other) {
*this = *this / other;
return *this;
}
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);
return BigDecimal(lhs + rhs, lhsScale);
}
BigDecimal BigDecimal::operator-(const BigDecimal& other) const {
return *this + (-other);
}
BigDecimal BigDecimal::operator*(const BigDecimal& other) const {
if (isZero() || other.isZero()) {
return BigDecimal(0);
}
BigInteger result = unscaledValue_ * other.unscaledValue_;
int resultScale = scale_ + other.scale_;
return BigDecimal(result, resultScale);
}
BigDecimal BigDecimal::operator/(const BigDecimal& other) const {
if (other.isZero()) {
throw std::invalid_argument("division by zero");
}
if (isZero()) {
return BigDecimal(0);
}
// 先对齐 scale,然后做整数除法
BigInteger lhs = unscaledValue_;
BigInteger rhs = other.unscaledValue_;
int lhsScale = scale_;
int rhsScale = other.scale_;
// 使用更高的精度进行除法
// 乘以 10^precision 来获得更多的精度
int precision = 10;
for (int i = 0; i < precision; i++) {
lhs = lhs * BigInteger(10);
}
BigInteger quotient = lhs / rhs;
int resultScale = lhsScale - rhsScale + precision;
return BigDecimal(quotient, resultScale);
}
BigDecimal BigDecimal::abs() const {
if (unscaledValue_.sign() >= 0) {
return *this;
}
return BigDecimal(-unscaledValue_, scale_);
}
BigDecimal BigDecimal::round(int scale) const {
if (scale < 0) {
throw std::invalid_argument("scale cannot be negative");
}
if (scale >= scale_) {
return *this;
}
// 简单实现:直接截断到指定小数位数
int diff = 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);
}
std::ostream& operator<<(std::ostream& os, const BigDecimal& bd) {
return os << bd.toString();
}
std::istream& operator>>(std::istream& is, BigDecimal& bd) {
std::string str;
is >> str;
bd = BigDecimal(str);
return is;
}
} // namespace bstl
+389
View File
@@ -0,0 +1,389 @@
#include <bstl/big_integer.hpp>
#include <algorithm>
#include <stdexcept>
#include <string>
#include <vector>
namespace bstl {
std::string BigInteger::trimLeadingZeros(const std::string& value) {
size_t pos = 0;
while (pos < value.size() - 1 && value[pos] == '0') {
pos++;
}
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);
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 result;
int carry = 0;
int i = static_cast<int>(a.size()) - 1;
int j = static_cast<int>(b.size()) - 1;
while (i >= 0 || j >= 0 || carry) {
int sum = carry;
if (i >= 0) sum += a[i--] - '0';
if (j >= 0) sum += b[j--] - '0';
result = char('0' + sum % 10) + result;
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 result;
int borrow = 0;
int i = static_cast<int>(ta.size()) - 1;
int j = static_cast<int>(tb.size()) - 1;
while (i >= 0) {
int diff = (ta[i--] - '0') - borrow;
if (j >= 0) {
diff -= (tb[j--] - '0');
}
if (diff < 0) {
diff += 10;
borrow = 1;
} else {
borrow = 0;
}
result = char('0' + diff) + result;
}
return trimLeadingZeros(result);
}
std::string BigInteger::mulAbs(const std::string& a, const std::string& b) {
std::string ta = trimLeadingZeros(a);
std::string tb = trimLeadingZeros(b);
if (ta == "0" || tb == "0") return "0";
std::vector<int> product(ta.size() + tb.size(), 0);
for (size_t i = 0; i < ta.size(); i++) {
for (size_t j = 0; j < tb.size(); j++) {
int mul = (ta[ta.size() - 1 - i] - '0') * (tb[tb.size() - 1 - j] - '0');
product[i + j] += mul;
}
}
int carry = 0;
for (size_t i = 0; i < product.size(); i++) {
int sum = product[i] + carry;
product[i] = sum % 10;
carry = sum / 10;
}
std::string result;
for (int i = static_cast<int>(product.size()) - 1; i >= 0; i--) {
result += char('0' + product[i]);
}
return trimLeadingZeros(result);
}
std::string BigInteger::divAbs(const std::string& a, const std::string& b) {
std::string tb = trimLeadingZeros(b);
if (tb == "0") {
throw std::invalid_argument("division by zero");
}
std::string ta = trimLeadingZeros(a);
if (compareAbs(ta, tb) < 0) {
return "0";
}
std::string quotient;
std::string current;
for (char digit : ta) {
current += digit;
current = trimLeadingZeros(current);
int count = 0;
while (compareAbs(current, tb) >= 0) {
current = subAbs(current, tb);
count++;
}
quotient += char('0' + count);
}
return trimLeadingZeros(quotient);
}
BigInteger::BigInteger() : digits_("0"), sign_(0) {}
BigInteger::BigInteger(int value) : digits_("0"), sign_(1) {
if (value == 0) {
digits_ = "0";
sign_ = 0;
return;
}
if (value < 0) {
sign_ = -1;
value = -value;
}
digits_.clear();
while (value > 0) {
digits_ = char('0' + value % 10) + digits_;
value /= 10;
}
}
BigInteger::BigInteger(long long value) : digits_("0"), sign_(1) {
if (value == 0) {
digits_ = "0";
sign_ = 0;
return;
}
if (value < 0) {
sign_ = -1;
value = -value;
}
digits_.clear();
while (value > 0) {
digits_ = char('0' + value % 10) + digits_;
value /= 10;
}
}
BigInteger::BigInteger(unsigned long long value) : digits_("0"), sign_(1) {
if (value == 0) {
digits_ = "0";
sign_ = 0;
return;
}
digits_.clear();
while (value > 0) {
digits_ = char('0' + value % 10) + digits_;
value /= 10;
}
}
BigInteger::BigInteger(const std::string& value) : digits_("0"), sign_(1) {
if (value.empty()) {
digits_ = "0";
sign_ = 0;
return;
}
std::string text = value;
sign_ = 1;
if (text[0] == '-') {
sign_ = -1;
text = text.substr(1);
} else if (text[0] == '+') {
text = text.substr(1);
}
if (text.empty()) {
digits_ = "0";
sign_ = 0;
return;
}
for (char ch : text) {
if (ch < '0' || ch > '9') {
throw std::invalid_argument("BigInteger: invalid numeric string");
}
}
digits_ = trimLeadingZeros(text);
if (digits_ == "0") {
sign_ = 0;
}
}
BigInteger::BigInteger(const char* value)
: BigInteger(value == nullptr ? std::string("0") : std::string(value)) {}
bool BigInteger::isZero() const {
return sign_ == 0 || digits_ == "0";
}
int BigInteger::sign() const {
return isZero() ? 0 : sign_;
}
std::string BigInteger::toString() const {
if (isZero()) return "0";
return (sign_ < 0 ? "-" : "") + digits_;
}
bool BigInteger::operator==(const BigInteger& other) const {
if (isZero() && other.isZero()) return true;
return sign_ == other.sign_ && digits_ == other.digits_;
}
bool BigInteger::operator!=(const BigInteger& other) const {
return !(*this == other);
}
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;
}
bool BigInteger::operator>(const BigInteger& other) const {
return other < *this;
}
bool BigInteger::operator<=(const BigInteger& other) const {
return *this < other || *this == other;
}
bool BigInteger::operator>=(const BigInteger& other) const {
return other <= *this;
}
bool BigInteger::operator==(int value) const {
return *this == BigInteger(value);
}
bool BigInteger::operator!=(int value) const {
return !(*this == value);
}
bool BigInteger::operator<(int value) const {
return *this < BigInteger(value);
}
bool BigInteger::operator>(int value) const {
return *this > BigInteger(value);
}
bool BigInteger::operator<=(int value) const {
return *this <= BigInteger(value);
}
bool BigInteger::operator>=(int value) const {
return *this >= BigInteger(value);
}
bool BigInteger::operator==(long long value) const {
return *this == BigInteger(value);
}
bool BigInteger::operator!=(long long value) const {
return !(*this == value);
}
bool BigInteger::operator<(long long value) const {
return *this < BigInteger(value);
}
bool BigInteger::operator>(long long value) const {
return *this > BigInteger(value);
}
bool BigInteger::operator<=(long long value) const {
return *this <= BigInteger(value);
}
bool BigInteger::operator>=(long long value) const {
return *this >= BigInteger(value);
}
BigInteger BigInteger::operator+() const {
return *this;
}
BigInteger BigInteger::operator-() const {
if (isZero()) return BigInteger(0);
BigInteger result(*this);
result.sign_ = -result.sign_;
return result;
}
BigInteger& BigInteger::operator+=(const BigInteger& other) {
*this = *this + other;
return *this;
}
BigInteger& BigInteger::operator-=(const BigInteger& other) {
*this = *this - other;
return *this;
}
BigInteger& BigInteger::operator*=(const BigInteger& other) {
*this = *this * other;
return *this;
}
BigInteger& BigInteger::operator/=(const BigInteger& other) {
*this = *this / other;
return *this;
}
BigInteger BigInteger::operator+(const BigInteger& other) const {
if (isZero()) return other;
if (other.isZero()) return *this;
BigInteger result;
if (sign_ == other.sign_) {
result.digits_ = addAbs(digits_, other.digits_);
result.sign_ = sign_;
} else {
int cmp = compareAbs(digits_, other.digits_);
if (cmp == 0) {
result.digits_ = "0";
result.sign_ = 0;
} else if (cmp > 0) {
result.digits_ = subAbs(digits_, other.digits_);
result.sign_ = sign_;
} else {
result.digits_ = subAbs(other.digits_, digits_);
result.sign_ = other.sign_;
}
}
if (result.digits_ == "0") result.sign_ = 0;
return result;
}
BigInteger BigInteger::operator-(const BigInteger& other) const {
return *this + (-other);
}
BigInteger BigInteger::operator*(const BigInteger& other) const {
if (isZero() || other.isZero()) return BigInteger(0);
BigInteger result;
result.digits_ = mulAbs(digits_, other.digits_);
result.sign_ = (sign_ * other.sign_);
if (result.digits_ == "0") result.sign_ = 0;
return result;
}
BigInteger BigInteger::operator/(const BigInteger& other) const {
if (other.isZero()) {
throw std::invalid_argument("division by zero");
}
if (isZero()) return BigInteger(0);
BigInteger result;
result.digits_ = divAbs(digits_, other.digits_);
result.sign_ = (sign_ * other.sign_);
if (result.digits_ == "0") result.sign_ = 0;
return result;
}
std::ostream& operator<<(std::ostream& os, const BigInteger& bi) {
return os << bi.toString();
}
std::istream& operator>>(std::istream& is, BigInteger& bi) {
std::string str;
is >> str;
bi = BigInteger(str);
return is;
}
} // namespace bstl
+373
View File
@@ -0,0 +1,373 @@
#include "bstl/string.hpp"
#include <sstream>
#include <stdexcept>
namespace bstl {
String::String() : data_("") {}
String::String(const std::string& str) : data_(str) {}
String::String(const char* str) : data_(str == nullptr ? "" : str) {}
std::string String::str() const {
return data_;
}
const char* String::c_str() const {
return data_.c_str();
}
size_t String::length() const {
return data_.length();
}
size_t String::size() const {
return data_.size();
}
bool String::empty() const {
return data_.empty();
}
char String::at(size_t pos) const {
if (pos >= data_.size()) {
throw std::out_of_range("String::at: index out of range");
}
return data_[pos];
}
char String::operator[](size_t pos) const {
return data_[pos];
}
char& String::operator[](size_t pos) {
return data_[pos];
}
std::vector<String> String::split(const String& delimiter) const {
std::vector<String> result;
if (data_.empty()) {
return result;
}
if (delimiter.empty()) {
result.push_back(*this);
return result;
}
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)));
start = pos + delimiter.size();
}
result.push_back(String(data_.substr(start)));
return result;
}
String String::join(const std::vector<String>& parts, const String& delimiter) {
if (parts.empty()) {
return String("");
}
std::string result = parts[0].str();
for (size_t i = 1; i < parts.size(); i++) {
result += delimiter.str() + parts[i].str();
}
return String(result);
}
String String::replace(const String& oldStr, const String& newStr, int count) const {
if (oldStr.empty()) {
return *this;
}
std::string result = data_;
size_t pos = 0;
int replaced = 0;
while ((pos = result.find(oldStr.data_, pos)) != std::string::npos && (count < 0 || replaced < count)) {
result.replace(pos, oldStr.size(), newStr.str());
pos += newStr.size();
replaced++;
}
return String(result);
}
String String::upper() const {
std::string result = data_;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::toupper(c); });
return String(result);
}
String String::lower() const {
std::string result = data_;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return String(result);
}
String String::capitalize() const {
if (data_.empty()) {
return *this;
}
std::string result = data_;
result[0] = std::toupper(static_cast<unsigned char>(result[0]));
for (size_t i = 1; i < result.size(); i++) {
result[i] = std::tolower(static_cast<unsigned char>(result[i]));
}
return String(result);
}
String String::title() const {
std::string result = data_;
bool newWord = true;
for (size_t i = 0; i < result.size(); i++) {
if (std::isspace(static_cast<unsigned char>(result[i]))) {
newWord = true;
} else {
if (newWord) {
result[i] = std::toupper(static_cast<unsigned char>(result[i]));
newWord = false;
} else {
result[i] = std::tolower(static_cast<unsigned char>(result[i]));
}
}
}
return String(result);
}
bool String::startswith(const String& prefix) const {
if (prefix.size() > data_.size()) {
return false;
}
return data_.compare(0, prefix.size(), prefix.data_) == 0;
}
bool String::endswith(const String& suffix) const {
if (suffix.size() > data_.size()) {
return false;
}
return data_.compare(data_.size() - suffix.size(), suffix.size(), suffix.data_) == 0;
}
bool String::contains(const String& substring) const {
return data_.find(substring.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;
}
bool String::isalpha() const {
if (data_.empty()) return false;
for (unsigned char c : data_) {
if (!std::isalpha(c)) return false;
}
return true;
}
bool String::isalnum() const {
if (data_.empty()) return false;
for (unsigned char c : data_) {
if (!std::isalnum(c)) return false;
}
return true;
}
bool String::isspace() const {
if (data_.empty()) return false;
for (unsigned char c : data_) {
if (!std::isspace(c)) return false;
}
return true;
}
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;
}
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;
}
int String::find(const String& substring, size_t start) const {
size_t pos = data_.find(substring.data_, start);
return pos == std::string::npos ? -1 : static_cast<int>(pos);
}
int String::rfind(const String& substring) const {
size_t pos = data_.rfind(substring.data_);
return pos == std::string::npos ? -1 : static_cast<int>(pos);
}
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) {
count++;
pos += substring.size();
}
return count;
}
String String::strip() const {
size_t start = 0;
size_t end = data_.size();
while (start < end && std::isspace(static_cast<unsigned char>(data_[start]))) {
start++;
}
while (end > start && std::isspace(static_cast<unsigned char>(data_[end - 1]))) {
end--;
}
return String(data_.substr(start, end - start));
}
String String::lstrip() const {
size_t start = 0;
while (start < data_.size() && std::isspace(static_cast<unsigned char>(data_[start]))) {
start++;
}
return String(data_.substr(start));
}
String String::rstrip() const {
size_t end = data_.size();
while (end > 0 && std::isspace(static_cast<unsigned char>(data_[end - 1]))) {
end--;
}
return String(data_.substr(0, end));
}
String String::strip(const String& chars) const {
size_t start = 0;
size_t end = data_.size();
while (start < end && chars.data_.find(data_[start]) != std::string::npos) {
start++;
}
while (end > start && chars.data_.find(data_[end - 1]) != std::string::npos) {
end--;
}
return String(data_.substr(start, end - start));
}
String String::ljust(size_t width, char fillchar) const {
if (data_.size() >= width) {
return *this;
}
std::string result = data_;
result.append(width - data_.size(), fillchar);
return String(result);
}
String String::rjust(size_t width, char fillchar) const {
if (data_.size() >= width) {
return *this;
}
std::string result(width - data_.size(), fillchar);
result.append(data_);
return String(result);
}
String String::center(size_t width, char fillchar) const {
if (data_.size() >= width) {
return *this;
}
size_t totalPad = width - data_.size();
size_t leftPad = totalPad / 2;
size_t rightPad = totalPad - leftPad;
std::string result(leftPad, fillchar);
result.append(data_);
result.append(rightPad, fillchar);
return String(result);
}
int String::toInt() const {
return std::stoi(data_);
}
long long String::toLongLong() const {
return std::stoll(data_);
}
double String::toDouble() const {
return std::stod(data_);
}
String String::operator+(const String& other) const {
return String(data_ + other.data_);
}
String String::operator+(const char* str) const {
return String(data_ + (str == nullptr ? "" : str));
}
String& String::operator+=(const String& other) {
data_ += other.data_;
return *this;
}
bool String::operator==(const String& other) const {
return data_ == other.data_;
}
bool String::operator!=(const String& other) const {
return data_ != other.data_;
}
bool String::operator<(const String& other) const {
return data_ < other.data_;
}
bool String::operator>(const String& other) const {
return data_ > other.data_;
}
bool String::operator<=(const String& other) const {
return data_ <= other.data_;
}
bool String::operator>=(const String& other) const {
return data_ >= other.data_;
}
std::ostream& operator<<(std::ostream& os, const String& str) {
return os << str.str();
}
std::istream& operator>>(std::istream& is, String& str) {
std::string temp;
is >> temp;
str = String(temp);
return is;
}
} // namespace bstl
+64
View File
@@ -0,0 +1,64 @@
#include <bstl/big_integer.hpp>
#include <bstl/big_decimal.hpp>
#include <bstl/string.hpp>
#include <sstream>
#include <cassert>
#include <iostream>
int main() {
using bstl::BigInteger;
using bstl::BigDecimal;
using bstl::String;
// 测试 BigInteger 的 cout
BigInteger bi1("12345678901234567890");
std::ostringstream oss1;
oss1 << bi1;
assert(oss1.str() == "12345678901234567890");
// 测试 BigInteger 的 cin
std::istringstream iss1("987654321");
BigInteger bi2;
iss1 >> bi2;
assert(bi2.toString() == "987654321");
// 测试负数
std::istringstream iss2("-555");
BigInteger bi3;
iss2 >> bi3;
assert(bi3.toString() == "-555");
// 测试 BigDecimal 的 cout
BigDecimal bd1("123.45");
std::ostringstream oss2;
oss2 << bd1;
assert(oss2.str() == "123.45");
// 测试 BigDecimal 的 cin
std::istringstream iss3("67.89");
BigDecimal bd2;
iss3 >> bd2;
assert(bd2.toString() == "67.89");
// 测试负小数
std::istringstream iss4("-12.34");
BigDecimal bd3;
iss4 >> bd3;
assert(bd3.toString() == "-12.34");
// 测试 String 的 cout
String s1("Hello World");
std::ostringstream oss3;
oss3 << s1;
assert(oss3.str() == "Hello World");
// 测试 String 的 cin
std::istringstream iss5("HelloWorld");
String s2;
iss5 >> s2;
assert(s2.str() == "HelloWorld");
std::cout << "All cin/cout tests passed!\n";
return 0;
}
+107
View File
@@ -0,0 +1,107 @@
#include <bstl/string.hpp>
#include <cassert>
#include <iostream>
int main() {
using bstl::String;
// 基本构造和获取
String s1("Hello, World!");
assert(s1.length() == 13);
assert(s1.c_str() == std::string("Hello, World!"));
// split 分割
String s2("apple,banana,cherry");
auto parts = s2.split(",");
assert(parts.size() == 3);
assert(parts[0] == String("apple"));
assert(parts[1] == String("banana"));
assert(parts[2] == String("cherry"));
// join 连接
std::vector<String> words = {String("Hello"), String("World")};
String joined = String::join(words, " ");
assert(joined == String("Hello World"));
// replace 替换
String s3("hello hello world");
String replaced = s3.replace("hello", "hi");
assert(replaced == String("hi hi world"));
String replaced1 = s3.replace("hello", "hi", 1);
assert(replaced1 == String("hi hello world"));
// upper/lower
String s4("HeLLo WoRLd");
assert(s4.upper() == String("HELLO WORLD"));
assert(s4.lower() == String("hello world"));
// capitalize
String s5("hello");
assert(s5.capitalize() == String("Hello"));
// title
String s6("hello world");
assert(s6.title() == String("Hello World"));
// startswith/endswith
String s7("hello.txt");
assert(s7.startswith("hello"));
assert(s7.endswith(".txt"));
assert(!s7.startswith(".txt"));
// contains
assert(s7.contains("llo"));
assert(!s7.contains("xyz"));
// isdigit/isalpha/isalnum
assert(String("12345").isdigit());
assert(!String("123a").isdigit());
assert(String("abc").isalpha());
assert(!String("abc1").isalpha());
assert(String("abc123").isalnum());
// isupper/islower
assert(String("HELLO").isupper());
assert(String("hello").islower());
assert(!String("Hello").isupper());
// find/rfind/count
assert(s2.find("banana") == 6);
assert(s2.find("xyz") == -1);
assert(s3.count("hello") == 2);
// strip
String s8(" hello world ");
assert(s8.strip() == String("hello world"));
assert(s8.lstrip() == String("hello world "));
assert(s8.rstrip() == String(" hello world"));
// ljust/rjust/center
String s9("hi");
assert(s9.ljust(5, '.') == String("hi..."));
assert(s9.rjust(5, '.') == String("...hi"));
assert(s9.center(5, '.') == String(".hi.."));
// 字符串转换
assert(String("123").toInt() == 123);
assert(String("456789").toLongLong() == 456789);
assert(String("3.14").toDouble() == 3.14);
// 运算符
String sa("Hello");
String sb(" World");
String sc = sa + sb;
assert(sc == String("Hello World"));
sa += sb;
assert(sa == String("Hello World"));
// 比较
assert(String("abc") < String("def"));
assert(String("xyz") > String("abc"));
std::cout << "All String tests passed!\n";
return 0;
}
+41
View File
@@ -0,0 +1,41 @@
#include <bstl/big_decimal.hpp>
#include <cassert>
#include <iostream>
#include <string>
int main() {
using bstl::BigDecimal;
// 基本构造
BigDecimal a("123.45");
BigDecimal b("67.89");
BigDecimal c = a + b;
assert(c.toString() == "191.34");
// 减法
BigDecimal d = a - b;
assert(d.toString() == "55.56");
// 乘法
BigDecimal e = a * BigDecimal("2");
assert(e.toString() == "246.90");
// 比较
assert((a > b) == true);
assert((a == a) == true);
assert((a != b) == true);
// 零
BigDecimal zero("0.0");
assert(zero.isZero());
// 负数
BigDecimal neg("-100.50");
assert(neg.sign() < 0);
assert((-neg).toString() == "100.50");
std::cout << "BigDecimal tests passed\n";
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
#include <bstl/big_integer.hpp>
#include <cassert>
#include <iostream>
#include <string>
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");
assert(c.toString() == "111111111011111111100");
assert(d.toString() == "86419753208641975320");
assert(e.toString() == "24691357802469135780");
assert(f.toString() == "100000");
BigInteger zero("0");
assert((a == a) == true);
assert((a != b) == true);
assert((zero == 0) == true);
assert((a > BigInteger("12345678901234567889")) == true);
assert((a < b) == true);
std::cout << "BigInteger tests passed\n";
return 0;
}