You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C++实现数据脱敏的自动列选择功能 替代硬编码方案

解决方案

核心改造思路

你当前的问题是脱敏规则与业务逻辑强耦合,通过规则配置化的思路剥离硬编码逻辑后,无需修改核心代码即可新增/调整事件的脱敏规则:

  • 抽离所有事件的脱敏规则为独立配置项,与执行逻辑完全解耦
  • 复用重复的脱敏处理逻辑,消除冗余代码
  • 新增事件场景仅需补充配置项,无需修改核心执行代码

改造后完整代码

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <ctime>
#include <unordered_set>
#include <stdexcept>

using namespace std;

// 读取CSV文件
vector<vector<string>> read_csv(const string& filename){
    ifstream input_file(filename);
    vector<string> row_items;
    vector<vector<string>> result;

    if (!input_file.is_open()) throw runtime_error("无法打开文件");

    string line, item;

    while(getline(input_file, line)){
        row_items.clear();
        stringstream ss(line);
        while(getline(ss, item, ',')){
            row_items.push_back(item);
        }
        result.push_back(row_items);
    }
    input_file.close();
    return result;
}

// 写入CSV文件
void write_csv(const string& filename, const vector<vector<string>>& dataset){
    ofstream output_file(filename);
    for (size_t rows = 0; rows < dataset.size(); rows++){
        for(size_t cols = 0; cols < dataset[rows].size(); cols++){
            output_file << dataset[rows][cols];
            if (cols != dataset[rows].size() - 1) output_file << ",";
        }
        output_file << "\n";
    }
    output_file.close();
    cout << "\n文件已保存为CSV格式!\n";
}

// 字符串脱敏逻辑,将字符替换为x,保留空格和小数点
string mask_string(const string& str_value){
    string new_str;
    new_str.reserve(str_value.size());
    for (char c : str_value){
        if (isspace(c)) new_str += ' ';
        else if (c == '.') new_str += '.';
        else new_str += 'x';
    }
    return new_str;
}

// 脱敏规则结构体,存储每个事件的脱敏配置
struct MaskRule {
    string event_name;
    unordered_set<int> keep_cols; // 保留明文无需脱敏的列
    unordered_set<int> partial_mask_cols; // 需要部分脱敏的列
    int partial_start_pos = 4; // 部分脱敏的起始下标
};

// 统一脱敏执行逻辑
void mask_column(vector<vector<string>>& dataset, int event)
{
    // 所有事件的脱敏配置,新增事件仅需在此添加配置即可
    vector<MaskRule> all_rules = {
        {"占位", {}, {}, 4}, // 下标0占位,事件id从1开始
        // 事件1:能耗事件
        {"能耗事件", {0,6,7,8,10,13,14,15,17,22}, {1,3,9,12,16}, 4},
        // 事件2:非技术损耗事件
        {"非技术损耗事件", {0,6,7,8,10,13,14,15,18,19,20,21}, {1,3,9,12,16}, 4},
        // 事件3:用电模式事件
        {"用电模式事件", {0,6,7,8,10,13,14,15,17,22}, {1,3,9,12,16}, 4},
        // 事件4:全量PII脱敏
        {"全量PII脱敏", {0,6,7,8,10,13,14,15,17,18,19,20,21,22}, {1,3,9,12,16}, 4}
    };

    // 校验事件id合法性
    if (event < 1 || event >= all_rules.size()) {
        throw runtime_error("输入的事件id不存在");
    }

    const MaskRule& rule = all_rules[event];
    // 遍历数据行,跳过表头行
    for (size_t rows = 1; rows < dataset.size(); rows++) {
        for (size_t cols = 0; cols < dataset[rows].size(); cols++) {
            int col_id = static_cast<int>(cols);
            // 保留列无需处理
            if (rule.keep_cols.count(col_id)) {
                continue;
            }
            // 部分脱敏列处理
            if (rule.partial_mask_cols.count(col_id)) {
                string& val = dataset[rows][cols];
                if (val.size() > rule.partial_start_pos) {
                    val.replace(rule.partial_start_pos, val.size() - rule.partial_start_pos, mask_string(val.substr(rule.partial_start_pos)));
                }
            } 
            // 全量脱敏列处理
            else {
                dataset[rows][cols] = mask_string(dataset[rows][cols]);
            }
        }
    }
}

int main(){
    // 显示当前日期时间
    time_t now = time(0);
    char* date_time = ctime(&now);
    cout << "当前日期时间:  " << date_time;

    cout << "\n欢迎使用IDSA程序\n";
    cout << "~我们为您保护客户数据~\n";

    // 读取CSV文件
    int event;
    vector<vector<string>> dataset = read_csv("originaldataset.csv");

    // 用户选择事件
    cout << "\n可选择的事件类型:\n\n";
    cout << "1. 能耗事件\n";
    cout << "2. 非技术损耗事件\n";
    cout << "3. 用电模式事件\n";
    cout << "4. 全量PII脱敏";
    cout << "\n\n请输入事件编号: ";
    cin >> event;

    try {
        mask_column(dataset, event);
        write_csv("masked_originaldataset.csv", dataset);
    } catch (const exception& e) {
        cout << "处理出错: " << e.what() << endl;
        return 1;
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者star

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 22:39:01