编译原理——语法分析器(SLR)

识别语法结构:

  • 变量声明(不含变量初始化)
  • if单条件分支语句以及if else 双条件分支语句
  • for循环和while循环语句
  • 赋值语句 ,四则运算,逻辑判断复合语句
  • 函数声明 函数调用

文法

//其中$作为标识符判断  @常数值判断
Z->S
S->while(E)S
S->E;S
S->;S
S->for(E;E;E)S
S->CM;S
S->C$(W){SreturnE;}S
S->$(H);S
M->M,$
M->$
H->$H
H->nH
H->,$H
H->,@H
H->#
C->char
C->int
C->double
S->if(E)S
S->SelseS
S->{S}S
S->#
E->EOE
E->(E)
E->@
E->$
W->#
W->C$,W
W->C$
O->+
O->-
O->/
O->*
O->>
O->=
O->>=
O-><
O-><=
O->!=
O->==
O->&
O->&&
O->|
O->||

算法描述及实验步骤

数据结构解析

  • product—存放文法
  typedef struct Product{char left;char right[N];int length;}Product;
  • Follow—存放文法的follow集
  typedef struct Follow{char V;vector<char> fset;}Follow;
  • I—存放状态闭包集
  typedef struct I{vector<Product> pros;}I;

主要函数解析

  • SLR函数设计

    • 该函数能够实现将文件中输入好的文法自动根据SLR状态转移算法形成Action表和Goto表

    • 事先读入文法,并获取产生式中出现的终结符集合以及非终结符集合

    • 修正文法,将产生式右部添加 . 号,便于算法模拟

      Z->.S
      S->.while(E)S
      S->.E;S
      S->.;S
      S->.for(E;E;E)S
      S->.CM;S
      S->.C$(W){SreturnE;}S
      S->.$(H);S
      M->.M,$
      M->.$
      H->.$H
      H->.nH
      H->.,$H
      H->.,@H
      H->.
      C->.char
      C->.int
      C->.double
      S->.if(E)S
      S->.SelseS
      S->.{S}S
      S->.
      E->.EOE
      E->.(E)
      E->.@
      E->.$
      W->.
      W->.C$,W
      W->.C$
      O->.+
      O->.-
      O->./
      O->.*
      O->.>
      O->.=
      O->.>=
      O->.<
      O->.<=
      O->.!=
      O->.==
      O->.&
      O->.&&
      O->.|
      O->.||
      
    • 将第一个产生式放入闭包集I(0),并求出完整的闭包集

    • 依次依据识别出的非终结符和终结符,对第一个闭包集进行状态转移

    • 每次转移之后,得到新的闭包集I(i),并对I(i)求出完整的闭包集。求出之后在已有的闭包集中判断是否是重复的闭包集。

    • 如果不重复添加Action表和Goto表信息,状态I(i-1)中的i-1为横坐标,识别的终结符或者是非终结符为纵坐标,i为表项的值。

    • 如果重复则第一次出现该闭包集的状态下标作为表项的值

    • 依次次做上一步,直到没有新的闭包集出现

    • 对所有闭包集做判断,倘若闭包集中出现了规约性项目,查询该项目的左部的非终结符的Follow集,并将对应的闭包集状态下标以及Follow符号对应的Action表和Goto表表项进行修改。

  • close函数设计

    • 该函数实现求状态转移后,完整闭包集的求法
    • 遍历当前闭包集中的产生式,每个产生式寻找到 . 号,对 . 号后面的字符做判断
      • 倘若是**\0**则代表是规约型项目,不做处理
      • 倘若是终结符,不作处理
      • 倘若是非终结符,则寻找,当前所有产生式左部含有该非终结符的产生式添加到该闭包集中
    • 循环处理上一步,直至闭包集的大小不发生改变
  • SLR驱动函数设计

    • 该函数实现对输入字符串的语法解析,采用的是SLR的算法策略
    • 首先该函数调用之前应具有正确的Action表以及Goto表
    • 根据SLR算法思想设立字符栈,状态栈,初始状态为0
    • 读入所需判断的字符,根据状态栈顶和字符,查询Action表以及Goto表
      • 如果是移路状态,则将该字符放入字符栈中
      • 如果是规约状,则根据规约产生式,将字符(状态)从字符(状态)栈中弹出,并判断对应非终结符的状态,放入状态栈中
      • 如果是接受状态,则判断该字符串语法正确
      • 如果出现错误,将调用error函数,处理错误
  • error函数设计

    • 该函数为出现错误时调用
    • 判断当前字符栈中的字符串,与所有产生式进行比对,如果是该字符串是产生式的一部分,那么可以得到结论,原始需要判断的字符串的中缺少的是该产生式中未得到比对的字符
    • 记录当前出错的代码位置,以及错误信息,将字符栈,状态栈,置空,重新判断后面的代码。
    • 该函数处理的比较一般,无法处理较复杂的错误,暂时未能够想到更好的处理办法
  • init_Follow函数设计

    • 该函数能获取非终结的follow集
    • 该函数暂时未能用代码自动实现,主要靠文件读取。
  • main函数设计

    • 先做词法分析,倘若出现词法错误,输出错误信息结束程序
    • 读取文法,将文件中的文法读取,到程序中
    • 初始化得到非终结集合,终结符集合,follow集合
    • 初始化Action表以及Goto表
    • SLR函数,求闭包集
    • 更新Action表以及Goto表
    • 调用SLR驱动程序,进行语法分析
    • 输出错误信息

