从文件中修剪一个函数,以便只剩下的字符是函数名和参数
问题描述:
我正在编写一些代码来替换旧的C exe。原始的c文件会读取一个文件,然后修剪内容并将它们放入两个新文件,一个.c和一个.h文件。我正在做同样的事情,但在C#中。除了如何修剪一个函数,只有函数名和参数被放入.h文件,我已经找到了一切。 这是两个的功能的示例:从文件中修剪一个函数,以便只剩下的字符是函数名和参数
void
M_SCP_Msg_ClearNVMemory(
Marshal_dataFunc* _argDataFunc_, Marshal_dataFuncArg _argDataFuncArg_, void const* _argSrc_)
{
SCP_Msg_ClearNVMemory const* _src_ = (SCP_Msg_ClearNVMemory const*)_argSrc_;
M_uint8_t(_argDataFunc_, _argDataFuncArg_, &_src_->operation);
}
void
MA_SCP_Msg_ClearNVMemory(
Marshal_dataFunc* argDataFunc, Marshal_dataFuncArg argDataFuncArg,
void const* argSrc, unsigned argNSrcElem)
{
SCP_Msg_ClearNVMemory const* src = (SCP_Msg_ClearNVMemory const*)argSrc;
for (; argNSrcElem > 0; --argNSrcElem)
{
M_SCP_Msg_ClearNVMemory(argDataFunc, argDataFuncArg, src++);
}
}
这将是所期望的输出:
extern void M_SCP_Msg_ClearNVMemory(
Marshal_dataFunc* argDataFunc, Marshal_dataFuncArg argDataFuncArg, void const* argSrc);
extern void MA_SCP_Msg_ClearNVMemory(
Marshal_dataFunc* argDataFunc, Marshal_dataFuncArg argDataFuncArg,
void const* argSrc, unsigned argNSrcElem);
目前,原始文件的线被读入作为其通过分配串streamreader,然后这个字符串被写入到一个streamwriter,所以我想迭代通过,并找到任何包含任何函数的字符串将是一个很好的开始,一旦我有这些字符串,我可以以某种方式编辑它们。这是我到目前为止,finList是字符串和fin的列表,我将写入输出文件的字符串。
List<string> finList = new List<string>();
finList.AddRange(fin.Split('\n'));
for (int x = 0; x < finList.Count; x++)
{
if (finList[x] == "void" || finList[x] == "_Bool" || finList[x] == "bool" || finList[x] == "unsigned")
{
finList[x] = im not sure what to do here
fin = string.Empty;
}
}
for (int x = 0; x < finList.Count; x++)
{
fin += finList[x];
}
任何方向或帮助将不胜感激。我对C#和C相对来说比较新,所以如果我没有使用正确的术语,请耐心等待。我认为在“)”结束函数的字符串/行是最有意义的,但我不确定如何做到这一点。 在此先感谢!
答
快速和肮脏的解决办法是这样的:
int bracketLevel = 0;
int squareBracketLevel = 0;
var methods = new List<string>();
var isMethodMode = true; // track if we are in method definition or in method body
var isMethod = false; // if we have seen parenthesis in definition
var builder = new StringBuilder();
for (int i = 0; i < fin.Length; i++)
{
if (isMethodMode)
{
switch (fin[i])
{
case '(':
isMethod = true;
builder.Append(fin[i]);
bracketLevel++;
break;
case ')':
builder.Append(fin[i]);
bracketLevel--;
break;
case '{':
if (bracketLevel > 0) continue;
if (isMethod)
{
methods.Add(builder.ToString().Trim());
builder.Clear();
isMethod = false;
}
isMethodMode = false;
squareBracketLevel++;
break;
default:
builder.Append(fin[i]);
break;
}
}
else
{
switch (fin[i])
{
case '{':
squareBracketLevel++;
break;
case '}':
squareBracketLevel--;
if (squareBracketLevel == 0)
{
isMethodMode = true;
}
break;
}
}
}
可变fin
包含加载C文件。尽管这适用于你的例子有几个假设:
- C代码是有效的(无错配的括号)
- 其中将包括括号(这包括注释功能在评论中已经提到)没有评论
- 体块不包含字符串花括号常量
如果这些假设不成立的,那么你将不得不看看到解析器生成将解析C文件,并生成抽象语法树为你从中你可以提取所需的信息。一个例子是ANTLR。 C语法也可在C.g4。
如果您想要一个强大的解决方案,您必须编写一个C语法分析器并提取所有函数定义。即使您修复了代码中的错误,它也会在注释掉的函数上失败,然后在所有其他类型的角落中失败。你需要用C#编写吗?使用脚本语言!他们是为此而制造的。 –
我同意,编写脚本似乎是一个更简单的解决方案,但该项目需要C#,它应该是一种学习如何将C转换为C#的方法。但感谢您的意见。我甚至没有想过评论的问题。 – John
而且你可能忘记了引用的字符串,并且对代码的格式做出了无效的假设。你想解析C代码,并且需要C代码解析器,无论你使用哪种语言,这些解析器都需要数千行代码。你的问题的答案是:为C语言获取语法和词法分析器文件并生成一个编译器!其他一切只是非法假设的破解。 –