程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> 美化你的代碼 vb(VBS)代碼格式化的實現代碼

美化你的代碼 vb(VBS)代碼格式化的實現代碼

編輯:C語言基礎知識

不過VB.NET確實有許多VB6沒有的新功能,代碼的自動排版就是一項,這也正是我們今天要實現的功能——VB代碼格式化。
先看下實現的效果:

格式化前:
代碼如下:

For i = 0 To WebBrowser1.Document.All.length - 1
If WebBrowser1.Document.All(i).tagName = "HTML" Then
strContent = strContent & WebBrowser1.Document.All(i).innerHTML
Exit For
End If
Next

格式化後:
代碼如下:

For i = 0 To WebBrowser1.Document.All.length - 1
If WebBrowser1.Document.All(i).tagName = "HTML" Then
strContent = strContent & WebBrowser1.Document.All(i).innerHTML
Exit For
End If
Next

C++水平一直很爛,所以選擇了C++作為練手語言寫了這個簡陋的VB代碼格式化工具。代碼不長,才200多行,標准C++實現。另外,為了徹底打消某些人繼續使用VC6的念頭,使用了auto關鍵字嘿嘿。好吧,廢話少說,直接上代碼:
代碼如下:

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<fstream>
using namespace std;

//判斷是否為空格
bool isSpace(const char chr)
{
return chr == ' ';
}

//去除左側空白
void leftTrim(string &str)
{
string::iterator p=find_if(str.begin(),str.end(),not1(ptr_fun(isSpace)));
str.erase(str.begin(),p);
}

//去除右側空白
void rightTrim(string& str)
{
string::reverse_iterator p=find_if(str.rbegin(),str.rend(),not1(ptr_fun(isSpace)));
str.erase(p.base(),str.end());
}

//去除兩側空白
string trim(const string& str)
{
string strRet(str);
leftTrim(strRet);
rightTrim(strRet);
return strRet;
}

//轉換成小寫
string toLower(const string& str)
{
string strRet(str);
transform(strRet.begin(),strRet.end(),strRet.begin(),(int (*)(int))tolower);
return strRet;
}

//判斷是否以給定關鍵字開頭
bool startWith(const vector<string>& vecCodeKeywords,const string& strCodeLine)
{
string line(toLower(strCodeLine));
for(auto keyword=vecCodeKeywords.begin(); keyword!=vecCodeKeywords.end(); keyword++)
if(line.find(*keyword + " ")==0 || line== *keyword)
return true;
return false;
}

//IF...Then...特殊檢查
bool checkForIfThen(const string& strCodeLine)
{
vector<string> vecIf;
vecIf.push_back("if");
if(!startWith(vecIf,strCodeLine))
return false;
if(toLower(strCodeLine).find("then")==string::npos)
return false;
string line(trim(toLower(strCodeLine)));
if(line.length()<7)
return false;
return !(line.substr(line.length()-4,4) == "then");
}

