编译原理头歌实验:实验1《词法分析程序设计与实现》(C语言版)

任务描述

本关任务:加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。

相关知识

为了完成本关任务,你需要掌握:词法分析程序设计与实现。

词法分析的基本知识

词法分析程序( Lexical analyzer,简称 Lexer ),负责从左到右逐个字符地对源程序进行扫描和分解,根据语言的词法规则识别出一个个的单词符号。

因此一个词法分析程序应具备如下功能:

  • 从左至右扫描构成源程序的字符流

  • 识别出有词法意义的单词

  • 返回单词记录,或词法错误信息

由上可知词法分析中的一个重要环节为识别单词符号类型,为了便于语法分析,通常将单词符号分为五类。

  • 标识符 用来命名程序中出现的变量、数组、函数、过程、标号等,通常是一个字母开头的字母数字串,如 length,nextch 等。

  • 基本字 也可以成为关键字或保留字。如 if,while,for,do,goto 等。他们具有标识符的形式,但他们不是由用户而是由语言定义的,其意义是约定的。多数语言中规定,他们不能作为标识符或者标识符的前缀,即用户不能使用它们来定义用户使用的名字,故我们称它为保留字,这些语言如 Pascal 和 C 等。但也有的语言允许将基本字作为标识符或者标识符的前缀,这类语言如 Fortran 等。

  • 常数 包括各种类型的常数,如整型、实型、字符型、布尔型等。如:53.1415926aTRUE等都是常数。

  • 运算符 算术运算符+-×÷;关系运算符<,<=,>,>=,==,!=以及逻辑运算符&&()||或者!等。

  • 界符 如等单字界符和/,/,//等双字界符,空白符等。

在进行词法分析后,识别出来的单词应该采用某种中间表示形式,以便为编译后续阶段方便地引用。通常一个单词用一个二元式来表示: (单词类别,单词的属性) 其中,第一元用于区分单词所属的类别,以整数编码表示。第二元用于区分该类别中的哪一个单词符号,即单词符号的值。

实验步骤

由一个词法分析程序应具备的功能来看,我们的程序具有如下要求:

  • 对单词的构词规则有明确的定义;
  • 编写的分析程序能够正确识别源程序中的单词符号;
  • 识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;
  • 对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;

下面我们进行实验代码的步骤分析。

  1. 定义目标语言的可用符号表和构词规则。
    我们需要对五种单词符号进行识别分析,这里将单词符号分为三大块进行识别。首先判断字符是否为关键字或者标识符,并与已定义好的关键字进行比较,从而判断为关键字或者标识符;然后是数字的识别;最后是其他字符的判断,它们被一一定义好的判断进行识别,这样所有的字符便被识别出来了。标示符和关键字的判断

     
    1. if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) //可能是标示符或者关键字

    字符与关键字的区别通过对比得出:

     
    1. if (strcmp(token, rwtab1[n]) == 0)
    2. {
    3. syn = 2;
    4. break;
    5. }
    6. else if (strcmp(token, rwtab[n]) == 0) {
    7. syn = 1;
    8. break;
    9. }
    10. }

    对于数字的识别:

     
    1. else if ((ch >= '0' && ch <= '9')) //数字

    其他字符的识别,他们被一一定义进行识别:

     
    1. else switch (ch) //其他字符
    2. {
    3. case'<':m = 0; token[m++] = ch;
    4. ch = prog[p++];
    5. if (ch == '>')
    6. {
    7. syn = 4;
    8. token[m++] = ch;
    9. }
    10. else if (ch == '=')
    11. {
    12. syn = 4;
    13. token[m++] = ch;
    14. }
    15. else
    16. {
    17. syn = 4;
    18. p--;
    19. }
    20. break;
    21. case'>':m = 0; token[m++] = ch;
    22. ch = prog[p++];
    23. if (ch == '=')
    24. {
    25. syn = 4;
    26. token[m++] = ch;
    27. }
    28. else
    29. {
    30. syn = 4;
    31. p--;
    32. }
    33. break;
    34. case':':m = 0; token[m++] = ch;
    35. ch = prog[p++];
    36. if (ch == '=')
    37. {
    38. syn = 4;
    39. token[m++] = ch;
    40. }
    41. else
    42. {
    43. syn = 4;
    44. p--;
    45. }
    46. break;
    47. case'*':syn = 4; token[0] = ch; break;
    48. case'/':syn = 4; token[0] = ch; break;
    49. case'+':syn = 4; token[0] = ch; break;
    50. case'-':syn = 4; token[0] = ch; break;
    51. case'=':syn = 4; token[0] = ch; break;
    52. case';':syn = 5; token[0] = ch; break;
    53. case',':syn = 5; token[0] = ch; break;
    54. case'(':syn = 5; token[0] = ch; break;
    55. case')':syn = 5; token[0] = ch; break;
    56. case'{':syn = 5; token[0] = ch; break;
    57. case'}':syn = 5; token[0] = ch; break;
    58. case'#':syn = 0; token[0] = ch; break;
    59. case'\n':syn = -2; break;
    60. default: syn = -1; break;
    61. }
    62. }
  2. 依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束。
    字符的输入我们使用cin.get() 获取,并切分保存在 prog中:

     
    1. p = 0;
    2. row = 1;
    3. cout << "Please input string:" << endl;
    4. do
    5. {
    6. cin.get(ch);
    7. prog[p++] = ch;
    8. } while (ch != '#');
    9. p = 0;
  3. 对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;

  4. 对不正确的单词,做出错误处理。 单词识别后,我们对返回的符号按3,4的规则进行输出:

     
    1. {
    2. scaner();
    3. switch (syn)
    4. {
    5. case 0: break;
    6. case 3: cout << "(" << syn << "," << sum << ")" << endl; break;
    7. case -1: cout << "Error in row " << row << "!" << endl; break;
    8. case -2: row = row++; break;
    9. default: cout << "(" << syn << "," << token << ")" << endl; break;
    10. }
    11. } while (syn != 0);