源代码

```c++
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#include <cmath>
#include <vector>
#include <stack>
//词法分析器
#include "CIFA.h"
using namespace std;
//const int N=100;
//const int MAXSIZE=1000;
//产生式存储
typedef struct Product{char left;char right[N];int length;
}Product;
//状态闭包集存储
typedef struct I{vector<Product> pros;
}I;
//follow集存储
typedef struct Follow{char V;vector<char> fset;
}Follow;
//闭包集 集合
vector<I> Is;
//follow集 集合
vector<Follow> FollowSet;
int prod_len;
//产生式集
Product products[MAXSIZE];//非终结符集,终结符集
char V[MAXSIZE];int V_len=0;
char T[MAXSIZE];int T_len=0;//action goto 表
char _action[MAXSIZE][MAXSIZE];
int _goto[MAXSIZE][MAXSIZE];
//action 表初始化
void init_action(){for(int i=0;i<MAXSIZE;i++)for(int j=0;j<MAXSIZE;j++)_action[i][j]='e';
}
//goto 表初始化
void init_goto(){for(int i=0;i<MAXSIZE;i++)for(int j=0;j<MAXSIZE;j++)_goto[i][j]=-1;
}
//字符串比对函数
bool mystrcmp(char *s,char *p){int i=0,j=0;while(s[i]!='\0' && p[j]!='\0' && s[i]==p[j]){++i;++j;}if(s[i]=='\0' && p[j]=='\0')return true;else return false;
}
//判断产生式是否相同
bool is_sameProduct(Product a,Product b){if(a.length!=b.length)return false;if(a.left==b.left && mystrcmp(a.right,b.right))return true;else return false;
}
//判断是否为操作符
bool is_operate(char c){char op[N]="+-*/=&|><";int i=0;while(op[i]!='\0'){if(op[i]==c)return true;i++;}return false;
}
//判断是否为非终结符
bool is_signV(char c){if(c>='A' && c<='Z')return true;else return false;
}
//判断状态闭包集是否相同
bool is_sameI(I a,I b){if(a.pros.size()!=b.pros.size())return false;int i,j;int cnt=0;for(i=0;i<a.pros.size();i++){for(j=0;j<b.pros.size();j++){if(is_sameProduct(a.pros[i],b.pros[j])){cnt++;break;}}}if(cnt==a.pros.size()){return true;}else return false;
}
//产生式拷贝
Product newProduct(Product a){Product ans;ans.left=a.left;strcpy(ans.right,a.right);ans.length=a.length;return ans;
}
//下标索引转换
int changIndex(char c){for(int i=0;i<T_len;i++){if(T[i]==c)return i;}for(int i=0;i<V_len;i++){if(V[i]==c)return T_len+i;}return -1;
}
//判断产生式是否在闭包集中
bool is_inI(I s,Product a){for(int i=0;i<s.pros.size();i++){if(is_sameProduct(s.pros[i],a))return true;}return false;
}
//输出产生式
void print_product(Product a){printf("%c->%s\n",a.left,a.right);
}
//输出产生式 --- 保存文件
void print_I(I a,int ans){char filename[10]="Is/I";int t=0,cnt=ans;string s="";while(filename[t]!='\0')t++;while(cnt){s+=(cnt%10)+'0';cnt/=10;}for(int i=s.size()-1;i>=0;i--)filename[t++]=s[i];filename[t++]='.';filename[t++]='t';filename[t++]='x';filename[t++]='t';filename[t]='\0';FILE *fp=fopen(filename,"w");for(int i=0;i<a.pros.size();i++){fprintf(fp,"%c->%s\n",a.pros[i].left,a.pros[i].right);}fclose(fp);
}
//判断是否是对应产生式
bool judge_product(Product a,Product b){int i=1,j=0;while(a.right[i]!='\0' && b.right[j]!='.' && a.right[i]==b.right[j]){++i;++j;}if(a.left==b.left && a.right[i]=='\0' && b.right[j]=='.')return true;else return false;
}
//闭包集求解
I close(I a){for(int i=0;i<a.pros.size();i++){char *s=a.pros[i].right;int k=0;while(s[k]!='\0' && s[k]!='.')k++;char c=s[k+1];if(c!='\0' && c>='A' && c<='Z'){for(int j=0;j<prod_len;j++){if(products[j].left==c){if(!is_inI(a,products[j]))a.pros.push_back(products[j]);}}}}return a;
}
//寻找非终结符对应follow集
int findFollow(char v){for(int i=0;i<FollowSet.size();i++){if(FollowSet[i].V==v)return i;}return -1;
}
//寻找产生式
int findProduct(Product a){for(int i=0;i<prod_len;i++){if(judge_product(products[i],a))return i;}return -1;
}
//SLR
void SLR(){I t;t.pros.push_back(products[0]);t=close(t);Is.push_back(t);int z=0;do{/*求状态闭包集*//*状态转移---非终结符*/for(int m=0;m<V_len;m++){I t;for(int n=0;n<Is[z].pros.size();n++){Product ans=newProduct(Is[z].pros[n]);int k=0;while(ans.right[k]!='\0' && ans.right[k]!='.')k++;if(ans.right[k+1]=='\0')continue;if(V[m]==ans.right[k+1]){swap(ans.right[k],ans.right[k+1]);t.pros.push_back(ans);}}t=close(t);if(t.pros.size()==0)continue;int u;for(u=0;u<Is.size();u++){if(is_sameI(Is[u],t)){int xx=z,yy=changIndex(V[m]);_goto[xx][yy]=u;break;}}if(u==Is.size()){Is.push_back(t);int xx=z,yy=changIndex(V[m]);_goto[xx][yy]=Is.size()-1;}}for(int m=0;m<T_len;m++){if(T[m]=='\0')continue;I t;for(int n=0;n<Is[z].pros.size();n++){Product ans=newProduct(Is[z].pros[n]);int k=0;while(ans.right[k]!='\0' && ans.right[k]!='.')k++;if(ans.right[k+1]=='\0')continue;if(T[m]==ans.right[k+1]){swap(ans.right[k],ans.right[k+1]);t.pros.push_back(ans);}}t=close(t);if(t.pros.size()==0)continue;int u;for(u=0;u<Is.size();u++){if(is_sameI(Is[u],t)){int xx=z,yy=changIndex(T[m]);_action[xx][yy]='s';_goto[xx][yy]=u;break;}}if(u==Is.size()){Is.push_back(t);int xx=z,yy=changIndex(T[m]);_action[xx][yy]='s';_goto[xx][yy]=Is.size()-1;}}z++;}while(z<Is.size());//printf("66\n");int l,xx,yy,index,r;for(int i=0;i<Is.size();i++){for(int j=0;j<Is[i].pros.size();j++){l=Is[i].pros[j].length;if(Is[i].pros[j].right[l-1]=='.'){xx=i;index=findFollow(Is[i].pros[j].left);//printf("%d \n",index);r=findProduct(Is[i].pros[j]);for(int k=0;k<FollowSet[index].fset.size();k++){yy=changIndex(FollowSet[index].fset[k]);_action[xx][yy]='r';_goto[xx][yy]=r;}}}}_action[1][T_len-1]='a';
}
//初始化非终结符
void init_V(){char c;int i,j;for(i=0;i<prod_len;i++){c=products[i].left;//printf("%c",c);for(j=0;j<V_len;j++){if(c==V[j]){break;}}if(j==V_len){V[V_len]=c;V_len++;}}//for(int i=0;i<V_len;i++){printf("%c ",V[i]);}
}
//初始化终结符
void init_T(){char *s,c;int i,j,k;for(i=0;i<prod_len;i++){s=products[i].right;k=0;while(s[k]!='\0'){c=s[k];k++;if((c>'Z' || c<'A') && c!='#'){//printf("%c ",c);for(j=0;j<T_len;j++){if(c==T[j]){break;}}if(j==T_len){T[T_len]=c;T_len++;}}}}T[T_len++]='\0';//for(int i=0;i<T_len;i++){printf("%c ",T[i]);}//printf("\n");
}
//初始化follow集
/*暂时还无法用程序实现*/
void init_Follow(){FILE * fp=fopen("Follow.txt","r");char ans[N];int v,k;while(!feof(fp)){fscanf(fp,"%s",ans);k=0;Follow t;while(ans[k]!='\0' && ans[k]!=EOF){if(ans[k]>='A' && ans[k]<='Z')t.V=ans[k];else {if(ans[k]=='#')t.fset.push_back('\0');else t.fset.push_back(ans[k]);}k++;}FollowSet.push_back(t);fgetc(fp);}fclose(fp);
}
//读取文件中的产生式
void GetProduct(char *filename){FILE  *fp=fopen(filename,"r");int ans;char c;prod_len=0;while(!feof(fp)){fscanf(fp,"%c->%s",&products[prod_len].left,products[prod_len].right);c=fgetc(fp);ans=0;while(products[prod_len].right[ans]!='\0')ans++;products[prod_len].length=ans;prod_len++;}fclose(fp);
}
//更新产生式
char* updateProduct(){FILE * fp=fopen("t_WENFA.txt","w");for(int i=0;i<prod_len;i++){if(i==prod_len-1){if(mystrcmp("#",products[i].right))fprintf(fp,"%c->.",products[i].left);else fprintf(fp,"%c->.%s",products[i].left,products[i].right);}else{if(mystrcmp("#",products[i].right))fprintf(fp,"%c->.\n",products[i].left);else fprintf(fp,"%c->.%s\n",products[i].left,products[i].right);}}fclose(fp);return "t_WENFA.txt";
}
//错误处理
void error(int eline,stack<char> s,char c,FILE *fp){if(s.empty())return ;int i,j,index,t=0;char tmp[20],ct;vector<char> ans(s.size());for(i=ans.size()-1;i>=0;i--){ans[i]=s.top();s.pop();}if(is_operate(ans[ans.size()-1])){insert_error(eline,"操作数","语法错,此处缺少");}bool judge=false;for(i=0;i<ans.size();i++){if(ans[i]=='(')judge=true;if(ans[i]==')')judge=false;}if(judge){insert_error(eline,")","语法错,此处缺少");}judge=false;for(i=0;i<ans.size();i++){if(ans[i]=='{')judge=true;if(ans[i]=='}')judge=false;}if(judge){insert_error(eline,"}","语法错,此处缺少");}
//    for(i=0;i<ans.size();i++){cout<<ans[i]<<" ";}
//    cout<<endl;for(i=0;i<prod_len;i++){j=0;while(j<products[i].length && j<ans.size() && products[i].right[j]==ans[j])j++;//cout<<i<<endl;if(j==ans.size()){while(products[i].right[j]!='\0'){if(products[i].right[j]<'A' || products[i].right[j]>'Z')tmp[t++]=products[i].right[j++];else break;//cout<<tmp[t-1]<<endl;}//print_product(products[i]);tmp[t]='\0';if(t==1){if(tmp[0]=='@' || tmp[0]=='$'){insert_error(eline,"操作数","语法错,此处缺少");return ;}else{if(is_operate(tmp[0])){insert_error(eline,tmp,"语法错,此处缺少");return ;}else{insert_error(eline,tmp,"语法错,非法字符");return ;}}}else if(t>1){if(t>1)insert_error(eline,tmp,"语法错,此处缺少");return ;}else{tmp[t++]=c;while((ct=fgetc(fp))!=EOF){if(ct>='a' && ct<='z')tmp[t++]=ct;else break;}tmp[t]='\0';insert_error(eline,tmp,"语法错,非法字符");return ;}}}//for(int i=0;i<=Erlen;i++){printf("%d :%s  %s\n",Errors[i].line,Errors[i].info,Errors[i].c);}//exit(0);
}
//更新action表
void update_action(){FILE *file_action=fopen("action.txt","w");fprintf(file_action,"\t");for(int i=0;i<T_len;i++){if(T[i]!='\0')fprintf(file_action,"%c\t",T[i]);else fprintf(file_action,"#\t");}fprintf(file_action,"\n");for(int i=0;i<Is.size();i++){fprintf(file_action,"%d\t",i);for(int j=0;j<T_len;j++)fprintf(file_action,"%c\t",_action[i][j]);fprintf(file_action,"\n");}fclose(file_action);
}
//更新goto表
void update_goto(){FILE *file_goto=fopen("goto.txt","w");fprintf(file_goto,"\t");for(int i=0;i<T_len;i++){if(T[i]!='\0')fprintf(file_goto,"%c\t",T[i]);else fprintf(file_goto,"#\t");}for(int i=0;i<V_len;i++){fprintf(file_goto,"%c\t",V[i]);}fprintf(file_goto,"\n");for(int i=0;i<Is.size();i++){fprintf(file_goto,"%d\t",i);for(int j=0;j<V_len+T_len;j++)fprintf(file_goto,"%d\t",_goto[i][j]);fprintf(file_goto,"\n");}fclose(file_goto);
}
//SLR驱动程序
void SLR_Driver(){FILE *fp_Token=fopen("Token.txt","r");FILE *fp_debug=fopen("debug.txt","w");stack<int> s_state;stack<char> s_char;int i=0,pos,state,code_line=1,ju=10;char ans,c,s[N];s_state.push(0);c=fgetc(fp_Token);while(1){if(c=='\n'){c=fgetc(fp_Token);code_line++;continue;}if(c==EOF){c='\0';}state=s_state.top();pos=changIndex(c);ans=_action[state][pos];//cout<<"状态栈顶"<<" "<<"符号栈顶"<<endl;fprintf(fp_debug,"状态栈顶   符号栈顶\n");if(!s_state.empty()&&!s_char.empty()){//cout<<s_state.top()<<" "<<s_char.top()<<endl;fprintf(fp_debug,"%d   %c\n",s_state.top(),s_char.top());}//cout<<c<<" "<<" "<<ans<<" "<<_goto[state][pos]<<endl;fprintf(fp_debug,"%c   %c   %d\n",c,ans,_goto[state][pos]);switch(ans){case 's':{s_state.push(_goto[state][pos]);s_char.push(c);c=fgetc(fp_Token);break;}case 'r':{if(products[_goto[state][pos]].right[0]!='#')for(int i=0;i<products[_goto[state][pos]].length;i++){s_state.pop();s_char.pop();}s_char.push(products[_goto[state][pos]].left);s_state.push(_goto[s_state.top()][changIndex(s_char.top())]);break;}case 'a':{if(Erlen<0)printf("Accept,语法分析成功666\n");return ;}default :{//cout<<c<<endl;error(code_line,s_char,c,fp_Token);s_char=stack<char>();s_state=stack<int>();s_state.push(0);c=fgetc(fp_Token);if(c==EOF)return ;break;}}}fclose(fp_Token);fclose(fp_debug);
}
int main()
{ci_start();if(Erlen!=-1){printf("词法分析错误\n");for(int i=0;i<=Erlen;i++){printf("%d :%s  %s\n",Errors[i].line,Errors[i].info,Errors[i].c);}exit(0);}GetProduct("WENFA.txt");init_V();init_T();init_Follow();char *filename=updateProduct();GetProduct(filename);init_action();init_goto();SLR();update_action();update_goto();for(int i=0;i<Is.size();i++){print_I(Is[i],i);}GetProduct("WENFA.txt");update_action();update_goto();SLR_Driver();for(int i=0;i<=Erlen;i++){printf("%d :%s  %s\n",Errors[i].line,Errors[i].info,Errors[i].c);}return 0;
}

效果呈现

test.c

int max(int a,int b){int m;if(a>b)m=a;else m=b;return m;
}
int main(){int sum,i,n;int cnt;double ave;sum=0;cnt=0;for(i=1;i<=n;i=i+1){sum=sum+i;}max(sum,n);ave=sum/n;for(i=1;i<=n;i=i+1){if(i==ave)cnt=cnt+1;}i=0;while(i<=n){if(cnt/i==0){printf("YES\n");}else{printf("NO\n");}i=i+1;}return 0;
}

调用程序,进行解析(该程序未出现语法错)

test2.c

int main(){int name;name=;for(name=0;name<10;name=name+name)name+1;return 0;
}

调用程序,进行解析(显然该程序出现语法错),因为一个错,带动后面一起错,所以出错处理不是非常好。

该程序可能会有bug,请见谅…欢迎指正。

编译原理——语法分析器(SLR)相关推荐

  1. 编译原理-语法分析器设计

    文章目录 语法分析器设计 实验环境 实验目的 实验内容及要求 实验步骤 用上下文无关文法表达 改写为LL(1)文法 First集与Follow集 预测分析表 结果分析 源代码 语法分析器设计 实验环境 ...

  2. 编译原理—语法分析器(Java)

    递归下降语法分析 1. 语法成分说明 <语句块> ::= begin<语句串> end <语句串> ::= <语句>{:<语句>} < ...

  3. 编译原理------语法分析器C/C++代码实现

    一.实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. 二.实验内容 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. 2.1 待分析的简单语言的语 ...

  4. 编译原理语法分析器实验报告

    编号: 实习 一 二 三 四 五 六 七 八 九 十 总评 教师签名 成绩 第一部分 语言语法规则 Mini语言包含程序设计所需要的最基本语言成分,包括 程序定义语句 :以 program 开头 en ...

  5. 编译原理——语法分析器(C/C++代码实现)

    0

  6. 编译原理—语法制导翻译、S属性、L属性、自上而下、自下而上计算

    编译原理-语法制导翻译.S属性.L属性.自上而下.自下而上计算 1.语法制导翻译 1.1属性文法 1.2算术表达式的计数器 1.3属性的分类 1.4属性依赖图 继承属性的计算 1.5语义规则的计算方法 ...

  7. 编译原理算符分析器实现 -* c语言代码,编译原理论文-词法分析器的设计与实现...

    <编译原理论文-词法分析器的设计与实现>由会员分享,可在线阅读,更多相关<编译原理论文-词法分析器的设计与实现(13页珍藏版)>请在人人文库网上搜索. 1.编译原理论文题 目 ...

  8. 编译原理 -- 语法制导翻译

    语法制导翻译 语法制导翻译是通过向一个文法的产生式附加一些规则或程序片段而得到的. 语法制导翻译的两个概念 下面是与语法制导翻译相关的两个概念: 属性(attribute) : 表示与某个程序构造相关 ...

  9. 编译原理算符分析器实现 -* c语言代码,C语言实现算符优先文法源代码(编译原理)...

    下面教大家用C语言实现编译原理中的算符优先文法.求出FIRSTVT集和LASTVT集,并判断该文法是否是算符优先文法. 一.知识解析 1.定义 算符优先文法是一种自下而上的分析方法,其文法的特点是文法 ...

最新文章

  1. 这引人联想的机械右手!玩转魔方,灵活不输人类,OpenAI:前所未有
  2. 虚拟服务器至强,用至强解决瓶颈 桌面虚拟化案例分享
  3. SSL 1052——开心的金明
  4. python基础语法第10关作业-Python基础语法习题一
  5. 自己动手实现一个简单的JSON解析器
  6. linux卸载pci驱动,linux的PCI驱动固件问题
  7. MySQL5.7 安装(win)
  8. mysql 替换 汉字_MySQL替换文字
  9. 关于mysql中select出数据未排序问题
  10. python导入excel表格给列命名_Python中对 Excel 的相关详细操作(读取、写入、指定行、指定列、新增sheet工作表)...
  11. matlab导线网平差,导线网平差算例教程
  12. 常见积分求导公式表--便于记忆
  13. mtk开机声音与关机声音修改(原创)
  14. DevOps落地实践:BAT系列:代码托管:iCode vs TGit
  15. 逆向序列号生成算法(三)
  16. 数据中心机房温湿度监测
  17. 信通方恒资产评估行业快讯:铁矿石供需关系未发生明显变化
  18. 互联网大佬们都在焦虑什么?
  19. win7安装高版本的node解决办法
  20. 实例恢复(Instance Recovery)之前滚(Rolling Forward)和回滚(Rolling Back)

热门文章

  1. LeetCode 第594题——最长和谐子序列
  2. pearson相关系数与spearman相关系数
  3. javac编译选项-Option
  4. new unsigned char 什么意思
  5. OpenCL项目模板
  6. 多种方式实现web端截屏录屏
  7. 六大室内定位方案算法对比,谁成为室内定位方案主流-新导智能
  8. 【Java Socket】TCP协议的多人聊天室
  9. 上位机和MYSQL连接_上位机下位机串口通信设计详解
  10. 浪潮超融合服务器虚拟机管理,浪潮在美发布InCloudRail超融合,这是什么样的节奏?...