SHA256
Compare commits
9
Commits
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
ceb7c3fa44 | ||
|
|
1f8fa26d73 | ||
|
|
b3ab9e9429 | ||
|
|
86191b5eb0 | ||
|
|
c145fa8d05 | ||
|
|
feac230fef | ||
|
|
32a43f6161 | ||
|
|
83a75d4e76 | ||
|
|
fb2b24bc72 |
+15
-4
@@ -4,8 +4,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# 定义源文件
|
||||
set(BETTERSTL_SOURCES
|
||||
src/BigInteger.cpp
|
||||
src/BigDecimal.cpp)
|
||||
src/big_integer.cpp
|
||||
src/big_decimal.cpp
|
||||
src/string.cpp)
|
||||
|
||||
# 生成静态库 (.a 文件)
|
||||
add_library(BetterSTL_static STATIC ${BETTERSTL_SOURCES})
|
||||
@@ -26,16 +27,26 @@ add_library(BetterSTL ALIAS BetterSTL_static)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(BigIntegerTests tests/BigIntegerTest.cpp)
|
||||
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/BigDecimalTest.cpp)
|
||||
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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
#include<BigDecimal.hpp>
|
||||
#include<BigInteger.hpp>
|
||||
#include <bstlint.hpp>
|
||||
#ifndef BETTERSTL_BSTL_HPP
|
||||
#define BETTERSTL_BSTL_HPP
|
||||
#endif //BETTERSTL_BSTL_HPP
|
||||
@@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
#ifndef BETTERSTL_BIG_DECIMAL_H
|
||||
#define BETTERSTL_BIG_DECIMAL_H
|
||||
|
||||
#include <string>
|
||||
#include "BigInteger.hpp"
|
||||
#include <iostream>
|
||||
#include <bstl/big_integer.hpp>
|
||||
|
||||
namespace bstl {
|
||||
|
||||
class BigDecimal {
|
||||
class BigDecimal {
|
||||
public:
|
||||
BigDecimal();
|
||||
BigDecimal(int value);
|
||||
@@ -69,4 +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
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#ifndef BETTERSTL_BIG_INTEGER_HPP
|
||||
#define BETTERSTL_BIG_INTEGER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace bstl {
|
||||
|
||||
@@ -64,6 +66,10 @@ private:
|
||||
static std::string divAbs(const std::string& a, const std::string& b);
|
||||
};
|
||||
|
||||
using BitInteger = BigInteger;
|
||||
// 流运算符重载
|
||||
std::ostream& operator<<(std::ostream& os, const BigInteger& bi);
|
||||
std::istream& operator>>(std::istream& is, BigInteger& bi);
|
||||
|
||||
} // namespace bstl
|
||||
|
||||
#endif //BETTERSTL_BIG_INTEGER_HPP
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
#include <cstdint>
|
||||
#include <>
|
||||
|
||||
typedef std::int8_t i8;
|
||||
typedef std::int16_t i16;
|
||||
@@ -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
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "BigDecimal.hpp"
|
||||
#include <bstl/big_decimal.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
@@ -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
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "BigInteger.hpp"
|
||||
#include <bstl/big_integer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
@@ -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
|
||||
|
||||
+373
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <BigDecimal.hpp>
|
||||
#include <bstl/big_decimal.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <BigInteger.hpp>
|
||||
#include <bstl/big_integer.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
Reference in New Issue
Block a user