编程要求

根据提示,在右侧编辑器补充代码标示符、数字符及其他字符符号的识别程序后,点击评测运行程序,系统会自动进行结果对比。

测试说明

平台会对你编写的代码进行测试:

测试输入:

 
  1. using namespace std;
  2. int main()
  3. {
  4. int year;
  5. cout << "hello" << endl;
  6. return 0;
  7. }
  8. #

代码:

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <stack>
#include <iomanip>
using namespace std;
string V[100][2]; //存储拆分后的文法
int vi = 0; //存储拆分后有多少行
int t = 0;
int s = 0;
int l;
int r;
string FIRSTVT[20][2]; //存储firstvt集
string LASTVT[20][2]; //存储lastvt集
string str; //存储输入文法
string str_a = "#"; // 下堆栈
string str_b; // 剩余输入串
string analysis_table[100][5]; // 文法分析过程
char table[100][100]; // 算符优先关系表
void init_string(string &a) // 删除字符串的第一个元素
{for (int i = 1; i <= a.length(); ++i){a[i - 1] = a[i];}
}
bool is_CHAR(char c) // 判断是否为大写字母
{if (c >= 'A' && c <= 'Z'){return true;}else{return false;}
}
bool is_in(int i, string x) // 判断从字符串x从最好一个开始算起连续的i个字符是否含有非大写字母
{bool flag = false;for (int j = 0; j < i; j++){if (!is_CHAR(x[x.length() - j - 1])){flag = true;}}return flag;
}
void split(string a) // 拆分文法,使其不含有|
{for (int i = 3; i < a.length(); ++i){V[vi][0] = a[0];while (a[i] != '|' && i < a.length()){V[vi][1] += a[i];i++;}vi++;}
}
void read_file(string file_path) //按行读取文件
{fstream f(file_path);vector<string> words;string line;while (getline(f, line)){words.push_back(line);}cout << "输入文法:" << endl;for (int i = 0; i < words.size(); i++){cout << words[i] << endl;split(words[i]);}
}
int find_index(char a) //寻找字符a在firstvt或者lastvt中的位置
{for (int i = 0; i < t; ++i){if (FIRSTVT[i][0][0] == a){return i;}}return -1;
}
int find_table_index(char a) //寻找字符a在算符优先关系表中的位置
{for (int i = 0; i <= s; ++i){if (table[i][0] == a){return i;}}return -1;
}
void get_start() //获取非终结符
{for (int i = 0; i < vi; ++i){bool flag = true;for (int j = 0; j < t; ++j){if (FIRSTVT[j][0] == V[i][0]){flag = false;}}if (flag){FIRSTVT[t][0] = V[i][0];LASTVT[t][0] = V[i][0];t++;}}
}
/********Beign********/
/*构造firstvt,lastvt*/
void add_firstvt(string b, int a) //判断字符串b是否在序号为a的firstvt中,没有则加入
{for(int i = 0;i < b.size();i++){bool flag = 1;char c = b[i];if(c >= 'A' && c <= 'Z'){continue;}for(int j = 0;j < FIRSTVT[a][1].size();j++){if(c == FIRSTVT[a][1][j]){flag = 0;}}if(flag){FIRSTVT[a][1] += c;}}
}
void add_firstvt(char c, int a) //判断字符c是否在序号为a的firstvt中,没有则加入
{bool flag = 1;for (int i = 0; i < FIRSTVT[a][1].size(); i++){if (c >= 'A' && c <= 'Z'){continue;}if (c == FIRSTVT[a][1][i]){flag = 0;}}if (flag){FIRSTVT[a][1] += c;}
}
void add_lastvt(string b, int a) //判断字符串b是否在序号为a的lastvt中,没有则加入
{for(int i = 0;i < b.size();i++){bool flag = 1;char c = b[i];if(c >= 'A' && c <= 'Z'){continue;}for(int j = 0;j < LASTVT[a][1].size();j++){if(c == LASTVT[a][1][j]){flag = 0;}}if(flag){LASTVT[a][1] += c;}}
}
void add_lastvt(char c, int a) //判断字符串c是否在序号为a的lastvt中,没有则加入
{bool flag = 1;for (int i = 0; i < LASTVT[a][1].size(); i++){if (c >= 'A' && c <= 'Z'){continue;}if (c == LASTVT[a][1][i]){flag = 0;}}if (flag){LASTVT[a][1] += c;}
}
string get_cur_firstvt(char c, int a) //获取当前字符的firstvt,并放入序号为a的firstvt中
{string temp;for (int i = 0; i < vi; i++){if (c == V[i][0][0]){if (!(V[i][1][0] >= 'A' && V[i][1][0] <= 'Z')){add_firstvt(V[i][1][0], a);}else{if (c != V[i][1][0]){temp = get_cur_firstvt(V[i][1][0], find_index(V[i][1][0]));add_firstvt(temp, a);}if (V[i][1].length() > 2){if (!(V[i][1][1] <= 'Z' && V[i][1][1] >= 'A')){add_firstvt(V[i][1][1], a);}}}}}return FIRSTVT[a][1];
}
string get_cur_lastvt(char c, int a) //获取当前字符的lastvt,并放入序号为a的lastvt中
{string temp;for (int i = 0; i < vi; ++i){int s = V[i][1].length();if (c == V[i][0][0]){if (!(V[i][1][s - 1] <= 'Z' && V[i][1][s - 1] >= 'A')){add_lastvt(V[i][1][s - 1], a);}else{if (c != V[i][1][s - 1]){temp = get_cur_lastvt(V[i][1][s - 1], find_index(V[i][1][0]));add_lastvt(temp, a);}if (V[i][1].length() > 2){if (!(V[i][1][s - 2] <= 'Z' && V[i][1][s - 2] >= 'A')){add_lastvt(V[i][1][s - 2], a);}}}}}return LASTVT[a][1];
}
/*********End*********/
void get_firstvt() //获取所有文法的firstvt
{for (int i = 0; i < t; i++){get_cur_firstvt(FIRSTVT[i][0][0], i);}
}
void get_lastvt() //获取所有文法的lastvt
{for (int i = 0; i < t; i++){get_cur_lastvt(LASTVT[i][0][0], i);}
}
void print_firstvt(string t, string a) //打印非终极符为t的firstvt
{cout << "FIRSTVT(" << t << ") = {";for (int i = 0; i < a.length(); ++i){if (i == a.length() - 1){cout << "\"" << a[i] << "\"";}else{cout << "\"" << a[i] << "\"" << ", ";}}cout << "}" << endl;
}
void print_lastvt(string t, string a) //打印非终结符为t的lastvt
{cout << "LASTVT(" << t << ") = {";for (int i = 0; i < a.length(); ++i){if (i == a.length() - 1){cout << "\"" << a[i] << "\"";}else{cout << "\"" << a[i] << "\"" << ", ";}}cout << "}" << endl;
}
/********Beign********/
/*构造算符优先表*/void init_table() //初始化算符优先关系表
{table[0][0] = '\\';for (int i = 0; i < vi; ++i){for (int j = 0; j < V[i][1].length(); ++j){bool flag = true;for (int k = 0; k < s + 1; ++k){if (table[k + 1][0] == V[i][1][j] || (V[i][1][j] <= 'Z' && V[i][1][j] >= 'A')){flag = false;}}if (flag){table[s + 1][0] = V[i][1][j];table[0][s + 1] = V[i][1][j];s++;}}}for (int l = 1; l < s + 1; ++l){for (int i = 1; i < s + 1; ++i){table[l][i] = ' ';}}
}void get_table() //生成算符优先关系表
{for (int i = 0; i < vi; ++i){for (int j = 0; j < V[i][1].length(); ++j){//abif (!(V[i][1][j] <= 'Z' && V[i][1][j] >= 'A') && !(V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&j + 1 < V[i][1].length()){table[find_table_index(V[i][1][j])][find_table_index(V[i][1][j + 1])] = '=';}//aQbif ((!(V[i][1][j] <= 'Z' && V[i][1][j] >= 'A')) && (V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&(!(V[i][1][j + 2] <= 'Z' && V[i][1][j + 2] >= 'A')) && j + 2 < V[i][1].length()){table[find_table_index(V[i][1][j])][find_table_index(V[i][1][j + 2])] = '=';}//aQif ((!(V[i][1][j] <= 'Z' && V[i][1][j] >= 'A')) && (V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&j + 1 < V[i][1].length()){for (int k = 0; k < FIRSTVT[find_index(V[i][1][j + 1])][1].length(); ++k){table[find_table_index(V[i][1][j])][find_table_index(FIRSTVT[find_index(V[i][1][j + 1])][1][k])] = '<';}}//Qaif ((V[i][1][j] <= 'Z' && V[i][1][j] >= 'A') && !(V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&j + 1 < V[i][1].length()){for (int k = 0; k < LASTVT[find_index(V[i][1][j])][1].length(); ++k){table[find_table_index(LASTVT[find_index(V[i][1][j])][1][k])][find_table_index(V[i][1][j + 1])] = '>';}}}}
}
/*********End*********/
void print_table() //打印算符优先关系表
{for (int i = 0; i < s + 1; ++i){for (int j = 0; j < s + 1; ++j){cout << table[i][j] << " ";}cout << endl;}
}
char get_relationship(char a, char b) //获取终结符a,b的优先关系
{return table[find_table_index(a)][find_table_index(b)];
}
bool is_reduce() //判断是否可以规约
{for (int i = 0; i < vi; ++i){int count = 0;int f = str_a.length() - 1;for (int j = V[i][1].length() - 1; j >= 0 && f >= 0; j--, f--){if (is_in(V[i][1].length(), str_a)){if (is_CHAR(str_a[f]) && is_CHAR(V[i][1][j])){count++;}else if (str_a[f] == V[i][1][j]){count++;}}else{continue;}}if (count == V[i][1].length()){r = i;return true;}}return false;
}
void analyze_input_string() // 生成算符优先文法的分析过程
{analysis_table[0][0] = "步骤";analysis_table[0][1] = "下堆栈";analysis_table[0][2] = "优先关系";analysis_table[0][3] = "剩余输入串";analysis_table[0][4] = "移进或规约";str_b = str;char relationship;l = 1;int x;stringstream ss;while (true){ss << l;int index = str_a.length() - 1;analysis_table[l][0] = ss.str();analysis_table[l][3] = str_b;analysis_table[l][1] = str_a;ss.clear();ss.str("");if (is_CHAR(str_a[index])){for (int i = str_a.length() - 1; i >= 0; i--){if (!is_CHAR(str_a[i])){index = i;break;}}}relationship = get_relationship(str_a[index], str_b[0]);analysis_table[l][2] = relationship;if (relationship == '='){if (str_a[index] == '#' && str_b[0] == '#'){analysis_table[l][4] = "完成";break;}else{analysis_table[l][4] = "移进";str_a += str_b[0];analysis_table[l + 1][1] = str_a;init_string(str_b);}}else if (relationship == '<'){analysis_table[l][4] = "移进";str_a += str_b[0];analysis_table[l + 1][1] = str_a;init_string(str_b);}else if (relationship == '>'){if (is_reduce()){analysis_table[l][4] = "规约";str_a[str_a.length() - V[r][1].length()] = V[r][0][0];str_a.erase(str_a.length() - V[r][1].length() + 1, V[r][1].length() - 1);}else{cout << "输入串非法" << endl;exit(-1);}}l++;}
}
void print_analyze_process() //打印算符优先文法的分析过程
{cout << "算符优先分析过程" << endl;cout << setw(12) << analysis_table[0][0] << setw(16) << analysis_table[0][1] << setw(16) << analysis_table[0][2]<< setw(24)<< analysis_table[0][3] << setw(20)<< analysis_table[0][4] << endl;for (int i = 1; i <= l; ++i){cout.width(10);cout << analysis_table[i][0];cout.width(12);cout << analysis_table[i][1];cout.width(10);cout << analysis_table[i][2];cout.width(20);cout << analysis_table[i][3];cout << analysis_table[i][4];cout << endl;}
}
int main(int argv, char *arg[])
{cout.setf(std::ios::left);read_file("/data/workspace/myshixun/in.txt");cout << "拆分后文法:" << endl;for (int i = 0; i < vi; ++i){cout << V[i][0] << "->" << V[i][1] << endl;}cout << "非终结符:" << endl;get_start();for (int j = 0; j < t; ++j){cout << FIRSTVT[j][0] << endl;}cout << "FIRSTVT:" << endl;get_firstvt();for (int k = 0; k < t; ++k){print_firstvt(FIRSTVT[k][0], FIRSTVT[k][1]);}cout << "LASTVT:" << endl;get_lastvt();for (int k = 0; k < t; ++k){print_lastvt(LASTVT[k][0], LASTVT[k][1]);}cout << "算符优先关系表" << endl;init_table();get_table();print_table();cout << "请输入文法并以#结束:" << endl;cin >> str;analyze_input_string();print_analyze_process();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/188007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt应用开发--国产工业开发板全志T113-i的部署教程

Qt在工业上的使用场景包括工业自动化、嵌入式系统、汽车行业、航空航天、医疗设备、制造业和物联网应用。Qt被用来开发工业设备的用户界面、控制系统、嵌入式应用和其他工业应用&#xff0c;因其跨平台性和丰富的功能而备受青睐。 Qt能够为工业领域带来什么好处&#xff1a; -…

袋鼠云产品功能更新报告08期|近百项全新功能和优化,你要的都在这里!

欢迎来到袋鼠云08期产品功能更新报告&#xff01;在瞬息万变的市场环境中&#xff0c;我们深知客户的需求与期待&#xff0c;因此&#xff0c;我们及时推出袋鼠云最新产品更新及优化&#xff0c;包括数据治理中心、Hive SQL 性能优化、新插件等&#xff0c;助力企业在数字世界中…

Golang分布式事务

引言 在分布式系统中&#xff0c;事务管理是一项非常重要的任务。分布式事务涉及到多个事务参与者之间的协调和一致性保证&#xff0c;同时还要解决网络延迟、故障恢复等问题。Golang作为一门强大的编程语言&#xff0c;提供了一些工具和框架来帮助开发人员实现分布式事务。本…

awk从放弃到入门(11):拾遗之”三元运算”与”打印奇偶行”

awk从放弃到入门&#xff08;11&#xff09;&#xff1a;拾遗之”三元运算”与”打印奇偶行” 三元运算打印奇偶行 本博文转载自 这篇文章中的知识点是建立在前文的基础上的&#xff0c;如果你还没有掌握前文中的知识&#xff0c;请先参考之前的文章。 这篇文章其实是对之前知…

英语翻译小软件 ← Python实现

【程序描述】 利用Python实现一个英语翻译小软件。 ★ 当输入一个英文单词后&#xff0c;输出对应的中文意思。 ★ 当输入 q 时&#xff0c;退出程序。 ★ 当输入一个不存在的词条时&#xff0c;捕获异常&#xff0c;提示“No finding!”。【程序代码】 dict{&quo…

IOS/安卓+charles实现抓包(主要解决证书网站无法打开问题)

安装 官网下载 https://www.charlesproxy.com/latest-release/download.do 安装charles文档 流程 上述链接解决下图问题 使用介绍 Charles介绍 上述链接看一至三即可&#xff0c;了解首页各个按钮的作用 charles全面使用教程及常见功能详解&#xff08;较详细&#xff09…

Vim编辑器使用

替换全部 :%s/search_string/replace_string/g 撤销 u 撤销 ctrl r 取消撤销 换行 下移动一行 -上移动一行 删除 插入模式删除字符 Ctrl U

netty源码:(1)NioEventLoopGroup

EventLoopGroup bossGroup new NioEventLoopGroup(); 不加参数创建NioEventLoopGroup的话&#xff0c;会使用cpu核数*2作为bossGroup的线程数。

二 使用GPIO的复用功能 利用USART 实现printf()

参考这篇&#xff1a; STM32串口通信详解 1. 关于USART USART ( universal synchronous / asynchronous receiver /transmitter) 是一种串行通讯协议 , 允许设备通过串行端口进行数据传输&#xff0c; USART 能够以同步或者异步的方式进行工作&#xff0c;在实际的运用中&…

容器技术发展史,编排与容器的技术演进之路——2

目录&#xff1a; 容器技术发展史 Jail时代 1979 年 贝尔实验室发明 chroot2000 年 FreeBSD 4.0 发行 FreeBSD Jail2001 年 Linux VServer 发行2004 年 Solaris Containers 发行云时代 2006 年 google 推出 Process Containers2008 年 LXC 推出2011 年 CloudFoundry 推出 Ward…

【Linux】I/O多路转接技术

I/O多路转接技术 一、I/O多路转接之select1、select函数2、fd_set的相关内容3、如何在代码中高效的使用select函数4、select服务器5、select的优缺点6、select的适用场景 二、I/O多路转接之poll1、poll函数2、struct pollfd结构2、poll服务器3、poll的优缺点 三、I/O多路转接之…

自身免疫疾病抗原应用方向——博迈伦生物

自身免疫疾病是指机体免疫系统对自身组织产生异常免疫反应的疾病&#xff0c;包括类风湿性关节炎、系统性红斑狼疮、多发性硬化症等。目前&#xff0c;针对自身免疫疾病的治疗方案主要包括药物治疗和免疫调节治疗。而自身免疫疾病抗原应用则是一种新的治疗方向&#xff0c;其通…

Mac IDEA解决Maven项目命令行报错:command not found: mvn

1. 使用idea自带的maven命令 open -e ~/.zshrc 2. 在其最下面增加 # maven export MAVEN_HOME"/Applications/IntelliJ IDEA.app/Contents/plugins/maven/lib/maven3" export PATH$MAVEN_HOME/bin:$PATH # maven end 3. 连接使之生效 source ~/.zshrc4. 修改mvn…

Promise介绍

前言 Promise是一种用于处理异步操作的JavaScript对象&#xff0c;它可以将生产代码和消费代码连接起来&#xff0c;让异步方法像同步方法一样返回值。 异步操作是指在执行过程中可能会遇到延迟或等待的操作&#xff0c;例如网络请求、定时器、文件读取等。传统的JavaScript代码…

【从删库到跑路 | MySQL总结篇】索引的详细使用

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、索引…

WPF实战项目十八(客户端):添加新增、查询、编辑功能

1、ToDoView.xmal添加引用&#xff0c;添加微软的行为类 xmlns:i"http://schemas.microsoft.com/xaml/behaviors" 2、给项目添加行为 <i:Interaction.Triggers><i:EventTrigger EventName"MouseLeftButtonUp"><i:InvokeCommandAction Com…

单车模型及其线性化

文章目录 1 单车模型2 线性化3 实现效果4 参考资料 1 单车模型 这里讨论的是以后轴为中心的单车运动学模型&#xff0c;由下式表达&#xff1a; S ˙ [ x ˙ y ˙ ψ ˙ ] [ v c o s ( ψ ) v s i n ( ψ ) v t a n ( ψ ) L ] \dot S \begin{bmatrix} \dot x\\ \dot y\\ \d…

【C++】异常抛出变量的生命周期

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。搜…

代码随想录算法训练营第三十七天 _ 贪心算法_738.单调自增的数字、968.监督二叉树

学习目标&#xff1a; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 738.单调自增的数字 听不懂的时候就到该动手了。必须要从后向前操作&#xff0c;才能把压力逐级传给最前面的这一位。入如&#xff1a;322 class Solution {// java中的String不能修改&#xf…

Web3 开发者集结赢积分顺利闭幕!全程回顾一起来看

由 TinTinLand 联合 Dataverse 、Web3Go 、Subquery 、Cregis 、Litentry、Aspecta、SpaceID、ANOME、VARA&Gear、Moonbeam、Mantle、Obelisk 等 10 余家 Web3 项目共同举办的 Web3 开发者赢积分活动已于 11 月 26 日顺利落下帷幕&#xff0c;三周精彩纷呈的活动吸引了一众…