//格式化給定行並標記相關信息
int formatAndMarkLine(string& strCodeLine)
{
//起始關鍵字 "if","for","[Private | Friend | Public] [Static] [Sub | Function | Property | Type]","with","do","select"
vector<string> vecStartKeywords;
vecStartKeywords.push_back("if");
vecStartKeywords.push_back("for");
vecStartKeywords.push_back("with");
vecStartKeywords.push_back("do");
vecStartKeywords.push_back("select");
string _pfp[] = {"private","friend","public"}; //可空
string _s[] = {"static"}; //可空
string _sfpt[] = {"sub","function","property","type"};
//_pfp _s 都為空
for(auto i=0; i<4; i++)
vecStartKeywords.push_back(_sfpt[i]);
//_pfp 為空
for(auto i=0; i<4; i++)
vecStartKeywords.push_back(_s[0] + " " + _sfpt[i]);
//_s 為空
for(auto i=0; i<4; i++)
for(auto j=0; j<3; j++)
vecStartKeywords.push_back(_pfp[j] + " " + _sfpt[i]);
//_pfp _s 都不為空
for(auto i=0; i<4; i++)
for(auto j=0; j<3; j++)
vecStartKeywords.push_back(_pfp[j] + " " + _s[0] + " " + _sfpt[i]);

//終止關鍵字 "end if","next","End [Sub | Function | Property | Type]","end with","loop","end select"
vector<string> vecEndKeywords;
vecEndKeywords.push_back("end if");
vecEndKeywords.push_back("next");
vecEndKeywords.push_back("end with");
vecEndKeywords.push_back("loop");
vecEndKeywords.push_back("end select");
for(auto i=0; i<4; i++)
vecEndKeywords.push_back("end " + _sfpt[i]);

//中間關鍵字 "else","elseif","case"
vector<string> vecMiddleKeywords;
vecMiddleKeywords.push_back("else");
vecMiddleKeywords.push_back("elseif");
vecMiddleKeywords.push_back("case");

auto mark = 0;
char c;
auto n=0;
string line;
auto quote = false; //雙引號狀態
/*
規則:
雙引號內單引號不考慮,否則後面內容成為注釋
*/
auto space = true; //空白符狀態 false 表示未遇到任何空白符
while((c=strCodeLine[n++]))
{
switch(c)
{
case ' ':
case '\t':
if(quote)
{
line += c;
}
else
{
if(!space)
{
line += c;
space = true;
}
}
break;
case '"':
space = false;
quote = !quote;
line += c;
break;
case '\'':
space = false;
if(quote)
line += c;
else
{
line += " '"; //MsgBox("itianda") '單引號前有一個空格
while((c=strCodeLine[n++])) //直接附加單引號後面內容
line += c;
continue;
}
break;
case '_': //續行符
space = false;
line += c;
if(!quote && n==(int)strCodeLine.length() && n-2>=0 && strCodeLine[n-2]==' ')
mark |= 0x80; //10000000
break;
default:
space = false;
line += c;
}
}
strCodeLine = line;
if(startWith(vecStartKeywords,line) && !checkForIfThen(line))
mark += 1;
if(startWith(vecEndKeywords,line))
mark += 2;
if(startWith(vecMiddleKeywords,line))
mark += 3;
return mark;
}

//將代碼按行分割
void splitToLines(const string& strCode, vector<string>& vecCodeLines)
{
vecCodeLines.clear();
char c;
auto n=0;
string line;
while((c=strCode[n++]))
{
if(c!='\n')
line += c;
else
{
vecCodeLines.push_back(line);
line.clear();
}
}
if(line.length()) //最後一行為空則捨去
vecCodeLines.push_back(line);
}

//格式化給定代碼
void formatCode(string& strCode,const string& strIndentString)
{
vector<string> vecLines; //所有代碼行
splitToLines(strCode,vecLines); //獲取所有代碼行
if(vecLines.size()==0)
{
return;
}
auto indentLevel = 0; //縮進級別
auto incompleteLine = false; //是否是未結束行
for(auto line=vecLines.begin(); line!=vecLines.end(); line++)
{
auto indent = indentLevel;
auto mask = formatAndMarkLine(*line);
switch(mask & ~0x80)
{
case 0:
break;
case 1:
indentLevel++;
break;
case 2:
indent--;
indentLevel--;
break;
case 3:
indent--;
break;
}
if(incompleteLine)
indent++;
incompleteLine = mask & 0x80;
if(indent<0)
indent = 0;
if(indentLevel<0)
indentLevel = 0;
string strIndent;
for(auto i=0; i<indent; i++)
strIndent += strIndentString;
*line = strIndent + *line;
}
strCode.clear();
for(auto line=vecLines.begin(); line!=vecLines.end(); line++)
strCode+= trim(*line).length() ? "\n" + *line : "";
}

int main()
{
string indentString = " ";
string code;
ifstream inputFile("in.txt");
string line;
while(getline(inputFile,line))
{
code += line + "\n";
}
formatCode(code,indentString);
ofstream outputFile("out.txt");
outputFile<<"Your beautiful code:"<<endl<<
"-------------------------------------------------------------------"
<<endl<<code<<endl<<endl<<
"-------------------------------------------------------------------"
<<endl<<
" Formatted by itianda's PUVBFormatter"
<<endl<<
" http://www.programup.com/blog"
<<endl;
return 0;
}

看過代碼應該知道這是多麼基本的實現了吧,好多細節都沒有去仔細處理,比如沒有考慮冒號連接多行的情況,所以如果你希望使用此工具,請不要把多行語句寫到一行哦!

最後提供一個我編譯好的EXE下載:PUVBFormatter

更新:
增加select case…end select關鍵字,感謝jjww2999網友的反饋。
本文來自: itianda's blog

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved