From 32a43f6161e2d7181113ae27f6f12ecff0860387883aefe2039a1c37c6853b81 Mon Sep 17 00:00:00 2001 From: ArchZer0 Date: Sun, 16 Aug 2026 15:07:40 +0800 Subject: [PATCH 1/3] fix some --- include/bstlint.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/bstlint.hpp b/include/bstlint.hpp index 57cc816..dac9ddd 100644 --- a/include/bstlint.hpp +++ b/include/bstlint.hpp @@ -2,7 +2,6 @@ #define BETTERSTL_BSTLINT_HPP #include -#include <> typedef std::int8_t i8; typedef std::int16_t i16; From 1f8fa26d73fbfe1b5dac38a247015363c05b158600ede9a37c2789b0f338e508 Mon Sep 17 00:00:00 2001 From: ArchZer0 Date: Sun, 16 Aug 2026 16:04:27 +0800 Subject: [PATCH 2/3] best string --- CMakeLists.txt | 8 +- include/bstl/string.hpp | 92 ++++++++++ src/string.cpp | 362 ++++++++++++++++++++++++++++++++++++++++ tests/StringTest.cpp | 107 ++++++++++++ 4 files changed, 568 insertions(+), 1 deletion(-) create mode 100644 include/bstl/string.hpp create mode 100644 src/string.cpp create mode 100644 tests/StringTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 057169b..fa21fe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,8 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 定义源文件 set(BETTERSTL_SOURCES src/big_integer.cpp - src/big_decimal.cpp) + src/big_decimal.cpp + src/string.cpp) # 生成静态库 (.a 文件) add_library(BetterSTL_static STATIC ${BETTERSTL_SOURCES}) @@ -36,6 +37,11 @@ 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) + # 生成导出信息用于外部使用 install(TARGETS BetterSTL_static BetterSTL_shared LIBRARY DESTINATION lib diff --git a/include/bstl/string.hpp b/include/bstl/string.hpp new file mode 100644 index 0000000..1253201 --- /dev/null +++ b/include/bstl/string.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include +#include + +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 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; + + // 大小写转换 + 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_; +}; + +} // namespace bstl diff --git a/src/string.cpp b/src/string.cpp new file mode 100644 index 0000000..0c8b784 --- /dev/null +++ b/src/string.cpp @@ -0,0 +1,362 @@ +#include "bstl/string.hpp" + +#include +#include + +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::split(const String& delimiter) const { + std::vector 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& 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(result[0])); + for (size_t i = 1; i < result.size(); i++) { + result[i] = std::tolower(static_cast(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(result[i]))) { + newWord = true; + } else { + if (newWord) { + result[i] = std::toupper(static_cast(result[i])); + newWord = false; + } else { + result[i] = std::tolower(static_cast(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(pos); +} + +int String::rfind(const String& substring) const { + size_t pos = data_.rfind(substring.data_); + return pos == std::string::npos ? -1 : static_cast(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(data_[start]))) { + start++; + } + while (end > start && std::isspace(static_cast(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(data_[start]))) { + start++; + } + return String(data_.substr(start)); +} + +String String::rstrip() const { + size_t end = data_.size(); + while (end > 0 && std::isspace(static_cast(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_; +} + +} // namespace bstl diff --git a/tests/StringTest.cpp b/tests/StringTest.cpp new file mode 100644 index 0000000..3271714 --- /dev/null +++ b/tests/StringTest.cpp @@ -0,0 +1,107 @@ +#include + +#include +#include + +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 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; +} From ceb7c3fa44c87c48255d5af09653ba41cb23b6e14f20e1e851646f01dcce27fd Mon Sep 17 00:00:00 2001 From: ArchZer0 Date: Sun, 16 Aug 2026 16:28:12 +0800 Subject: [PATCH 3/3] =?UTF-8?q?stdio=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 5 ++ IO_SUPPORT.md | 91 +++++++++++++++++++++++++++++++++++ examples/IODemo.cpp | 41 ++++++++++++++++ examples/a.out | Bin 0 -> 22880 bytes include/bstl/big_decimal.hpp | 5 ++ include/bstl/big_integer.hpp | 5 ++ include/bstl/string.hpp | 5 ++ src/big_decimal.cpp | 11 +++++ src/big_integer.cpp | 11 +++++ src/string.cpp | 11 +++++ tests/IOTest.cpp | 64 ++++++++++++++++++++++++ 11 files changed, 249 insertions(+) create mode 100644 IO_SUPPORT.md create mode 100644 examples/IODemo.cpp create mode 100755 examples/a.out create mode 100644 tests/IOTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fa21fe4..8656933 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,11 @@ 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 diff --git a/IO_SUPPORT.md b/IO_SUPPORT.md new file mode 100644 index 0000000..eddd0c3 --- /dev/null +++ b/IO_SUPPORT.md @@ -0,0 +1,91 @@ +# BetterSTL cin/cout 支持 + +现在三个核心类都支持标准输入输出: + +## BigInteger - 高精度整数 + +```cpp +#include +#include + +bstl::BigInteger bi; +std::cout << "Enter a large integer: "; +std::cin >> bi; +std::cout << "You entered: " << bi << std::endl; +``` + +支持任意精度的整数输入输出,不受 `long long` 限制。 + +## BigDecimal - 高精度浮点数 + +```cpp +#include +#include + +bstl::BigDecimal bd; +std::cout << "Enter a decimal number: "; +std::cin >> bd; +std::cout << "You entered: " << bd << std::endl; +``` + +支持任意精度的浮点数输入输出,精度不丢失。 + +## String - 增强字符串 + +```cpp +#include +#include + +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 +``` diff --git a/examples/IODemo.cpp b/examples/IODemo.cpp new file mode 100644 index 0000000..8800568 --- /dev/null +++ b/examples/IODemo.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +#include + +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; +} diff --git a/examples/a.out b/examples/a.out new file mode 100755 index 0000000000000000000000000000000000000000000000000000000000000000..978346a4d5e4a4ac60088f80b088df71587b571f282ee43fac5c8b22ba855eb8 GIT binary patch literal 22880 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 M&>kvlv7zFB0s0u#4*&oF literal 0 HcmV?d00001 diff --git a/include/bstl/big_decimal.hpp b/include/bstl/big_decimal.hpp index 59b8639..0ce87b6 100644 --- a/include/bstl/big_decimal.hpp +++ b/include/bstl/big_decimal.hpp @@ -2,6 +2,7 @@ #define BETTERSTL_BIG_DECIMAL_H #include +#include #include namespace bstl { @@ -69,6 +70,10 @@ private: 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 diff --git a/include/bstl/big_integer.hpp b/include/bstl/big_integer.hpp index c4f12d9..2f6e088 100644 --- a/include/bstl/big_integer.hpp +++ b/include/bstl/big_integer.hpp @@ -2,6 +2,7 @@ #define BETTERSTL_BIG_INTEGER_HPP #include +#include namespace bstl { @@ -65,6 +66,10 @@ private: 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 diff --git a/include/bstl/string.hpp b/include/bstl/string.hpp index 1253201..37588fe 100644 --- a/include/bstl/string.hpp +++ b/include/bstl/string.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace bstl { @@ -89,4 +90,8 @@ private: std::string data_; }; +// 流运算符重载 +std::ostream& operator<<(std::ostream& os, const String& str); +std::istream& operator>>(std::istream& is, String& str); + } // namespace bstl diff --git a/src/big_decimal.cpp b/src/big_decimal.cpp index 52291ee..2570da5 100644 --- a/src/big_decimal.cpp +++ b/src/big_decimal.cpp @@ -338,4 +338,15 @@ BigDecimal BigDecimal::round(int scale) const { 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 diff --git a/src/big_integer.cpp b/src/big_integer.cpp index 3ed86c3..4436fd9 100644 --- a/src/big_integer.cpp +++ b/src/big_integer.cpp @@ -374,5 +374,16 @@ BigInteger BigInteger::operator/(const BigInteger& other) const { 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 diff --git a/src/string.cpp b/src/string.cpp index 0c8b784..e1e2a1a 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -359,4 +359,15 @@ 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 diff --git a/tests/IOTest.cpp b/tests/IOTest.cpp new file mode 100644 index 0000000..eae9339 --- /dev/null +++ b/tests/IOTest.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +#include +#include +#include + +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; +}