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

C#开发:使用正则从C风格函数声明中提取任意数量形参名

C# 正则提取C风格函数形参名通用方案

不要试图用单条正则覆盖所有场景,这类C函数声明因为存在宏嵌套、类型修饰符组合、换行排版差异,单正则会写得极其冗长且难以维护,分层处理的方案通用性和可维护性高很多。

实现思路

分两步处理:先定位所有函数的参数列表块,再从单个参数声明里提取形参名,额外用极简单的计数逻辑处理宏括号内的逗号分割问题,比纯正则处理效率高、漏匹配概率低。


第一步:匹配函数的参数列表块

使用如下正则匹配函数声明,捕获组1会返回函数名后括号内的完整参数内容,自动兼容带嵌套括号的宏返回值(比如AUTOSAR的FUNC(xxx, yyy) 格式)、跨多行排版的声明:

(?:\w+\s+|\*|\)+)*\w+\s*\(([^)(]*?(?:\([^)(]*\)[^)(]*?)*)\)

对你提供的三个示例,该正则捕获到的参数块内容分别为:

  1. NegativeResponseCode *ErrorCode_pt, uint8 Sid_u8
  2. P2CONST(uint8, AUTOMATIC, RTE_APPL_DATA) p_Data,\n P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, RTE_APPL_DATA) ErrorCode
  3. const UBYTE* abc
    如果捕获到的参数块为空、或仅为void,直接判定为无参数函数跳过即可。

第二步:分割单参数、提取形参名

拿到完整参数块后,不要直接用普通Split(',')分割——否则会把P2CONST这类宏内部的逗号误判为参数分隔符。写个10行左右的括号计数逻辑做分割:遍历字符串时遇到左括号计数+1,右括号计数-1,只有计数为0时遇到的逗号才是参数分隔符。

对分割后的单个参数字符串,用如下正则提取形参名,自动跳过所有前缀修饰:

(?:const\s+|volatile\s+)*\w+(?:\s*\([^)]*\))?\s*(?:\*+\s*|\s+)(\w+)\s*$

该正则可以覆盖的修饰场景包括:基础类型名、const/volatile类型限定符、带括号的参数/类型宏(P2CONST/P2VAR等)、任意数量的指针符号*,最终捕获组1的内容就是形参名。

对你的示例的匹配结果:

  • 第一组参数:分别捕获ErrorCode_pt、Sid_u8
  • 第二组参数:分别捕获p_Data、ErrorCode
  • 第三组参数:捕获abc

C# 可直接运行的实现代码

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class FunctionParamExtractor
{
    private static readonly Regex _functionMatcher = new Regex(
        @"(?:\w+\s+|\*|\)+)*\w+\s*\(([^)(]*?(?:\([^)(]*\)[^)(]*?)*)\)",
        RegexOptions.Compiled | RegexOptions.Multiline
    );

    private static readonly Regex _paramNameMatcher = new Regex(
        @"(?:const\s+|volatile\s+)*\w+(?:\s*\([^)]*\))?\s*(?:\*+\s*|\s+)(\w+)\s*$",
        RegexOptions.Compiled
    );

    public static List<string> GetAllParamNames(string sourceCode)
    {
        var paramNames = new List<string>();
        foreach (Match funcMatch in _functionMatcher.Matches(sourceCode))
        {
            string paramBlock = funcMatch.Groups[1].Value.Trim();
            // 跳过无参数函数
            if (string.IsNullOrWhiteSpace(paramBlock) || paramBlock.Equals("void", StringComparison.Ordinal))
                continue;

            foreach (string singleParam in SplitParamBlock(paramBlock))
            {
                var nameMatch = _paramNameMatcher.Match(singleParam.Trim());
                if (nameMatch.Success)
                    paramNames.Add(nameMatch.Groups[1].Value);
            }
        }
        return paramNames;
    }

    // 括号感知的逗号分割,避免宏内逗号被误判为参数分隔符
    private static List<string> SplitParamBlock(string paramBlock)
    {
        var paramList = new List<string>();
        int bracketCount = 0;
        int segmentStart = 0;
        for (int i = 0; i < paramBlock.Length; i++)
        {
            char current = paramBlock[i];
            if (current == '(') bracketCount++;
            if (current == ')') bracketCount--;
            if (current == ',' && bracketCount == 0)
            {
                paramList.Add(paramBlock.Substring(segmentStart, i - segmentStart));
                segmentStart = i + 1;
            }
        }
        paramList.Add(paramBlock.Substring(segmentStart));
        return paramList;
    }
}

方案适配范围

  • 支持1到任意数量的函数参数
  • 兼容AUTOSAR标准的FUNC、P2CONST、P2VAR等宏修饰写法
  • 支持const/volatile修饰、多级指针、跨多行排版的函数声明
  • 自动过滤无参数的函数声明
  • 后续如果需要新增修饰符适配(比如restrict关键字、自定义类型宏),只需要在参数名匹配的正则前缀部分追加对应规则即可,维护成本远低于单条全匹配正则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:54:14