标准库特殊设施涵盖了 C++ 标准库中一些非常实用但相对独立的组件,这些工具能极大提升编程效率和代码质量。
1. tuple
类型
基本用法
cpp
#include <tuple>
#include <string>
#include <iostream>
void tuple_basic_demo() {
// 创建 tuple
std::tuple<int, double, std::string> t1(42, 3.14, "hello");
// 使用 make_tuple(自动推导类型)
auto t2 = std::make_tuple(1, 2.5, "world", 'a');
// 访问元素(编译时确定索引)
std::cout << "t1[0]: " << std::get<0>(t1) << std::endl; // 42
std::cout << "t1[1]: " << std::get<1>(t1) << std::endl; // 3.14
std::cout << "t1[2]: " << std::get<2>(t1) << std::endl; // hello
// 获取 tuple 大小
std::cout << "t1 size: " << std::tuple_size<decltype(t1)>::value << std::endl;
// 按类型访问(类型必须唯一)
std::cout << "string element: " << std::get<std::string>(t1) << std::endl;
}
tuple 的实用操作
cpp
#include <functional>
void tuple_operations_demo() {
auto t1 = std::make_tuple(1, 2.5, "hello");
auto t2 = std::make_tuple(2, 3.14, "world");
// 比较操作
if (t1 < t2) {
std::cout << "t1 < t2" << std::endl;
}
// 连接 tuple(C++11 之后)
auto t3 = std::tuple_cat(t1, t2, std::make_tuple('x', 'y'));
// 解包 tuple
int a;
double b;
std::string c;
std::tie(a, b, c) = t1; // a=1, b=2.5, c="hello"
std::cout << "a=" << a << ", b=" << b << ", c=" << c << std::endl;
// 结构化绑定(C++17)
auto [x, y, z] = t2;
std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
}
tuple 与函数返回多值
cpp
#include <vector>
#include <algorithm>
// 返回多个值
std::tuple<double, double, double> statistics(const std::vector<double>& data) {
if (data.empty()) {
return std::make_tuple(0.0, 0.0, 0.0);
}
double sum = std::accumulate(data.begin(), data.end(), 0.0);
double mean = sum / data.size();
auto [min_it, max_it] = std::minmax_element(data.begin(), data.end());
double min_val = *min_it;
double max_val = *max_it;
return std::make_tuple(mean, min_val, max_val);
}
void tuple_return_demo() {
std::vector<double> numbers = {1.0, 2.5, 3.7, 0.5, 4.2};
// C++17 结构化绑定
auto [mean, min_val, max_val] = statistics(numbers);
std::cout << "Mean: " << mean << std::endl;
std::cout << "Min: " << min_val << std::endl;
std::cout << "Max: " << max_val << std::endl;
// C++11/14 方式
double m1, m2, m3;
std::tie(m1, m2, m3) = statistics(numbers);
}
2. bitset
类型
基本操作
cpp
#include <bitset>
#include <string>
void bitset_basic_demo() {
// 创建 bitset
std::bitset<8> b1; // 8位,全0
std::bitset<16> b2(0xFFFF); // 从整数初始化
std::bitset<32> b3("1100"); // 从字符串初始化
std::cout << "b1: " << b1 << std::endl; // 00000000
std::cout << "b2: " << b2 << std::endl; // 1111111111111111
std::cout << "b3: " << b3 << std::endl; // 00000000000000000000000000001100
// 设置位
b1.set(0); // 设置第0位
b1.set(3, true); // 设置第3位为1
b1.set(); // 设置所有位为1
// 重置位
b1.reset(0); // 重置第0位
b1.reset(); // 重置所有位
// 翻转位
b1.flip(0); // 翻转第0位
b1.flip(); // 翻转所有位
// 访问位
bool bit0 = b1[0]; // 访问第0位
b1[1] = true; // 设置第1位
// 测试位
if (b1.test(0)) {
std::cout << "Bit 0 is set" << std::endl;
}
// 统计
std::cout << "Number of 1s: " << b1.count() << std::endl;
std::cout << "Total bits: " << b1.size() << std::endl;
std::cout << "Any bit set: " << b1.any() << std::endl;
std::cout << "All bits set: " << b1.all() << std::endl;
std::cout << "No bits set: " << b1.none() << std::endl;
}
bitset 应用:权限系统
cpp
class PermissionSystem {
public:
enum Permissions {
READ = 0,
WRITE = 1,
EXECUTE = 2,
DELETE = 3,
SHARE = 4,
TOTAL_PERMISSIONS = 5
};
private:
std::bitset<TOTAL_PERMISSIONS> permissions;
public:
void grant(Permissions p) {
permissions.set(p);
}
void revoke(Permissions p) {
permissions.reset(p);
}
bool has(Permissions p) const {
return permissions.test(p);
}
void toggle(Permissions p) {
permissions.flip(p);
}
void clear() {
permissions.reset();
}
std::string to_string() const {
return permissions.to_string();
}
};
void bitset_application_demo() {
PermissionSystem user_perms;
user_perms.grant(PermissionSystem::READ);
user_perms.grant(PermissionSystem::WRITE);
user_perms.grant(PermissionSystem::SHARE);
std::cout << "Permissions: " << user_perms.to_string() << std::endl;
std::cout << "Can read: " << user_perms.has(PermissionSystem::READ) << std::endl;
std::cout << "Can execute: " << user_perms.has(PermissionSystem::EXECUTE) << std::endl;
user_perms.toggle(PermissionSystem::WRITE);
std::cout << "After toggle WRITE: " << user_perms.to_string() << std::endl;
}
3. 正则表达式库
基本匹配
cpp
#include <regex>
#include <string>
void regex_basic_demo() {
std::string text = "Quick brown fox jumps over the lazy dog";
// 简单搜索
std::regex word_regex("\\b\\w+\\b"); // 单词边界
auto words_begin = std::sregex_iterator(text.begin(), text.end(), word_regex);
auto words_end = std::sregex_iterator();
std::cout << "Words found: " << std::distance(words_begin, words_end) << std::endl;
for (auto i = words_begin; i != words_end; ++i) {
std::smatch match = *i;
std::cout << match.str() << " ";
}
std::cout << std::endl;
// 精确匹配
std::regex fox_regex("fox");
if (std::regex_search(text, fox_regex)) {
std::cout << "Found 'fox' in the text" << std::endl;
}
// 匹配检查
std::regex exact_regex("^Quick.*dog$");
if (std::regex_match(text, exact_regex)) {
std::cout << "Text matches the pattern" << std::endl;
}
}
分组和替换
cpp
void regex_advanced_demo() {
// 分组提取
std::string date = "2024-01-15";
std::regex date_regex(R"((\d{4})-(\d{2})-(\d{2}))");
std::smatch match;
if (std::regex_match(date, match, date_regex)) {
std::cout << "Full match: " << match[0] << std::endl;
std::cout << "Year: " << match[1] << std::endl;
std::cout << "Month: " << match[2] << std::endl;
std::cout << "Day: " << match[3] << std::endl;
}
// 字符串替换
std::string text = "C++ is better than Java";
std::regex lang_regex("Java");
std::string result = std::regex_replace(text, lang_regex, "Python");
std::cout << "After replacement: " << result << std::endl;
// 格式化替换
std::string phone = "Call me at (123) 456-7890";
std::regex phone_regex(R"(\((\d{3})\)\s*(\d{3})-(\d{4}))");
std::string formatted = std::regex_replace(phone, phone_regex, "$1-$2-$3");
std::cout << "Formatted phone: " << formatted << std::endl;
// 邮箱验证
std::regex email_regex(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b)");
std::string email = "user@example.com";
if (std::regex_match(email, email_regex)) {
std::cout << "Valid email: " << email << std::endl;
}
}
4. 随机数库
现代随机数生成
cpp
#include <random>
#include <chrono>
void random_number_demo() {
// 随机数引擎(使用时间作为种子)
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator(seed);
// 均匀分布
std::uniform_int_distribution<int> int_dist(1, 100); // 1-100 整数
std::uniform_real_distribution<double> real_dist(0.0, 1.0); // 0-1 实数
std::cout << "Random integers: ";
for (int i = 0; i < 5; ++i) {
std::cout << int_dist(generator) << " ";
}
std::cout << std::endl;
std::cout << "Random reals: ";
for (int i = 0; i < 5; ++i) {
std::cout << real_dist(generator) << " ";
}
std::cout << std::endl;
// 正态分布
std::normal_distribution<double> normal_dist(0.0, 1.0); // 均值0,标准差1
std::cout << "Normal distribution: ";
for (int i = 0; i < 5; ++i) {
std::cout << normal_dist(generator) << " ";
}
std::cout << std::endl;
// 布尔分布(50% 概率)
std::bernoulli_distribution bool_dist(0.5);
std::cout << "Coin flips: ";
for (int i = 0; i < 10; ++i) {
std::cout << (bool_dist(generator) ? "Heads" : "Tails") << " ";
}
std::cout << std::endl;
}
随机数应用:抽奖系统
cpp
#include <vector>
#include <algorithm>
class LotterySystem {
private:
std::mt19937 generator;
public:
LotterySystem() : generator(std::random_device{}()) {}
// 从范围内抽取不重复的数字
std::vector<int> draw_numbers(int min, int max, int count) {
std::vector<int> all_numbers;
for (int i = min; i <= max; ++i) {
all_numbers.push_back(i);
}
std::shuffle(all_numbers.begin(), all_numbers.end(), generator);
all_numbers.resize(count);
std::sort(all_numbers.begin(), all_numbers.end());
return all_numbers;
}
// 从列表中随机选择
template<typename T>
T select_random(const std::vector<T>& items) {
std::uniform_int_distribution<size_t> dist(0, items.size() - 1);
return items[dist(generator)];
}
};
void lottery_demo() {
LotterySystem lottery;
// 抽奖:从1-49中抽取6个数字
auto numbers = lottery.draw_numbers(1, 49, 6);
std::cout << "Lottery numbers: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 随机选择
std::vector<std::string> prizes = {"Car", "TV", "Phone", "Book", "Nothing"};
std::cout << "You won: " << lottery.select_random(prizes) << std::endl;
}
5. IO 库高级功能
格式化输出
cpp
#include <iomanip>
void formatting_demo() {
double pi = 3.141592653589793;
int number = 255;
// 设置精度
std::cout << "Default: " << pi << std::endl;
std::cout << "Fixed(2): " << std::fixed << std::setprecision(2) << pi << std::endl;
std::cout << "Scientific: " << std::scientific << pi << std::endl;
// 恢复默认
std::cout << std::defaultfloat;
// 设置宽度和对齐
std::cout << std::setw(10) << number << std::endl;
std::cout << std::setw(10) << std::left << number << std::endl;
std::cout << std::setw(10) << std::right << number << std::endl;
// 填充字符
std::cout << std::setw(10) << std::setfill('*') << number << std::endl;
// 进制输出
std::cout << "Decimal: " << number << std::endl;
std::cout << "Hex: " << std::hex << number << std::endl;
std::cout << "Octal: " << std::oct << number << std::endl;
// 恢复十进制
std::cout << std::dec;
// 布尔值输出
bool flag = true;
std::cout << "Default bool: " << flag << std::endl;
std::cout << "Boolalpha: " << std::boolalpha << flag << std::endl;
}
文件流操作
cpp
#include <fstream>
#include <sstream>
void file_io_demo() {
// 写入文件
std::ofstream outfile("example.txt");
if (outfile) {
outfile << "Line 1: Hello World" << std::endl;
outfile << "Line 2: 3.14159" << std::endl;
outfile << "Line 3: 42" << std::endl;
outfile.close();
}
// 读取文件
std::ifstream infile("example.txt");
std::string line;
if (infile) {
while (std::getline(infile, line)) {
std::cout << "Read: " << line << std::endl;
}
infile.close();
}
// 字符串流
std::string data = "John 25 85.5";
std::istringstream iss(data);
std::string name;
int age;
double score;
iss >> name >> age >> score;
std::cout << "Name: " << name << ", Age: " << age << ", Score: " << score << std::endl;
// 字符串流构建字符串
std::ostringstream oss;
oss << "Result: " << 42 << " " << 3.14 << " " << std::boolalpha << true;
std::string result_str = oss.str();
std::cout << "Built string: " << result_str << std::endl;
}
6. 实践项目:配置文件解析器
cpp
#include <map>
#include <sstream>
class ConfigParser {
private:
std::map<std::string, std::string> config;
public:
bool load(const std::string& filename) {
std::ifstream file(filename);
if (!file) {
return false;
}
std::string line;
std::regex config_regex(R"(^\s*([\w\.-]+)\s*=\s*(.*?)\s*$)");
std::regex comment_regex(R"(^\s*#)");
while (std::getline(file, line)) {
// 跳过空行和注释
if (line.empty() || std::regex_match(line, comment_regex)) {
continue;
}
std::smatch match;
if (std::regex_match(line, match, config_regex)) {
config[match[1]] = match[2];
}
}
return true;
}
template<typename T>
T get(const std::string& key, const T& default_value = T()) const {
auto it = config.find(key);
if (it == config.end()) {
return default_value;
}
std::istringstream iss(it->second);
T value;
if (!(iss >> value)) {
return default_value;
}
return value;
}
// 字符串特化
std::string get(const std::string& key, const std::string& default_value = "") const {
auto it = config.find(key);
if (it == config.end()) {
return default_value;
}
return it->second;
}
// 布尔值特化
bool get_bool(const std::string& key, bool default_value = false) const {
auto it = config.find(key);
if (it == config.end()) {
return default_value;
}
std::string value = it->second;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if (value == "true" || value == "1" || value == "yes" || value == "on") {
return true;
} else if (value == "false" || value == "0" || value == "no" || value == "off") {
return false;
}
return default_value;
}
};
void config_parser_demo() {
ConfigParser parser;
if (parser.load("config.txt")) {
std::string name = parser.get("name", "Unknown");
int port = parser.get("port", 8080);
double timeout = parser.get("timeout", 30.0);
bool debug = parser.get_bool("debug", false);
std::cout << "Name: " << name << std::endl;
std::cout << "Port: " << port << std::endl;
std::cout << "Timeout: " << timeout << std::endl;
std::cout << "Debug: " << std::boolalpha << debug << std::endl;
}
}
最佳实践总结
- 优先使用现代随机数库 而不是
rand()
- 使用
regex
进行复杂的字符串处理 tuple
适合返回多个相关值bitset
适合存储固定大小的标志集合- 掌握 IO 格式化提升输出质量
使用 C++ 标准库中的高级工具解决复杂问题,大大提升编程效率!