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

读取C++头文件#define遇字典重复键,保存格式异常技术问询

解决你的C++头文件常量编辑器问题

嘿,我看你遇到了两个头疼的问题,咱们一个个来搞定:

问题1:字典重复键错误

这个错误是因为你的头文件里存在重复的#define宏定义,比如同一个常量被定义了多次,而ToDictionary方法不允许键重复。

你原来的loadweapon方法直接把匹配到的结果转成字典,一旦有重复键就会炸。咱们可以改成手动构建字典,保留最后一次出现的定义(这也是C++预处理的逻辑,后面的定义会覆盖前面的):

public void loadweapon()
{
    this.tokens = new Dictionary<string, string>();
    var lines = File.ReadLines(this.file);
    // 先保存原始文件内容,后续保存时可以参考(或者直接在Save里重新读取)
    this.header = string.Join(Environment.NewLine, lines);

    foreach (var line in lines)
    {
        var match = Regex.Match(line, @"^\s*#define\s+(.+?)(\s+(.+?))?((\s*//)|$)");
        if (match.Success && match.Groups[3].Success)
        {
            var key = match.Groups[1].Value.Trim();
            var value = match.Groups[3].Value.Trim();
            // 如果键已存在,直接覆盖(模拟C++宏的覆盖逻辑)
            if (tokens.ContainsKey(key))
            {
                tokens[key] = value;
            }
            else
            {
                tokens.Add(key, value);
            }
        }
    }
}

这样既避免了重复键错误,还完全符合C++的宏处理规则。

问题2:保存文件格式混乱

你现在的Save方法有两个核心问题:

  1. header变量根本没赋值(原来的代码里只声明了没初始化),导致写入空内容;
  2. 写入的格式完全搞反了,应该是#define 键 值而不是键#define 值,而且丢失了原始文件里的注释、空行和其他非#define内容。

咱们修改Save方法,只替换原始文件中对应的#define行,而不是重新生成整个文件,这样就能完美保留原始格式:

public void Save(string file)
{
    var lines = File.ReadAllLines(file).ToList();
    for (int i = 0; i < lines.Count; i++)
    {
        var line = lines[i];
        var match = Regex.Match(line, @"^\s*#define\s+(.+?)(\s+(.+?))?((\s*//).*)?$");
        if (match.Success && match.Groups[3].Success)
        {
            var key = match.Groups[1].Value.Trim();
            if (tokens.TryGetValue(key, out var newValue))
            {
                // 保留行首的缩进空格,替换宏的值部分,同时保留行尾注释
                var prefix = line.Substring(0, match.Groups[1].Index);
                var comment = match.Groups[4].Value;
                lines[i] = $"{prefix}#define {key} {newValue}{comment}";
            }
        }
    }
    File.WriteAllLines(file, lines);
}

这个方法会遍历原始文件的每一行,只修改匹配到的#define行,替换成新的值,同时保留原始的缩进、行尾注释和其他所有内容,格式再也不会乱了。

另外提个小优化:你的Search方法可以直接用字典的TryGetValue,比foreach遍历高效多了:

public string Search(string name)
{
    tokens.TryGetValue(name, out var value);
    return value;
}

这样代码更简洁,性能也更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:44:09