编译原理 | 课程设计 — PL/0编译程序语法分析

news2025/2/28 16:55:26

1、任务描述

基于第二章的词法分析程序,使用C/C++语言编写PL/0编译程序的语法分析程序。

2、编程要求

完成上述编程任务,将C/C++语言源程序复制粘贴到右侧代码编辑器,点击“评测”按钮,运行程序,系统会自动进行结果对比。

3、测试说明

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

测试输入:

const a = 10;
var   b, c;
procedure p;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0 do
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

语法正确

测试输入:

const a := 10;
var   b, c;
procedure p;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0 do
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:1)

测试输入:

const a = 10;
var   b, c;
//单行注释
/*
* 多行注释
*/
procedure p;
    if a <= 10 then
        begin
            c := b + a
        end;
begin
    read(b);
    while b # 0 do
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:13)

测试输入:

const a = 10;
var   b, c;
//单行注释
/*
* 多行注释
*/
procedure p;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0
        begin
            call p;
            write(2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:17)

测试输入:

const a := 10;
var   b, c d;
//单行注释
/*
* 多行注释
*/
procedure procedure fun1;
    if a <= 10 
        begin
            c = b + a
        end;
begin
    read(b;
    while b # 0 
        begin
            call fun1;
            write 2 * c);
            read(b);
        end;
end.

预期输出:

(语法错误,行号:1)
(语法错误,行号:2)
(语法错误,行号:10)
(语法错误,行号:11)
(语法错误,行号:13)
(语法错误,行号:16)
(语法错误,行号:17)
(语法错误,行号:20)

4、代码 

        语法分析的代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <sstream>
using namespace std;

/* ------------ 全局变量声明定义 ------------ */
int lineNumber = 1; // 当前行号

char charTable[2000];				// 字符表 —— 存储输入程序的 所有字符,包括空格、换行等
string wordTable[200] = { "\0" };	// 单词表 —— 存储输入程序的 所有单词,包括换行
char word[88] = "\0";				// 存储单个字符,添加到 wordTable 中

string ENDsign = "end.";	// 结束标识符
int charIndex = 0;			// 记录当前 charTable 字符个数
int wordIndex = 0;			// 记录当前 wordTable 单词个数

int errorNum = 0;			// 语法错误个数
int errorLine = 0;			// 语法错误行

string reservedWord[20] = { // 保留字
	"begin","call", "const","do","end","if",
	"odd","procedure", "read","then",
	"var","while","write"
};


/* ------------ 函数声明 ------------ */
void LexicalAnalysis();		// 词法分析
void GrammaticalAnalysis();	// 语法分析

void StrConnect(char* str, char ch);	// 拼接字符串
int StrLength(char* str);			// 计算字符串长度

int IsChar(char ch);			// 判断是否是字符
int IsOperator(char ch);		// 判断是否是运算符
int IsDigit(char ch);			// 判断是否是数字
int IsBoundary(char ch);		// 判断是是否界符
int IsReservedWord(char* str);	// 判断是否是保留字

void ProcessString(char ch);	// 判断字符串是否合法,合法则保存到单词表中
void ProcessNumber(char ch);	// 判断数字串是否合法,合法则保存到单词表中

void PrintError(int type);		//语法错误输出

int id();					// 变量名声明判断
void subroutine();			// 子程序
void constant();		// 常量定义
void variable();		// 变量定义
void sentence();			// 语句分析
void annotation();			// 注释
void condition();			// 条件分析
void expression();			// 表达式
void term();				// 项
void factor();				// 因子
void identifier();			// 标识符
void number();				// 数字



