目录
前言
在学习STM32开发板时,需要使用到这个开发板的源程序代码。但源程序代码的格式看起来不是很好看,有许多空白行或者每行代码开头的缩进长短不一。我一开始是通过纯手工的方式进行修改,但后面发现需要修改的代码太多了,我就想用代码实现这个功能,让修改之后的代码格式更加的工整。对于我来说写代码最看重的就是代码格式了,如果代码格式不好,那么就很难去看懂整个代码的逻辑。
修改之前的代码:
修改之后的代码:
代码编写
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<filesystem>
#include<vector>
#include<windows.h>
#include<comdef.h>
#include<climits>
#include<stack>
#include<iostream>
#include <iostream>
using namespace std;
namespace fs = std::filesystem;
bool hasReadWriteAccess(LPCTSTR filePath)//检测文件是否有读写权限
{
DWORD attributes = GetFileAttributes(filePath);
if (attributes == INVALID_FILE_ATTRIBUTES)
{
// 文件不存在或错误
return false;
}
// 检查是否设置了只读属性
if ((attributes & FILE_ATTRIBUTE_READONLY) != 0)
{
// 文件是只读的,所以可能没有写权限
return false;
}
// 注意:这只是初步检查,不能确认具体读写权限
return true;
}
void write_c_file_paths_to_txt(vector<string>& stringArray, string& name, int& quantity) {//将.c,.h,.cpp文件存入数组中
// 遍历指定目录及其子目录
for (const auto& entry : fs::recursive_directory_iterator(name))
{
// 检查文件是否为.c文件
if (entry.is_regular_file() && (entry.path().extension() == ".c" || entry.path().extension() == ".h" || entry.path().extension() == ".cpp" || entry.path().extension() == ".txt"))
{
// 将.c文件的完整路径写入到数组中
stringArray.push_back(entry.path().string());
quantity++;
}
}
}
void Modify_1(int& L_buf, char(&buf)[10000])//将每一行末尾的Tab格式和空格清空
{
for (int i = L_buf - 1; i >= 0; --i)
{
if (buf[i] == ' ' || buf[i] == '\t')
{
buf[i] = '\0';
}
else
{
break;
}
}
L_buf = (int)(strlen(buf));//字符串的长度
}
void Modify_2(int& slash, int& L_buf, char(&buf)[10000], bool option)//将每一行开头的Tab格式和空格清空,末尾是\除外
{
if (option == false)//用于判断是否是注释
{
while (slash != 1 && (buf[0] == ' ' || buf[0] == '\t'))
{
for (int i = 0; i < L_buf - 1; i++)
{
buf[i] = buf[i + 1];
}
buf[L_buf - 1] = '\0';
}
L_buf = strlen(buf);
if (buf[L_buf - 1] == '\\')//用于记录\,并对后一行开头的Tab和空格不做处理
{
slash = 1;
}
else
{
slash = 0;
}
}
else
{
while (buf[0] == ' ' || buf[0] == '\t')
{
for (int i = 0; i < L_buf - 1; i++)
{
buf[i] = buf[i + 1];
}
buf[L_buf - 1] = '\0';
}
}
L_buf = (int)(strlen(buf));//字符串的长度
}
void Modify_3(int& L_buf, char(&buf)[10000])//用于删除‘符号’两边的空格
{
bool signal2[10000] = {false};
for (int i = 1; i < L_buf; ++i)
{
if (buf[i] == '"' && buf[i - 1] != '\\')
{
signal2[i] = true;
++i;
for (; i < L_buf; ++i)
{
signal2[i] = true;
if (buf[i] == '"' && buf[i - 1] != '\\')
{
break;
}
}
}
}
for (int i = L_buf - 1; i >= 0; --i)
{
if (signal2[i] == false && (buf[i] == '=' || buf[i] == ',' || buf[i] == ';' || buf[i] == '(' || buf[i] == ')' || buf[i] == '[' || buf[i] == ']' || buf[i] == '+' || buf[i] == '-' || buf[i] == '*' || buf[i] == '/' || buf[i] == '!' || buf[i] == '&' || buf[i] == '~' || buf[i] == '%' || buf[i] == '<' || buf[i] == '>' || buf[i] == '|' || buf[i] == '{' || buf[i] == '}'))
{
while (buf[i + 1] == ' ' || buf[i + 1] == '\t')
{
for (int j = i + 1; j < L_buf - 1; j++)
{
buf[j] = buf[j + 1];
}
buf[L_buf - 1] = '\0';
L_buf = (int)(strlen(buf));//字符串的长度
}
while (buf[i - 1] == ' ' || buf[i - 1] == '\t')
{
for (int j = i - 1; j < L_buf - 1; j++)
{
buf[j] = buf[j + 1];
}
buf[L_buf - 1] = '\0';
L_buf = (int)(strlen(buf));//字符串的长度
}
}
}
}
void Modify_4(int& bracket, int& L_buf, char(&buf)[10000], ofstream& fout, bool option, bool& L_annotation)//用于对每一行的开头进行Tab缩进,缩进数量由bracket决定
{
int brackets_s = 0;
stack<pair<int,char>> s;
bool signal2[10000] = { false };
for (int i = 1; i < L_buf; ++i)
{
if (buf[i] == '"' && buf[i - 1] != '\\')
{
signal2[i] = true;
++i;
for (; i < L_buf; ++i)
{
signal2[i] = true;
if (buf[i] == '"' && buf[i - 1] != '\\')
{
break;
}
}
}
}
if (option == false)//用于判断是否是注释
{
int test = -1;//用于记录//或/*的位置
for (int i = 0; i < L_buf - 1; ++i)
{
if (signal2[i] != true)
{
if (buf[i] == '/' && buf[i + 1] == '/')
{
test = i;
break;
}
if (buf[i] == '/' && buf[i + 1] == '*')
{
L_annotation = true;
test = i;
if (buf[L_buf - 2] == '*' && buf[L_buf - 1] == '/')
{
L_annotation = false;
}
break;
}
}
}
if (test == -1)
{
test = L_buf;
}
if (L_buf != 0 && L_buf != 1)
{
for (int i = 0; i < test; ++i)
{
if (buf[i] == '{')
{
++brackets_s;
s.push(make_pair(i, '{'));
}
else if (buf[i] == '}')
{
--brackets_s;
if (!s.empty() && s.top().second == '{')
{
s.pop();
}
else
{
s.push(make_pair(i, '}'));
}
}
}
int size = s.size();
if (brackets_s == 0)
{
if (buf[0] == '}')
{
for (int i = 0; i < bracket - 1; ++i)
{
fout << '\t';
}
fout << buf << endl;
}
else
{
for (int i = 0; i < bracket; ++i)
{
fout << '\t';
}
fout << buf << endl;
}
}
else if (brackets_s < 0)
{
int* brackets = new int[size];
for (int i = size - 1; i >= 0; --i)
{
if (!s.empty())
{
brackets[i] = s.top().first;
s.pop();
}
}
int j = 0;
for (int i = 0; i < size; ++i)
{
if (brackets[i] != 0)
{
for (int k = 0; k < bracket; ++k)
{
fout << '\t';
}
for (; j < brackets[i]; ++j)
{
fout << buf[j];
}
fout << endl;
}
if (i == size - 1)
{
for (int k = 0; k < bracket - 1; ++k)
{
fout << '\t';
}
for (; j < L_buf; ++j)
{
fout << buf[j];
}
fout << endl;
--bracket;
}
else
{
if (buf[brackets[i] + 1] == ',' || buf[brackets[i] + 1] == ';')
{
for (int k = 0; k < bracket - 1; ++k)
{
fout << '\t';
}
for (; j < brackets[i] + 2; ++j)
{
fout << buf[j];
}
fout << endl;
--bracket;
}
else
{
for (int k = 0; k < bracket; ++k)
{
fout << '\t';
}
for (; j < brackets[i] + 1; ++j)
{
fout << buf[j];
}
fout << endl;
--bracket;
}
}
}
delete[] brackets;
}
else
{
int* brackets = new int[size];
for (int i = size - 1; i >= 0; --i)
{
if (!s.empty())
{
brackets[i] = s.top().first;
s.pop();
}
}
int j = 0;
for (int i = 0; i < size; ++i)
{
if (brackets[i] != 0)
{
for (int k = 0; k < bracket; ++k)
{
fout << '\t';
}
for (; j < brackets[i]; ++j)
{
fout << buf[j];
}
fout << endl;
}
if (i == size - 1)
{
for (int k = 0; k < bracket; ++k)
{
fout << '\t';
}
fout << buf[j] << endl;
++j;
if (j + 1 < L_buf)
{
for (int k = 0; k < bracket + 1; ++k)
{
fout << '\t';
}
for (; j < L_buf; ++j)
{
fout << buf[j];
}
fout << endl;
}
++bracket;
}
else
{
for (int k = 0; k < bracket; ++k)
{
fout << '\t';
}
for (; j < brackets[i] + 1; ++j)
{
fout << buf[j];
}
fout << endl;
++bracket;
}
}
delete[] brackets;
}
}
else if(L_buf == 1)
{
if (buf[0] == '}')
{
for (int i = 0; i < bracket - 1; ++i)
{
fout << '\t';
}
--bracket;
}
else
{
for (int i = 0; i < bracket; ++i)
{
fout << '\t';
}
if (buf[0] == '{')
{
++bracket;
}
}
fout << buf << endl;
}
}
else
{
for (int i = 0; i < bracket; ++i)
{
fout << '\t';
}
fout << buf << endl;
}
L_buf = (int)(strlen(buf));//字符串的长度
}
void Modify_5(char(&buf)[10000])//将buf清空
{
for (int i = 0; i < 10000; ++i)
{
if (buf[i] != '\0')
{
buf[i] = '\0';
}
}
}
int main()
{
ifstream fin;//读文件
ofstream fout;//写文件
string ST;//输入选项或文件路径
const char* cp = "_COPY";
char buf[10000] = { 0 };
int bracket = 0;//用于记录括号
int select = 0;//输入选项
int slash = 0;//用于记录斜杠
string name;//文件名
string COPY;//复制文件名
int record = -1;//记录所有文件是否整理成功
bool L_annotation = false;//长注释
bool code = false;//代码行标志
bool _sign = false;//用于判断除空格,Tab键,以*号开头的是否是注释的结束
bool record_t = true;//用于记录文件路径是文件还是文件夹
int L_buf = 0;//字符串的长度
bool mark = false;//用于记录每一行是否有双引号或单引号
const char* filename = nullptr;//文件名
vector<string>stringArray;//string数组
int quantity = 0;//用于记录文件路径的数量
while (1)
{
cout << " 《《文件代码整理》》" << endl;
cout << "提示:可以直接输入选项,文件夹和文件" << endl;
cout << "1.继续使用当前文件,文件夹" << endl << "2.退出" << endl;
cout << "文件是否整理成功:";
if (record == 0)
cout << "否" << endl;
else if (record == 1)
cout << "是" << endl;
else
cout << "" << endl;
cout << "案例1:C:\\Users\\lenovo\\Desktop\\我的文件" << endl;
cout << "案例2:C:/Users/lenovo/Desktop/我的文件" << endl;
cout << "提示:输入的路径必须是绝对路径,文件中每一行处理的最大字符数为1万。" << endl;
cout << " 文件中的\".\"只能存在在后缀名的前一位,否则文件处理会出错" << endl;
cout << "请输入需要整理格式的文件名:";
record_t = true;//文件夹
quantity = 0;//用于记录文件路径的数量
cin >> ST;
for (int i = 0; i < ST.size(); ++i)
{
if (ST[i] == '\\')
{
ST[i] = '/';
}
}
if (ST == "1")
{
if (name == "")
{
cout << "当前文件路径为空!" << endl;
do
{
cout << "请重新输入:";
cin >> name;
if (name == "2")
{
cout << "系统退出" << endl;
return 0;
}
else
{
for (int i = name.size() - 1; i >= 0; --i)
{
if (name[i] == '/')
{
for (int j = name.size() - 1; j >= i; --j)
{
if (name[j] == '.')
{
record_t = false;//文件
}
}
break;
}
}
if (record_t == false)
{
stringArray.push_back(name);
quantity = 1;
}
else
{
write_c_file_paths_to_txt(stringArray, name, quantity);
}
}
} while (name == "2");
}
else
{
for (int i = name.size() - 1; i >= 0; --i)
{
if (name[i] == '/')
{
for (int j = name.size() - 1; j >= i; --j)
{
if (name[j] == '.')
{
record_t = false;//文件
}
}
break;
}
}
if (record_t == false)
{
stringArray.push_back(name);
quantity = 1;
}
else
{
write_c_file_paths_to_txt(stringArray, name, quantity);
}
}
}
else if (ST == "2")
{
return 0;
}
else
{
name = ST;//文件名
for (int i = name.size() - 1; i >= 0; --i)
{
if (name[i] == '/')
{
for (int j = name.size() - 1; j >= i; --j)
{
if (name[j] == '.')
{
record_t = false;//文件
}
}
break;
}
}
if (record_t == false)
{
stringArray.push_back(name);
quantity = 1;
}
else
{
write_c_file_paths_to_txt(stringArray, name, quantity);
}
}
for (int i = 0; i < quantity; ++i)
{
for (int j = 0; j < stringArray[i].size(); ++j)
{
if (stringArray[i][j] == '\\')
{
stringArray[i][j] = '/';
}
}
}
for (int i = 0; i < quantity; ++i)
{
bracket = 0;
_bstr_t bstr(stringArray[i].c_str());
LPCTSTR lpctstrValue = (LPTSTR)bstr;
if (hasReadWriteAccess(lpctstrValue) == true)//读写权限检测
{
name = stringArray[i];
COPY = name;
for (int i = size(name) - 1; i >= 0; i--)//创建复制文件
{
if (name[i] == '.')
{
COPY.insert(i, cp, 5);
break;
}
}
ofstream create_file(COPY);//创建COPY文件
if (!create_file.is_open())
{
cout << "COPY文件创建失败,程序出现异常!- 1" << endl;
return 0;
}
create_file.close();//关闭文件
fout.open(COPY, ios::out | ios::app);
if (fout.fail())//文件打开失败
{
cout << "文件打开失败,程序出现异常!- 2" << endl;
return 0;
}
fin.open(name, ios::in);
if (fin.fail())//文件打开失败
{
cout << "文件打开失败,程序出现异常!- 3" << endl;
fin.close();//关闭文件
fout.close();//关闭文件
filename = COPY.data();
record = 0;
if (remove(filename) != 0)//用于删除文件
{
cout << "文件删除失败,请手动删除" << COPY << "文件!" << endl;
return 0;
}
}
else
{
while (fin.getline(buf, sizeof(buf)))
{
L_buf = (int)(strlen(buf));//字符串的长度
if (slash == 1)
{
int signal = 0;//用于标记是否存在空格,和\t之外的字符
for (int i = 0; i < L_buf; ++i)
{
if (buf[i] != ' ' && buf[i] != '\t')
{
signal = 1;
break;
}
}
if (L_buf == 0 || signal == 0)
{
fout << endl;
}
}
for (int i = 0; i <= L_buf - 2; ++i)
{
if (buf[i] != ' ' && buf[i] != '\t')
{
if (buf[i] == '#')
{
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
Modify_2(slash, L_buf, buf, false);//将每一行开头的Tab格式和空格清空,末尾是\除外
fout << buf << endl;
break;
}
else if (buf[i] == '/' && buf[i + 1] == '/')
{
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
Modify_2(slash, L_buf, buf, true);//将每一行开头的Tab格式和空格清空,末尾是\除外
Modify_4(bracket, L_buf, buf, fout, true, L_annotation);//用于对每一行的开头进行Tab缩进,缩进数量由bracket决定
break;
}
else if (buf[i] == '/' && buf[i + 1] == '*')
{
L_annotation = true;
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
if (buf[L_buf - 2] == '*' && buf[L_buf - 1] == '/')
{
L_annotation = false;
Modify_2(slash, L_buf, buf, true);//将每一行开头的Tab格式和空格清空,末尾是\除外
Modify_4(bracket, L_buf, buf, fout, true, L_annotation);//用于对每一行的开头进行Tab缩进,缩进数量由bracket决定
}
else
{
fout << buf << endl;
}
break;
}
else if (buf[i] == '*')
{
for (int j = i; j <= L_buf - 2; ++j)
{
if (buf[j] == '*' && buf[j + 1] == '/')
{
_sign = true;
break;
}
}
if (_sign == true)
{
_sign = false;
L_annotation = false;
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
fout << buf << endl;
}
else
{
if (L_annotation == true)
{
for (int j = 0; j < L_buf - 2; ++j)
{
if (buf[j] == '*' && buf[j + 1] == '/')
{
L_annotation = false;
break;
}
}
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
fout << buf << endl;
}
else
{
code = true;
}
}
break;
}
else
{
if (L_annotation == true)
{
for (int j = 0; j < L_buf - 1; ++j)
{
if (buf[j] == '*' && buf[j + 1] == '/')
{
L_annotation = false;
break;
}
}
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
fout << buf << endl;
}
else
{
code = true;
}
break;
}
}
else
if (true)
{
if (buf[i + 1] == '}' || buf[i + 1] == '{' || buf[i + 1] == '(' || buf[i + 1] == ')' || buf[i + 1] == '[' || buf[i + 1] == ']' || buf[i + 1] == '<' || buf[i + 1] == '>')
{
code = true;
break;
}
}
}
if (L_buf == 1)
{
if (L_annotation == true)
{
fout << buf << endl;
}
else
{
code = true;
}
}
if (code == true)
{
code = false;
Modify_1(L_buf, buf);//将每一行末尾的Tab格式和空格清空
int slash_2 = slash;
Modify_2(slash, L_buf, buf, false);//将每一行开头的Tab格式和空格清空,末尾是\除外
if (slash_2 == 0)
{
Modify_3(L_buf, buf);//用于删除‘符号’两边的空格
Modify_4(bracket, L_buf, buf, fout, false, L_annotation);//用于对每一行的开头进行Tab缩进,缩进数量由bracket决定
}
else
{
fout << buf << endl;
}
Modify_5(buf);//将buf清空
}
}
fin.close();
fout.close();
ofstream truncateFile(name, ios::trunc);//清空文件内容
fin.open(COPY, ios::in);//读文件
if (fin.fail())//文件打开失败
{
cout << "文件打开失败,程序出现异常!- 4" << endl;
return 0;
}
fout.open(name, ios::out | ios::app);//写文件
if (fout.fail())//文件打开失败
{
cout << "文件打开失败,程序出现异常!- 5" << endl;
return 0;
}
while (fin.getline(buf, sizeof(buf)))//将COPY文件中的内容全部转移到name文件中
{
fout << buf << endl;
for (int i = 0; i < 10000; ++i)
{
if (buf[i] != '\0')
{
buf[i] = '\0';
}
}
}
fin.close();//关闭文件
fout.close();//关闭文件
filename = COPY.data();
if (remove(filename) != 0)//用于删除文件
{
cout << "文件删除失败,请手动删除" << COPY << "文件!" << endl;
record = 0;
return 0;
}
}
}
cout << stringArray[i] << endl;
}
record = 1;
system("cls");//清空终端
}
}
该代码的实现逻辑非常简单,这里的实现过程在代码中都有解释。
打包
将该程序打包之后,使用会更加简单,并且可以将安装包进行分享。
首先将Debug选项换成Release,之后再点击运行。
在该项目的工程文件夹里,新建一个打包文件。
然后再点击X64->点击Release,将.exe文件进行复制,再回到打包文件夹下面,将该exe文件粘贴到此文件夹下。
之后需要使用到安装包打包封装工具Inno Setup v5.5.9汉化优化版。
这个可以在网上直接进行免费下载。
打开该软件选择Create a new script file using the Script Wizard(创建新的脚本文件)
点击OK(确定)
之后点击Next(下一步)
这里需要设置Application name(应用程序名称),Application version(应用程序版本),APPlication publisher(应用程序发布者),Application website(应用程序网站)。
之后点击Next(下一步)->再点击Next(下一步)
这里需要选择要打包的exe文件的名字,不要使用他提供默认的exe文件,这里我选择了要打包的exe文件。
之后点击Next(下一步)->点击Next(下一步)->点击Next(下一步)
然后选择语言为English,这里好像没有中文版本。
之后点击Next(下一步),这里需要设置Custom compiler output folder(自定义编译器输出文件夹)就是生成文件的存放位置,Compiler output base file name(编译器输出基本文件名)就是给生成文件取名字,Custom Setup icon file(自定义安装程序图标文件)这里我没有设置,Setup password(安装密码)这里也没有设置。设置完之后点击Next(下一步)->点击Finish(完成)就OK了。
然后点击否,生成的这一长串是脚本代码,不需要管。
之后点击Build(构建)->点击compile(编译)->点击是,之后需要保存脚本代码,这个随便保存不需要管了。
然后整个打包过程就完成了。
具体的打包过程可以观看下面这个视频。C/C++编程技术讲解:好不容易做好了一个程序,想装一下B,却只会发送源码,可是朋友根本没有编译器怎么办?来,让我教你把程序打包成EXE.谁也不能阻止我装逼了._哔哩哔哩_bilibili
这是打包好的安装包
程序运行
安装好了之后,就会生成一个可执行文件。
点击之后打开运行界面。
然后在桌面上新建一个txt文件,将需要修改格式的代码复制粘贴到该txt文件上保存,之后在该程序上输入文件的绝对路径回车就可以了。
然后txt文件里面的代码格式就修改好了。
如果需要继续向txt文件里复制粘贴没有修改格式的代码,可以将txt文件清空,再将未修改格式的代码粘贴上去,然后保存关闭txt文件。再在程序上直接输入1就可以持续的进行修改了。
总结
多学习知识多实践能解决更多的烦恼。