std::string的replace用例(替换字符串或容器中的某个元素)

本文详细解析了C++标准库中std::replace函数的使用方法与内部实现原理,包括如何替换字符串中的字符和容器中的元素,并通过实例展示了其在实际编程中的应用。

std::replace 位于#include <algorithm>中
主要作用是替换字符串的字符或者容器的元素

下面看一下 std::replace 的源码:

template<class _FwdIt,class _Ty> inline
void replace(_FwdIt _First, _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval)
{	// replace each matching _Oldval with _Newval
	_DEBUG_RANGE(_First, _Last);
	_Replace_unchecked(_Unchecked(_First), _Unchecked(_Last),
		_Oldval, _Newval);
}

_Replace_unchecked 的源码:

_Replace_unchecked 的源码:
template<class _FwdIt,class _Ty> inline
void _Replace_unchecked(_FwdIt _First, _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval)
{	// replace each matching _Oldval with _Newval
	for (; _First != _Last; ++_First)
		if (*_First == _Oldval)
			*_First = _Newval;
}

发现其主要采用的是泛型编程即模板编程的方法,
通过遍历传入进来的_First,如果_First不等于_Last,就会继续遍历,
直到找到我们想替换的_Oldval,然后通过赋值操作进行替换。

栗子1:

std::string str1="hello,world,"
//把最后一个逗号替换成换行符 
str1.replace(str1.find_last_of(","),1,"\n"); 

输出结果:

栗子2:

std::string str2="c++ is a language";
//把某个字符替换成新字符,c++替换为javascript
str2.replace(str2,find("c++"),3,"javascript");

输出结果:

如果改成str2.replace(str2,find("c++"),20,"javascript") 这时只输出javascript。

栗子3:

//替换等于1的所有数
vector<int> v{ 1,2,3,4,5,6,1 };
std::replace(v.begin(), v.end(), 1, 66);

for (auto i : v) {
	cout << i << " ";
}
std::cout << std::endl;

//替换小于4的所有数
std::replace_if(v.begin(), v.end(),std::bind(std::less<int>(), std::placeholders::_1, 4), 99);
for (int i : v) {
	std::cout << i << " ";
}
std::cout << std::endl;

输出:

 

#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> #include <regex> #include <algorithm> #include <iomanip> struct LogEntry { std::string time; int V = -1; int C = -1; int L_Pump = -1; int R_Pump = -1; int line_number = -1; // 记录原始行号用于错误跟踪 bool isComplete() const { return !time.empty() && V != -1 && C != -1 && L_Pump != -1 && R_Pump != -1; } }; // 增强的字段修复函数 std::string fixMalformedLine(const std::string& line) { std::string fixed = line; // 修复字段粘连问题(如 L_Pump188 → L_Pump:188) std::regex malformed(R"((\b[Ll][_ ]?[Pp]ump|\b[Rr][_ ]?[Pp]ump|\b[Vv]\b|\b[Cc]\b)(\d+))"); fixed = std::regex_replace(fixed, malformed, "$ 1:$ 2"); // 修复等号/冒号缺失问题(如 "V 123" → "V:123") std::regex missingSeparator(R"((\b[Ll][_ ]?[Pp]ump|\b[Rr][_ ]?[Pp]ump|\b[Vv]\b|\b[Cc]\b)\s+(\d+))"); fixed = std::regex_replace(fixed, missingSeparator, "$ 1:$ 2"); // 统一分隔符为冒号 std::regex equalSign(R"((\b[Ll][_ ]?[Pp]ump|\b[Rr][_ ]?[Pp]ump|\b[Vv]\b|\b[Cc]\b)\s*=\s*(\d+))"); fixed = std::regex_replace(fixed, equalSign, "$ 1:$ 2"); return fixed; } // 增强的时间戳识别 bool extractTimestamp(std::string& line, std::string& timestamp) { std::regex timeRegex( R"((\d{4})[-/](\d{1,2})[-/](\d{1,2})[T\s](\d{1,2}):(\d{1,2})(?::(\d{1,2}))?)" ); std::smatch match; if (std::regex_search(line, match, timeRegex)) { // 标准化时间格式为 YYYY-MM-DD HH:MM:SS std::ostringstream oss; oss << match[1] << "-" << std::setw(2) << std::setfill('0') << match[2] << "-" << std::setw(2) << std::setfill('0') << match[3] << " " << std::setw(2) << std::setfill('0') << match[4] << ":" << std::setw(2) << std::setfill('0') << match[5]; if (match[6].matched) { oss << ":" << std::setw(2) << std::setfill('0') << match[6]; } else { oss << ":00"; // 添加默认秒数 } timestamp = oss.str(); return true; } return false; } // 改进的日志解析函数 std::vector<LogEntry> parseLogFile(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) { throw std::runtime_error("无法打开日志文件: " + filename); } std::string line; std::vector<LogEntry> entries; LogEntry currentEntry; int line_number = 0; bool hasPartialEntry = false; while (std::getline(file, line)) { line_number++; std::string original_line = line; // 保存原始行用于错误报告 // 跳过空行和注释行 if (line.empty() || line.find("//") == 0 || line.find('#') == 0) continue; // 修复格式问题 std::string fixedLine = fixMalformedLine(line); // 检查时间戳 std::string timestamp; if (extractTimestamp(fixedLine, timestamp)) { if (hasPartialEntry) { if (!currentEntry.isComplete()) { std::cerr << "⚠️ 警告: 第 " << currentEntry.line_number << " 行开始的日志条目不完整\n"; } entries.push_back(currentEntry); } currentEntry = LogEntry(); currentEntry.time = timestamp; currentEntry.line_number = line_number; hasPartialEntry = true; } // 提取字段值(忽略大小写) std::smatch match; std::regex vRegex(R"(\b[Vv]\s*[:=]\s*(\d+))"); if (std::regex_search(fixedLine, match, vRegex)) { try { currentEntry.V = std::stoi(match[1]); } catch (...) { std::cerr << "⛔ 数值转换错误 (V): 第 " << line_number << " 行: " << original_line << "\n"; } } std::regex cRegex(R"(\b[Cc]\s*[:=]\s*(\d+))"); if (std::regex_search(fixedLine, match, cRegex)) { try { currentEntry.C = std::stoi(match[1]); } catch (...) { std::cerr << "⛔ 数值转换错误 \(C\): 第 " << line_number << " 行: " << original_line << "\n"; } } std::regex lPumpRegex(R"(\b[Ll][_ ]?[Pp]ump\s*[:=]\s*(\d+))"); if (std::regex_search(fixedLine, match, lPumpRegex)) { try { currentEntry.L_Pump = std::stoi(match[1]); } catch (...) { std::cerr << "⛔ 数值转换错误 (L_Pump): 第 " << line_number << " 行: " << original_line << "\n"; } } std::regex rPumpRegex(R"(\b[Rr][_ ]?[Pp]ump\s*[:=]\s*(\d+))"); if (std::regex_search(fixedLine, match, rPumpRegex)) { try { currentEntry.R_Pump = std::stoi(match[1]); } catch (...) { std::cerr << "⛔ 数值转换错误 (R_Pump): 第 " << line_number << " 行: " << original_line << "\n"; } } } // 处理最后一个条目 if (hasPartialEntry) { if (!currentEntry.isComplete()) { std::cerr << "⚠️ 警告: 第 " << currentEntry.line_number << " 行开始的日志条目不完整\n"; } entries.push_back(currentEntry); } return entries; } // 增强的CSV保存功能 void saveToCSV(const std::vector<LogEntry>& entries, const std::string& csvFilename) { std::ofstream outFile(csvFilename); if (!outFile.is_open()) { throw std::runtime_error("无法创建CSV文件: " + csvFilename); } // 写入UTF-8 BOM头(可选,增强Excel兼容性) outFile << "\xEF\xBB\xBF"; // 写入列头 outFile << "时间戳,V值,C值,左泵值,右泵值,原始行号\n"; for (const auto& entry : entries) { outFile << "\"" << entry.time << "\"," << entry.V << "," << entry.C << "," << entry.L_Pump << "," << entry.R_Pump << "," << entry.line_number << "\n"; } } int main(int argc, char* argv[]) { std::string logFilename = "C:\\Users\\A\\Desktop\\input.txt"; std::string csvFilename = "C:\\Users\\A\\Desktop\\output.csv"; // 简单的命令行参数处理 if (argc > 1) logFilename = argv[1]; if (argc > 2) csvFilename = argv[2]; try { std::cout << "🔧 开始解析日志文件: " << logFilename << std::endl; auto entries = parseLogFile(logFilename); std::cout << "✅ 成功解析 " << entries.size() << " 个日志条目\n"; std::cout << "💾 写入CSV文件: " << csvFilename << std::endl; saveToCSV(entries, csvFilename); std::cout << "🎉 转换完成!结果已保存至 " << csvFilename << std::endl; // 统计信息 size_t complete = std::count_if(entries.begin(), entries.end(), [](const LogEntry& e) { return e.isComplete(); }); std::cout << "📊 统计: " << complete << " 个完整条目, " << (entries.size() - complete) << " 个不完整条目\n"; } catch (const std::exception& e) { std::cerr << "❌ 错误: " << e.what() << std::endl; return 1; } return 0; } 这个代码丢失大量数据如何完善
06-30
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值