/* ------------ 函数定义 ------------ */
// 词法分析
void LexicalAnalysis() {
	while (charTable[charIndex] != '\0') { // 当前字符表未识别到结束符 '\0'
		if (charTable[charIndex] == '\0')
			break;
		if (charTable[charIndex] == ' ') {
			charIndex++;
			continue;
		}
		if (charTable[charIndex] == '\n') {
			wordTable[wordIndex++] = "\n";  // 将 换行符 保存到单词表 wordTable 中
			charIndex++;
			lineNumber++;	// 程序换行,行数加一
		}
		// 识别到字符
		else if (IsChar(charTable[charIndex])) {
			ProcessString(charTable[charIndex]); // 处理该字符之后的字符串
			continue;
		}
		// 识别到数字
		else if (IsDigit(charTable[charIndex])) {
			ProcessNumber(charTable[charIndex]); // 处理该数字之后的数字串
			continue;
		}
		// 识别到'/' 符
		else if (charTable[charIndex] == '/') {
			// 之后是 '/' ,说明是注释 //
			if (charTable[charIndex + 1] == '/') {
				wordTable[wordIndex++] = "//";
				charIndex = charIndex + 2;
				word[0] = '\0';

				while (charTable[charIndex] != '\n') // 将未换行的字符全部识别为注释
					StrConnect(word, charTable[charIndex++]);
				wordTable[wordIndex++] = word;
				wordTable[wordIndex++] = "\n";
				charIndex++;
				continue;
			}
			// 之后是 '*' ,说明是注释 /*
			else if (charTable[charIndex + 1] == '*') {
				wordTable[wordIndex++] = "/*";
				charIndex = charIndex + 2;
				while (!(charTable[charIndex] == '*' && charTable[charIndex + 1] == '/')) {
					if (charTable[charIndex] == '\n') {
						wordTable[wordIndex++] = "\n";
						charIndex++;
						continue;
					}
					word[0] = '\0';
					while (charTable[charIndex] != '\n') StrConnect(word, charTable[charIndex++]);
					wordTable[wordIndex++] = word;
					wordTable[wordIndex++] = "\n";
					charIndex++;
				}
				wordTable[wordIndex++] = "*/";
				charIndex = charIndex + 2;
				word[0] = '\0';
				continue;
			}
			// 是非法字符(串)
			else {
				while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
					StrConnect(word, charTable[charIndex]);
					charIndex++;
				}
				printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
				word[0] = '\0';
				break;
			}
		}
		// 识别到比较符
		else if (charTable[charIndex] == '<' || charTable[charIndex] == '>') {
			charIndex++;
			// 是 <= 或者 >= 符
			if (charTable[charIndex] == '=') {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<="; // 保存单词表
				else
					wordTable[wordIndex] = ">="; // 保存单词表
				wordIndex++;
				charIndex++;
				continue;
			}
			// 是 < 或者 > 符
			else {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<"; // 保存单词表
				else
					wordTable[wordIndex] = ">"; // 保存单词表
				wordIndex++;
				continue;
			}
		}
		// 识别到':'
		else if (charTable[charIndex] == ':') {
			charIndex++;
			if (charTable[charIndex] == '=') {
				wordTable[wordIndex++] = ":="; // 保存单词表
				charIndex++;
				continue;
			}
			else {
				printf(":后面不是=号\n");
				continue;
			}
		}
		// 识别到运算符
		else if (IsOperator(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到界符
		else if (IsBoundary(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到非法字符(串)
		else {
			printf("(非法字符(串),%c,行号:%d)\n", charTable[charIndex], lineNumber);
			charIndex++;
		}
	}
}
// 语法分析
void GrammaticalAnalysis() {
	subroutine();
	if (!wordTable[wordIndex].compare(".")) {
		if (errorNum == 0)
			printf("语法正确\n");
	}
	else {
		PrintError(0); // 输出语法错误以及行号
		return;
	}
}
// 打印语法错误
void PrintError(int type) {
	if (type == 1) {
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			errorNum++;
		}
	}
	else {
		while (wordTable[wordIndex].compare("\n") != 0) 
			wordIndex++;
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			errorNum++;
		}
	}
}


// 拼接字符串
void StrConnect(char* str, char ch) {        
	int i = 0;
	while (str[i] != '\0') i++;
	str[i] = ch;
	str[i + 1] = '\0';
}
// 计算字符串长度
int StrLength(char* str) {     
	int i = 0;
	while (str[i] != '\0') 
		i++;
	return i;
}

// 判断是否是字符
int IsChar(char ch) {
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		return 1;
	else
		return 0;
}
// 判断是否是运算符
int IsOperator(char ch) {                    
	if (ch == '>' || ch == '<' || ch == '=' || ch == '*' || ch == '-' || ch == '+' || ch == '#')
		return 1;
	else
		return 0;
}
// 判断是否是数字
int IsDigit(char ch) {               
	if ((ch >= '0' && ch <= '9'))
		return 1;
	else
		return 0;
}
// 判断是是否界符
int IsBoundary(char ch) {          
	if (ch == ';' || ch == '.' || ch == ',' || ch == '(' || ch == ')')
		return 1;
	else
		return 0;
}
// 判断是否是保留字
int IsReservedWord(char* str) {          
	for (int i = 0; i < 20; i++) 
		if (reservedWord[i].compare(str) == 0) 
			return 1;
	return 0;
}

// 判断字符串是否合法,合法则保存到单词表中
void ProcessString(char ch) {
	// 字符串 或 数字
	if (IsChar(ch) || IsDigit(ch)) { 
		StrConnect(word, ch);
		charIndex++;
		ProcessString(charTable[charIndex]); //处理下一个字符
	}
	// 运算符或界符等,表示当前单词停止
	else if (ch == ' ' || ch == '\n' || ch == '\0' || IsOperator(ch) || IsBoundary(ch)) {
		// 判断为保留字
		if (IsReservedWord(word)) {
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
			word[0] = '\0';	// word变量初始化
		}
		// 否则判断为标识符
		else {
			if (StrLength(word) >= 8) 
				printf("(标识符长度超长,%s,行号:%d)\n", word, lineNumber);
			else 
				wordTable[wordIndex++] = word; 
			word[0] = '\0';
		}
	}
	// 非法字符(串)
	else {
		StrConnect(word, ch);
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		charIndex++;
		word[0] = '\0';
	}
}
// 判断数字串是否合法,合法则保存到单词表中
void ProcessNumber(char ch) {
	// 数字
	if (IsDigit(ch)) {
		StrConnect(word, charTable[charIndex]);
		charIndex++;
		ProcessNumber(charTable[charIndex]);
	}
	// 无符号整数
	else if (!IsChar(ch)) {
		if (StrLength(word) >= 6) 
			printf("(无符号整数越界,%s,行号:%d)\n", word, lineNumber);
		else 
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
		word[0] = '\0';
	}
	// 非法字符(串)
	else {
		while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
			StrConnect(word, charTable[charIndex]);
			charIndex++;
		}
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		word[0] = '\0';
	}
}

