今天我在想怎样的函数声明好看……于是写了段代码自动排版,但是后来我觉得效果不太好,还是要灵活一点比较好。
这个工具能将一般的 C++ 头文件的函数声明排版成这样:
// 图像缩放(基于 Win32 API,保留透明度信息)
IMAGE
ZoomImage_Win32_Alpha(
IMAGE* pImg,
int width,
int height
);
生成的 output.h 还需要放到 VS 里面进行格式对齐,因为我没有补 Tab 之类的。
但是后来我觉得又不太好看,算了。
代码写都写了,就留个纪念。现在基本功能可以了,但是还有一点小 Bug:一个参数的函数排版会失败,构造函数排版会失败,有时候很小一部分函数排版会失败,其余都可以。
#include <stdio.h>
#include <conio.h>
#include <string>
#include <vector>
#include <fstream>
#include <streambuf>
using namespace std;
// 获取文件内容
string GetFile(const char* filepath)
{
ifstream t(filepath);
string str((istreambuf_iterator<char>(t)), istreambuf_iterator<char>());
t.close();
if (str.size() <= 0)
{
printf("\n\nopen %s error.", filepath);
_getch();
exit(-1);
}
return str;
}
bool isSpace(char c)
{
return c == ' ' || c == '\t';
}
bool isReturn(char c)
{
return c == '\r' || c == '\n';
}
bool isBracket(char c)
{
return c == '(';
}
bool isBackBracket(char c)
{
return c == ')';
}
bool isSemicolon(char c)
{
return c == ';';
}
bool StrCompare_Head(string res, string reference)
{
for (size_t i = 0; i < reference.size() && i < res.size(); i++)
{
if (res[i] != reference[i])
{
return false;
}
}
return true;
}
void SkipSpace(string res, size_t& index)
{
for (; index < res.size(); index++)
{
if (!isSpace(res[index]))
{
return;
}
}
}
void SkipReturn(string res, size_t& index)
{
for (; index < res.size(); index++)
{
if (!isReturn(res[index]))
{
return;
}
}
}
void SkipComment(string res, size_t& index)
{
while (StrCompare_Head(&res[index], "//"))
{
for (; index < res.size(); index++)
{
if (isReturn(res[index]))
{
SkipReturn(res, index);
break;
}
}
}
}
// 返回跳过的字符长度
size_t SkipWord(string res, size_t& index)
{
size_t sum = 0;
for (; index < res.size(); index++)
{
if (isReturn(res[index]) || isSpace(res[index]) || isBracket(res[index]))
{
SkipReturn(res, index);
SkipSpace(res, index);
return sum;
}
else
{
sum++;
}
}
return sum;
}
// 遇到第一个无匹配的反括号时返回
void SkipBrackets(string res, size_t& index)
{
for (int num = 0; index < res.size(); index++)
{
if (isBracket(res[index]))
{
num++;
}
else if (isBackBracket(res[index]))
{
num--;
}
// 不成对的反括号
if (num < 0)
{
index++;
return;
}
}
}
bool isFunction(string res, size_t& index)
{
SkipSpace(res, index);
size_t begin = index;
if (SkipWord(res, index) && SkipWord(res, index))
{
if (isBracket(res[index]))
{
index++;
SkipBrackets(res, index);
if (isSemicolon(res[index]))
{
index = begin;
return true;
}
}
}
return false;
}
void NewLine(string& res, size_t& index)
{
res.insert(res.begin() + index, '\n');
index++;
}
void ProcFunc(string& res, size_t& index)
{
SkipWord(res, index);
if (!isReturn(res[index]))
{
NewLine(res, index);
}
SkipWord(res, index);
index++; // 跳过函数括号
// 函数无参数
if (isBackBracket(res[index]))
{
index++;
SkipReturn(res, index);
return;
}
for (; index < res.size(); index++)
{
if (!isReturn(res[index]))
{
NewLine(res, index);
}
for (; index < res.size(); index++)
{
// 参数,继续换行
if (res[index] == ',')
{
break;
}
// 函数声明结束
if (StrCompare_Head(&res[index], ");"))
{
index--;
// 往前找
size_t i = 0;
for (; index > 0; index--, i++)
{
// 已有换行,无需再换
if (isReturn(res[index]))
{
break;
}
// 若存在文本,则换行
else if (!isSpace(res[index]))
{
index++;
NewLine(res, index);
break;
}
}
index += i + 2; // 跳过反括号
SkipReturn(res, index);
return;
}
}
}
}
void Proc(string& res)
{
for (size_t index = 0; index < res.size(); index++)
{
SkipReturn(res, index);
SkipSpace(res, index);
SkipComment(res, index);
if (isFunction(res, index))
{
ProcFunc(res, index);
}
// 不是函数则进入下一行
else
{
for (; index < res.size(); index++)
{
if (isReturn(res[index]))
{
break;
}
}
}
}
}
int main()
{
char buf[1024] = { 0 };
printf("Type your header file path:\n");
string strCode = GetFile(gets_s(buf));
Proc(strCode);
ofstream out(L"output.h");
out.write(strCode.c_str(), strCode.size());
out.close();
printf("%s\n", strCode.c_str());
_getch();
return 0;
}