// 变量名声明判断
int id() {
	// 拷贝当前读取的单词到word变量中
	int i = 0;
	for (i = 0; i < wordTable[wordIndex].length(); i++) 
		word[i] = wordTable[wordIndex][i];
	word[i] = '\0';
	// 判断该单词不是保留字且不为空
	if (!IsReservedWord(word) && word[0] != '.') {
		wordIndex++;
	}
	else PrintError(1);
}
// 子程序
void subroutine() {
	// 当前单词表匹配 const —— 常量定义
	if (!wordTable[wordIndex].compare("const")) {
		wordIndex++;
		constant();
		// 匹配 "," 说明存在多个变量定义 
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			constant(); // 处理判断下一个常量
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			// 匹配换行符,进入下一行的识别
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++; // 函数加一
				annotation();
			}
			subroutine();
		}
		// 否则出错
		else {
			PrintError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
			annotation();
		}
	}
	// 当前单词表匹配 var
	else if (!wordTable[wordIndex].compare("var")) {
		wordIndex++;
		variable(); // 读下一个单词,变量 语法判断
		// 匹配 "," 说明有多个变量
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			variable();
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			while (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			annotation();
			subroutine();
		}
		// 否则出错
		else {
			PrintError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}

	}
	// 当前单词表匹配 procedure
	else if (!wordTable[wordIndex].compare("procedure")) {
		wordIndex++;
		id();
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			subroutine();
			if (!wordTable[wordIndex].compare(";")) {
				annotation();
				while (!wordTable[wordIndex].compare("\n")) {
					wordIndex++;
					lineNumber++;
					annotation();
				}
				wordIndex++;
			}
			else {
				PrintError(1);

			}
		} 
		// 否则出错
		else {
			PrintError(0);
			subroutine();
		}
		while (!wordTable[wordIndex].compare("procedure")) {
			wordIndex++;
			id();
			if (!wordTable[wordIndex].compare(";")) {
				wordIndex++;
				subroutine();
				if (!wordTable[wordIndex].compare(";")) wordIndex++;
				else  PrintError(1);
			}
			else {
				PrintError(0);
				subroutine();
			}
		}
	}
	// 当前单词表匹配 换行符
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}

	sentence(); // 迭代判断
}
// 常量
void constant() {    
	// 标识符处理判断
	identifier();
	// 匹配等号 = 
	if (!wordTable[wordIndex].compare("=")) {
		wordIndex++;
		number(); // 读入下一个数字进行判断
	}
	// 打印错误
	else PrintError(0);
}
// 变量
void variable() {    
	id();
}
// 语句分析
void sentence() {
	// 匹配 if 语句
	if (!wordTable[wordIndex].compare("if")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 then 语句
		if (!wordTable[wordIndex].compare("then")) {
			wordIndex++;
			// 如果换行,行数加一
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			PrintError(0);
			sentence();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 while 语句
	else if (!wordTable[wordIndex].compare("while")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 do 语句
		if (!wordTable[wordIndex].compare("do")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			PrintError(1);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
	}
	// 匹配 call 语句
	else if (!wordTable[wordIndex].compare("call")) {
		wordIndex++;
		id();
	}
	// 匹配 read 语句
	else if (!wordTable[wordIndex].compare("read")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			id(); 
			// 匹配 "," 说明有多个变量
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				id();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else  
				PrintError(1);
		}
		else if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		else  PrintError(0);
	}
	// 匹配 write 语句
	else if (!wordTable[wordIndex].compare("write")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			expression(); // 读下一个单词 表达式语法判断
			// 匹配 "," 说明有多个表达式
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else PrintError(0);
		}
		else {
			PrintError(1);
			expression();
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			if (!wordTable[wordIndex].compare(")")) wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else PrintError(0);
		}
	}
	// 匹配 begin 语句
	else if (!wordTable[wordIndex].compare("begin")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		sentence();  // 读下一个单词 语句语法判断
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		else {
			PrintError(0);
			sentence();
		}

		while (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		// 匹配 end 语句,说明语句判断结束
		if (!wordTable[wordIndex].compare("end")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
		} else {
			PrintError(0);
			return;
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 换行符
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 注解
	else if (!wordTable[wordIndex].compare("//") || !wordTable[wordIndex].compare("/*")) {
		annotation();
		subroutine();
	}
	else {
		int tt = 0;
		for (tt = 0; tt < wordTable[wordIndex].length(); tt++) word[tt] = wordTable[wordIndex][tt];
		word[tt] = '\0';
		if (!IsReservedWord(word) && word[0] != '.') {
			id();
			if (!wordTable[wordIndex].compare(":=")) wordIndex++;
			expression();
		}
	}
}
// 注释
void annotation() {
	// 匹配 "\n" 行数加一
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 "//" 为单行注解
	if (!wordTable[wordIndex].compare("//")) {
		wordIndex++;
		wordIndex++;
		while (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		annotation();
	}
	// 匹配 "/*" 为多行注解
	else if (!wordTable[wordIndex].compare("/*")) {
		wordIndex++;
		while (wordTable[wordIndex].compare("*/")) {
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else {
				wordIndex++;
			}
		}
		wordIndex++;
	}
	// 一直换行则行数一直加1
	while (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
}
// 条件分析
void condition() {        
	expression(); // 先进行 表达式 判断
	if (!wordTable[wordIndex].compare("=") || !wordTable[wordIndex].compare("#") || !wordTable[wordIndex].compare("<") || !wordTable[wordIndex].compare("<=") || !wordTable[wordIndex].compare(">") || !wordTable[wordIndex].compare(">=")) {
		wordIndex++;
		expression();
	}
	else if (!wordTable[wordIndex].compare("odd")) {
		wordIndex++;
		expression();
	}
	else 
		PrintError(0);
}
// 表达式
void expression() {       
	term(); // 先进行 项 判断
	if (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
		wordIndex++;
		term();
		while (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
			wordIndex++;
			term();
		}

	}
}
// 项
void term() {
	factor();// 先进行 因子 判断
	while (!wordTable[wordIndex].compare("*") || !wordTable[wordIndex].compare("/")) {
		wordIndex++;
		factor();
	}
}
// 因子
void factor() {       
	if (!wordTable[wordIndex].compare("(")) {
		wordIndex++;
		expression();
		if (!wordTable[wordIndex].compare(")")) {
			wordIndex++;
		}
		else PrintError(0);
	}
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	else wordIndex++;
}
// 数字
void number() {
	wordIndex++;
}
// 标识符
void identifier() {
	wordIndex++;
}


int main() {
	// 程序字符串输入
	charTable[0] = '\0';
	scanf("%[^\.]", charTable); // 读取输入流中的字符,直到遇到第一个句点('.')为止
	charTable[StrLength(charTable)] = '.'; // 在程序字符串结尾添加'.'作为标识符

	// 进行词法分析
	LexicalAnalysis();

	// 进行语法分析
	charIndex = 0;
	wordIndex = 0;
	lineNumber = 1;
	GrammaticalAnalysis();

	return 0;
}

        运行结果如下:

5、扩展

        添加文件输入的功能,程序能够读取指定目录下的源程序字符串txt文件,进行语法分析并将结果输出到指定的文件下。代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <sstream>
using namespace std;

/* ------------ 全局变量声明定义 ------------ */
int lineNumber = 1; // 当前行号

char charTable[2000];				// 字符表 —— 存储输入程序的 所有字符,包括空格、换行等
string wordTable[200] = { "\0" };	// 单词表 —— 存储输入程序的 所有单词,包括换行
char word[88] = "\0";				// 存储单个字符,添加到 wordTable 中

string ENDsign = "end.";	// 结束标识符
int charIndex = 0;			// 记录当前 charTable 字符个数
int wordIndex = 0;			// 记录当前 wordTable 单词个数

char errorMsg[2000] = "";	// 语法错误输出串,用于文件写入
int errorNum = 0;			// 语法错误个数
int errorLine = 0;			// 语法错误行

string reservedWord[20] = { // 保留字
	"begin","call", "const","do","end","if",
	"odd","procedure", "read","then",
	"var","while","write"
};


/* ------------ 函数声明 ------------ */
void LexicalAnalysis();			// 词法分析
void GrammaticalAnalysis();		// 语法分析
void OutputError(int type);		//语法错误输出
int ReadFile(char* path);		// 读取文件
int WriteFile(char* path);		// 写入文件
char* GenerateMessage(int lineNumber);// 生成语法错误字符串

void StrConnect(char* str, char ch);	// 拼接字符串
int StrLength(char* str);				// 计算字符串长度

int IsChar(char ch);			// 判断是否是字符
int IsOperator(char ch);		// 判断是否是运算符
int IsDigit(char ch);			// 判断是否是数字
int IsBoundary(char ch);		// 判断是是否界符
int IsReservedWord(char* str);	// 判断是否是保留字

void ProcessString(char ch);	// 判断字符串是否合法,合法则保存到单词表中
void ProcessNumber(char ch);	// 判断数字串是否合法,合法则保存到单词表中


int id();					// 变量名声明判断
void subroutine();			// 子程序
void constant();			// 常量定义
void variable();			// 变量定义
void sentence();			// 语句分析
void annotation();			// 注释
void condition();			// 条件分析
void expression();			// 表达式
void term();				// 项
void factor();				// 因子
void identifier();			// 标识符
void number();				// 数字


/* ------------ 函数定义 ------------ */
// 词法分析
void LexicalAnalysis() {
	while (charTable[charIndex] != '\0') { // 当前字符表未识别到结束符 '\0'
		if (charTable[charIndex] == '\0')
			break;
		if (charTable[charIndex] == ' ') {
			charIndex++;
			continue;
		}
		if (charTable[charIndex] == '\n') {
			wordTable[wordIndex++] = "\n";  // 将 换行符 保存到单词表 wordTable 中
			charIndex++;
			lineNumber++;	// 程序换行,行数加一
		}
		// 识别到字符
		else if (IsChar(charTable[charIndex])) {
			ProcessString(charTable[charIndex]); // 处理该字符之后的字符串
			continue;
		}
		// 识别到数字
		else if (IsDigit(charTable[charIndex])) {
			ProcessNumber(charTable[charIndex]); // 处理该数字之后的数字串
			continue;
		}
		// 识别到'/' 符
		else if (charTable[charIndex] == '/') {
			// 之后是 '/' ,说明是注释 //
			if (charTable[charIndex + 1] == '/') {
				wordTable[wordIndex++] = "//";
				charIndex = charIndex + 2;
				word[0] = '\0';

				while (charTable[charIndex] != '\n') // 将未换行的字符全部识别为注释
					StrConnect(word, charTable[charIndex++]);
				wordTable[wordIndex++] = word;
				wordTable[wordIndex++] = "\n";
				charIndex++;
				continue;
			}
			// 之后是 '*' ,说明是注释 /*
			else if (charTable[charIndex + 1] == '*') {
				wordTable[wordIndex++] = "/*";
				charIndex = charIndex + 2;
				while (!(charTable[charIndex] == '*' && charTable[charIndex + 1] == '/')) {
					if (charTable[charIndex] == '\n') {
						wordTable[wordIndex++] = "\n";
						charIndex++;
						continue;
					}
					word[0] = '\0';
					while (charTable[charIndex] != '\n') StrConnect(word, charTable[charIndex++]);
					wordTable[wordIndex++] = word;
					wordTable[wordIndex++] = "\n";
					charIndex++;
				}
				wordTable[wordIndex++] = "*/";
				charIndex = charIndex + 2;
				word[0] = '\0';
				continue;
			}
			// 是非法字符(串)
			else {
				while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
					StrConnect(word, charTable[charIndex]);
					charIndex++;
				}
				printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
				word[0] = '\0';
				break;
			}
		}
		// 识别到比较符
		else if (charTable[charIndex] == '<' || charTable[charIndex] == '>') {
			charIndex++;
			// 是 <= 或者 >= 符
			if (charTable[charIndex] == '=') {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<="; // 保存单词表
				else
					wordTable[wordIndex] = ">="; // 保存单词表
				wordIndex++;
				charIndex++;
				continue;
			}
			// 是 < 或者 > 符
			else {
				if (charTable[charIndex - 1] == '<')
					wordTable[wordIndex] = "<"; // 保存单词表
				else
					wordTable[wordIndex] = ">"; // 保存单词表
				wordIndex++;
				continue;
			}
		}
		// 识别到':'
		else if (charTable[charIndex] == ':') {
			charIndex++;
			if (charTable[charIndex] == '=') {
				wordTable[wordIndex++] = ":="; // 保存单词表
				charIndex++;
				continue;
			}
			else {
				printf(":后面不是=号\n");
				continue;
			}
		}
		// 识别到运算符
		else if (IsOperator(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到界符
		else if (IsBoundary(charTable[charIndex])) {
			wordTable[wordIndex++] = charTable[charIndex]; // 保存单词表
			charIndex++;
			continue;
		}
		// 识别到非法字符(串)
		else {
			printf("(非法字符(串),%c,行号:%d)\n", charTable[charIndex], lineNumber);
			charIndex++;
		}
	}
}
// 语法分析
void GrammaticalAnalysis() {
	subroutine();
	if (!wordTable[wordIndex].compare(".")) {
		if (errorNum == 0) {
			printf("语法正确\n");
			strcat(errorMsg, "语法正确\n");
		}
			

	}
	else {
		OutputError(0); // 输出语法错误以及行号
		return;
	}
}
// 输出语法错误
void OutputError(int type) {
	if (type == 1) {
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			strcat(errorMsg, GenerateMessage(lineNumber));
			errorNum++;
		}
	}
	else {
		while (wordTable[wordIndex].compare("\n") != 0) 
			wordIndex++;
		if (errorLine != lineNumber) {
			errorLine = lineNumber;
			printf("(语法错误,行号:%d)\n", lineNumber);
			strcat(errorMsg, GenerateMessage(lineNumber));
			errorNum++;
		}
	}
}
// 读取文件
int ReadFile(char* path) {
	FILE* file;
	file = fopen(path, "r");
	if (file == NULL) {
		printf("file is error.");
		return -1;
	}
	int len;
	for (len = 0; len < 2048; len++) {
		fscanf(file, "%c", &charTable[len]);
		if (charTable[len] == '.') {
			len++;
			break;
		}
	}
	charTable[len] = '\0';
	fclose(file);
	return len;
}
// 写入文件
int WriteFile(char* path) {
	FILE* file = NULL;
	file = fopen(path, "w+");
	if (file == NULL) {
		printf("file is error.");
		return -1;
	}
	fputs(errorMsg, file);
	fclose(file);
	return 1;
}
// 生成语法错误字符串
char* GenerateMessage(int lineNumber) {
	char msg[24] = "(语法错误,行号:";
	char endMsg[5] = ")\n";
	char num[5];
	_itoa_s(lineNumber, num, 10);
	strcat(msg, num);
	strcat(msg, endMsg);
	return msg;
}

// 拼接字符串
void StrConnect(char* str, char ch) {        
	int i = 0;
	while (str[i] != '\0') i++;
	str[i] = ch;
	str[i + 1] = '\0';
}
// 计算字符串长度
int StrLength(char* str) {     
	int i = 0;
	while (str[i] != '\0') 
		i++;
	return i;
}

// 判断是否是字符
int IsChar(char ch) {
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		return 1;
	else
		return 0;
}
// 判断是否是运算符
int IsOperator(char ch) {                    
	if (ch == '>' || ch == '<' || ch == '=' || ch == '*' || ch == '-' || ch == '+' || ch == '#')
		return 1;
	else
		return 0;
}
// 判断是否是数字
int IsDigit(char ch) {               
	if ((ch >= '0' && ch <= '9'))
		return 1;
	else
		return 0;
}
// 判断是是否界符
int IsBoundary(char ch) {          
	if (ch == ';' || ch == '.' || ch == ',' || ch == '(' || ch == ')')
		return 1;
	else
		return 0;
}
// 判断是否是保留字
int IsReservedWord(char* str) {          
	for (int i = 0; i < 20; i++) 
		if (reservedWord[i].compare(str) == 0) 
			return 1;
	return 0;
}

// 判断字符串是否合法,合法则保存到单词表中
void ProcessString(char ch) {
	// 字符串 或 数字
	if (IsChar(ch) || IsDigit(ch)) { 
		StrConnect(word, ch);
		charIndex++;
		ProcessString(charTable[charIndex]); //处理下一个字符
	}
	// 运算符或界符等,表示当前单词停止
	else if (ch == ' ' || ch == '\n' || ch == '\0' || IsOperator(ch) || IsBoundary(ch)) {
		// 判断为保留字
		if (IsReservedWord(word)) {
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
			word[0] = '\0';	// word变量初始化
		}
		// 否则判断为标识符
		else {
			if (StrLength(word) >= 8) 
				printf("(标识符长度超长,%s,行号:%d)\n", word, lineNumber);
			else 
				wordTable[wordIndex++] = word; 
			word[0] = '\0';
		}
	}
	// 非法字符(串)
	else {
		StrConnect(word, ch);
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		charIndex++;
		word[0] = '\0';
	}
}
// 判断数字串是否合法,合法则保存到单词表中
void ProcessNumber(char ch) {
	// 数字
	if (IsDigit(ch)) {
		StrConnect(word, charTable[charIndex]);
		charIndex++;
		ProcessNumber(charTable[charIndex]);
	}
	// 无符号整数
	else if (!IsChar(ch)) {
		if (StrLength(word) >= 6) 
			printf("(无符号整数越界,%s,行号:%d)\n", word, lineNumber);
		else 
			wordTable[wordIndex++] = word; // 保存到单词表 wordTable 中
		word[0] = '\0';
	}
	// 非法字符(串)
	else {
		while (charTable[charIndex] != ' ' && IsBoundary(charTable[charIndex]) != 1 && charTable[charIndex] != '\0') {
			StrConnect(word, charTable[charIndex]);
			charIndex++;
		}
		printf("(非法字符(串),%s,行号:%d)\n", word, lineNumber);
		word[0] = '\0';
	}
}

// 变量名声明判断
int id() {
	// 拷贝当前读取的单词到word变量中
	int i = 0;
	for (i = 0; i < wordTable[wordIndex].length(); i++) 
		word[i] = wordTable[wordIndex][i];
	word[i] = '\0';
	// 判断该单词不是保留字且不为空
	if (!IsReservedWord(word) && word[0] != '.') {
		wordIndex++;
	}
	else OutputError(1);
}
// 子程序
void subroutine() {
	// 当前单词表匹配 const —— 常量定义
	if (!wordTable[wordIndex].compare("const")) {
		wordIndex++;
		constant();
		// 匹配 "," 说明存在多个变量定义 
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			constant(); // 处理判断下一个常量
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			// 匹配换行符,进入下一行的识别
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++; // 函数加一
				annotation();
			}
			subroutine();
		}
		// 否则出错
		else {
			OutputError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
			annotation();
		}
	}
	// 当前单词表匹配 var
	else if (!wordTable[wordIndex].compare("var")) {
		wordIndex++;
		variable(); // 读下一个单词,变量 语法判断
		// 匹配 "," 说明有多个变量
		while (!wordTable[wordIndex].compare(",")) {
			wordIndex++;
			variable();
		}
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			while (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			annotation();
			subroutine();
		}
		// 否则出错
		else {
			OutputError(0);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
				annotation();
			}
			subroutine();
		}

	}
	// 当前单词表匹配 procedure
	else if (!wordTable[wordIndex].compare("procedure")) {
		wordIndex++;
		id();
		// 匹配 ";" 说明变量声明结束
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			subroutine();
			if (!wordTable[wordIndex].compare(";")) {
				annotation();
				while (!wordTable[wordIndex].compare("\n")) {
					wordIndex++;
					lineNumber++;
					annotation();
				}
				wordIndex++;
			}
			else {
				OutputError(1);

			}
		} 
		// 否则出错
		else {
			OutputError(0);
			subroutine();
		}
		while (!wordTable[wordIndex].compare("procedure")) {
			wordIndex++;
			id();
			if (!wordTable[wordIndex].compare(";")) {
				wordIndex++;
				subroutine();
				if (!wordTable[wordIndex].compare(";")) wordIndex++;
				else  OutputError(1);
			}
			else {
				OutputError(0);
				subroutine();
			}
		}
	}
	// 当前单词表匹配 换行符
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}

	sentence(); // 迭代判断
}
// 常量
void constant() {    
	// 标识符处理判断
	identifier();
	// 匹配等号 = 
	if (!wordTable[wordIndex].compare("=")) {
		wordIndex++;
		number(); // 读入下一个数字进行判断
	}
	// 打印错误
	else OutputError(0);
}
// 变量
void variable() {    
	id();
}
// 语句分析
void sentence() {
	// 匹配 if 语句
	if (!wordTable[wordIndex].compare("if")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 then 语句
		if (!wordTable[wordIndex].compare("then")) {
			wordIndex++;
			// 如果换行,行数加一
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			OutputError(0);
			sentence();
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 while 语句
	else if (!wordTable[wordIndex].compare("while")) {
		wordIndex++;
		condition(); // 读下一个单词,条件 语法判断
		// 条件判断后,匹配 do 语句
		if (!wordTable[wordIndex].compare("do")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence(); // 读下一个单词,语句 语法判断
		}
		// 不匹配,报错
		else {
			OutputError(1);
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
	}
	// 匹配 call 语句
	else if (!wordTable[wordIndex].compare("call")) {
		wordIndex++;
		id();
	}
	// 匹配 read 语句
	else if (!wordTable[wordIndex].compare("read")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			id(); 
			// 匹配 "," 说明有多个变量
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				id();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else  
				OutputError(1);
		}
		else if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		else  OutputError(0);
	}
	// 匹配 write 语句
	else if (!wordTable[wordIndex].compare("write")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("(")) {
			wordIndex++;
			expression(); // 读下一个单词 表达式语法判断
			// 匹配 "," 说明有多个表达式
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			// "(" 匹配 ")" ,结束判断
			if (!wordTable[wordIndex].compare(")")) 
				wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else OutputError(0);
		}
		else {
			OutputError(1);
			expression();
			while (!wordTable[wordIndex].compare(",")) {
				wordIndex++;
				expression();
			}
			if (!wordTable[wordIndex].compare(")")) wordIndex++;
			else if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else OutputError(0);
		}
	}
	// 匹配 begin 语句
	else if (!wordTable[wordIndex].compare("begin")) {
		wordIndex++;
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		sentence();  // 读下一个单词 语句语法判断
		if (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		else {
			OutputError(0);
			sentence();
		}

		while (!wordTable[wordIndex].compare(";")) {
			wordIndex++;
			annotation();
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			sentence();
		}
		// 匹配 end 语句,说明语句判断结束
		if (!wordTable[wordIndex].compare("end")) {
			wordIndex++;
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
		} else {
			OutputError(0);
			return;
		}
		if (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
	}
	// 匹配 换行符
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 注解
	else if (!wordTable[wordIndex].compare("//") || !wordTable[wordIndex].compare("/*")) {
		annotation();
		subroutine();
	}
	else {
		int tt = 0;
		for (tt = 0; tt < wordTable[wordIndex].length(); tt++) word[tt] = wordTable[wordIndex][tt];
		word[tt] = '\0';
		if (!IsReservedWord(word) && word[0] != '.') {
			id();
			if (!wordTable[wordIndex].compare(":=")) wordIndex++;
			expression();
		}
	}
}
// 注释
void annotation() {
	// 匹配 "\n" 行数加一
	if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	// 匹配 "//" 为单行注解
	if (!wordTable[wordIndex].compare("//")) {
		wordIndex++;
		wordIndex++;
		while (!wordTable[wordIndex].compare("\n")) {
			wordIndex++;
			lineNumber++;
		}
		annotation();
	}
	// 匹配 "/*" 为多行注解
	else if (!wordTable[wordIndex].compare("/*")) {
		wordIndex++;
		while (wordTable[wordIndex].compare("*/")) {
			if (!wordTable[wordIndex].compare("\n")) {
				wordIndex++;
				lineNumber++;
			}
			else {
				wordIndex++;
			}
		}
		wordIndex++;
	}
	// 一直换行则行数一直加1
	while (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
}
// 条件分析
void condition() {        
	expression(); // 先进行 表达式 判断
	if (!wordTable[wordIndex].compare("=") || !wordTable[wordIndex].compare("#") || !wordTable[wordIndex].compare("<") || !wordTable[wordIndex].compare("<=") || !wordTable[wordIndex].compare(">") || !wordTable[wordIndex].compare(">=")) {
		wordIndex++;
		expression();
	}
	else if (!wordTable[wordIndex].compare("odd")) {
		wordIndex++;
		expression();
	}
	else 
		OutputError(0);
}
// 表达式
void expression() {       
	term(); // 先进行 项 判断
	if (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
		wordIndex++;
		term();
		while (!wordTable[wordIndex].compare("+") || !wordTable[wordIndex].compare("-")) {
			wordIndex++;
			term();
		}

	}
}
// 项
void term() {
	factor();// 先进行 因子 判断
	while (!wordTable[wordIndex].compare("*") || !wordTable[wordIndex].compare("/")) {
		wordIndex++;
		factor();
	}
}
// 因子
void factor() {       
	if (!wordTable[wordIndex].compare("(")) {
		wordIndex++;
		expression();
		if (!wordTable[wordIndex].compare(")")) {
			wordIndex++;
		}
		else OutputError(0);
	}
	else if (!wordTable[wordIndex].compare("\n")) {
		wordIndex++;
		lineNumber++;
	}
	else wordIndex++;
}
// 数字
void number() {
	wordIndex++;
}
// 标识符
void identifier() {
	wordIndex++;
}



int main() {
	// 程序字符串输入
	char readPath[200];
	char writePath[200];
	printf("输入源程序路径:");
	scanf("%s", readPath);
	printf("输入语法输出文件路径:");
	scanf("%s", writePath);

	if (ReadFile(readPath) != -1) {
		// 进行词法分析
		LexicalAnalysis();

		// 进行语法分析
		charIndex = 0;
		wordIndex = 0;
		lineNumber = 1;
		GrammaticalAnalysis();

		WriteFile(writePath);
	}
	return 0;
}

        指定的文件如下:

         运行结果如下:

       读取源程序文件:

         写入结果文件:

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

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

相关文章

CoreDX DDS应用开发指南(4)DDS实体h和主题

6 DDS实体 DDS标准定义了一个体系结构,该体系结构表示构成DDS API实体的面向对象模型。这些实体充当中间件和应用软件之间的接口。为了开发支持DDS的应用程序,开发人员必须创建、交互并销毁这些DDS实体。 本章概述了DDS实体和相关概念。 6.1 DDS实体层次结构 构成DDS API的主…

马斯克最大的挑战是什么?

“硅谷钢铁侠”马斯克&#xff0c;最大的挑战是什么&#xff1f; 有纠错反馈循环&#xff0c;并保持这个循环 我们常说的“迭代”&#xff0c;就是打造“反馈系统” 趣讲大白话&#xff1a;需要一面不扭曲的镜子 【趣讲信息科技192期】 **************************** 2017年&a…

通过浏览器,将webp格式图片转jpg格式

概述 我们网络上下载的图片&#xff0c;很多的是webp格式的图片&#xff0c;而目前支持这种图片格式的软件较少&#xff0c;比如Windows 照片查看器&#xff0c;是不能直接打开图片的。安装其他专业图像软件又麻烦。 因此&#xff0c;本文介绍利用电脑常用的软件&#xff0c;…

运营-20.产品社区化和内容化

产品社区化和内容化 为什么现在很多产品都在往社区化、内容化发展&#xff1f; 1.拓展产品线&#xff0c;满足用户的多元需求 分享、交流、炫耀、虚荣&#xff0c;这些是人类永恒的情感需求&#xff0c;社区是一个能很好的满足这些需求的工具&#xff1b; 2.打造归属感&…

TiDB亿级数据亚秒响应查询Dashboard使用

目录 1 集群概况1.1 QPS1.1.1 延迟1.1.2 Top SQL 语句1.1.3 最近的慢查询 2 集群信息2.1 实例列表2.1.1 表格列解释2.1.2 实例状态解释 2.2 主机列表2.2.1 表格列解释 2.3 SQL语句分析2.3.1 执行列表页2.3.2 执行详情页面 2.4 慢查询2.4.1 慢查询列表页2.4.2 查看执行详情 2.5 …

2023-06-10 Untiy进阶 C#知识补充1——.Net介绍

文章目录 一、.Net 介绍二、.Net 跨语言的实现三、.Net 跨平台的实现&#xff08;一&#xff09;.Net Framework&#xff08;二&#xff09;.Net Core&#xff08;三&#xff09;Mono 四、总结 一、.Net 介绍 ​ 微软的 .Net 既不是编程语言也不是框架&#xff0c;是类似于互联…

Tomcat部署和优化

文章目录 Tomcat概述Tomcat的核心组件Tomcat的功能组件结构Container 结构分析Tomcat 请求过程&#xff1a; Tomcat 服务部署Tomcat 虚拟主机配置HTTP 请求过程 Tomcat优化常用的优化相关参数如下 Tomcat概述 Tomcat 是 Java 语言开发的&#xff0c;Tomcat 服务器是一个免费的…

Spring高手之路4——深度解析Spring内置作用域及其在实践中的应用

文章目录 1. Spring的内置作用域2. singleton作用域2.1 singleton作用域的定义和用途2.2 singleton作用域线程安全问题 3. prototype作用域3.1 prototype作用域的定义和用途3.2 prototype作用域在开发中的例子 4. request作用域&#xff08;了解&#xff09;5. session作用域&a…

002docker 安装

官网安装https://docs.docker.com/engine/install/ 系统要求 Centos7 Linux 内核&#xff1a;官方建议 3.10 以上查看Linux内核版本 用于打印当前系统的相关信息(内核版本号,硬件架构,主机名称和操作系统类型等 cat /proc/version uname -a 更新YUM源 生产环境中此步操作…

Spring Cloud Feign实战

概述 Feign是一种声明式、模板化的HTTP Client&#xff0c;目标是使编写Java HTTP Client变得更简单。Feign通过使用Jersey和CXF等工具实现一个HTTP Client&#xff0c;用于构建REST或SOAP的服务。Feign还支持用户基于常用的HTTP工具包&#xff08;OkHTTP、HTTPComponents&…

2023网安面试题170道,轻松应对面试

最近有不少小伙伴跑来咨询&#xff1a; 想找网络安全工作&#xff0c;应该要怎么进行技术面试准备&#xff1f; 工作不到 2 年&#xff0c;想跳槽看下机会&#xff0c;有没有相关的面试题呢&#xff1f; 为了更好地帮助大家高薪就业&#xff0c;今天就给大家分享两份网络安全工…

仙境传说ro:如何在地图上刷怪教程

仙境传说ro&#xff1a;如何在地图上刷怪教程 大家好我是艾西&#xff0c;在仙境传说这个游戏中我们知道了怎么创建NPC添加商品售卖后&#xff0c;那么对于游戏的怪肯定也得有自己的想法以及对游戏的设定以及理解&#xff0c;今天我跟大家分享的是怎么在地图中刷怪教程。 我们…

STL——string、vector、deque容器

初识STL **STL的基本概念****vector容器存放内置数据类型****vector容器中存放自定义数据类型****vector容器嵌套vector容器****string容器——构造函数****string容器——赋值操作****string容器——字符串拼接****string容器——字符串的查找和替换****string容器——字符串比…

人工智能该如何学习?详细的AI学习

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 1.TomChat 地址&#xff1a;https://www.ridderchat.com/ 该网站非常简介好看&#xff0c;界面看着很舒服&#xff0c;可以帮助你快速编写、编辑和讨论代码。 2.强大的AI辅助 链接…

模拟实现strstr函数,通俗易懂!!!

函数介绍 函数声明 函数声明&#xff1a;char *strstr(const char *str1, const char *str2) 头 文 件&#xff1a;#include <string.h> 返 回 值&#xff1a; 返回值为char * 类型&#xff08; 返回指向 str1 中第一次出现的 str2 的指针&#xff09;&#xff1b…

Webots R2021a教程

文章目录 Windows安装设置中文打开世界添加贴图 为外部控制器配置Anaconda解决报错&#xff1a;CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.调用Python API Windows 安装 进入下载页面 https://github.com/cyberbotics/webots/r…

CSS实现几种常见布局

CSS实现几种常见布局 两列左窄右宽型布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" co…

【面试题】2023前端面试系列-- Vue 篇

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 Vue 常见面试题总结 MVVM模型&#xff1f; MVVM&#xff0c;是Model-View-ViewModel的简写…

001docker架构介绍

docker 官网Choose the best method for you to install Docker Engine. This client-server application is available on Linux, Mac, Windows, and as a static binary.https://docs.docker.com/engine/install/ 介绍 Docker用Go编程语言编写&#xff0c;并利用Linux内核的…

算法刷题-链表-两两交换链表中的节点

两两交换链表中的节点 24. 两两交换链表中的节点思路其他语言版本 24. 两两交换链表中的节点 力扣题目链接 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 思…