⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 explain.cpp

📁 c语言写的VB编译器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		getftime(fileno(stream), &ft);
		fclose(stream);

		// 如果需要,分别对月,日,小时,分钟,秒分别进行前部加“0”处理
		HeadZero(ft.ft_month, Month);
		HeadZero(ft.ft_day, Day);
		HeadZero(ft.ft_hour, Hour);
		HeadZero(ft.ft_min, Minute);
		HeadZero(ft.ft_tsec * 2, Sec);

		// 设置输出文件名格式
		sprintf(Name, "%-12s", ffblk.ff_name);

		// 设置底部信息栏信息格式
		sprintf(Mess, "Date : %4u-%s-%s %c Time : %s:%s:%s %c Size : %ld",
			ft.ft_year+1980, Month, Day, 179, Hour, Minute, Sec, 179, ffblk.ff_fsize);

		// 将当前文件加入列表
		lstOpenFile.Add(Name, Mess);

		// 搜索下一个源文件
		Done = findnext(&ffblk);
	}

	// 对列表按文件名升序进行排序
	lstOpenFile.Sort();

	// 用户选中的文件序号
	int Sign;

	// 存储选中文件的文件名
	char Name[MaxLenOfFileName] = "";

	do
	{
		// 隐藏光标
		_setcursortype(_NOCURSOR);

		// 打印列表
		lstOpenFile.Show();

		// 当代用户选择,并返回选择序号
		Sign = lstOpenFile.Work();

		if (Sign > 0)
		{
			// 用户选择了一个已存在的文件

			// 取出文件名
			strcpy(Name, lstOpenFile.ItemName(Sign));

			// 删除尾部空格
			ClearTailBlank(Name);
		}
		else if (Sign == 0)
		{
			// 用户选择新建一个文件

			// 打开窗口等待用户输入文件名
			winGetFileName.Show();
			winGetFileName.GetInput(Name, 10, 46, MaxLenOfFileName);
			winGetFileName.Hide();
		}
	} while (Name[0] == '\0' && Sign != Cancel);

	// 隐藏打开文件列表
	lstOpenFile.Hide();

	int i = 0;

	if (Sign != Cancel && Name != '\0')
	{
		// 可以打开文件或建立新的文件

		if (!strchr(Name, '.'))
		{
			// 若没有扩展名则自动添加扩展名
			strcat(Name, ".BAS");
		}

		FILE *fi;
		if ((fi = fopen(Name, "r")) != NULL)
		{
			// 文件已存在

			// 以新文件设置参数
			NewFile(Name);

			while (!feof(fi))
			{
				// 文件未读完

				if (i > TotRoomLine)
				{
					// 需要申请新的文本行空间

					// 申请新的文本行空间
					NewLine();

					if (Error)
					{
						// 无剩余内存可申请

						// 重置错误代码
						Error = NoError;

						// 重置编辑窗口标题为默认文件
						winEdit.SetTitle(DefaultFileName);
						winEdit.RefreshTitle();

						return;
					}
				}

				// 读入文件的一行
				char Chr;

				int Len = -1;
				Chr = fgetc(fi);
				while (Chr != '\n' && Len < MaxY - 2 && !feof(fi))
				{
					if (Chr == '\t')
					{
						for (int j = 0; j < TabSize && Len < MaxY - 1; j++)
						{
							Len++;
						}
					}
					else
					{
						Len++;
						Text[i]->Line[Len] = Chr;
					}

					Chr = fgetc(fi);
				}

				StandardizeLine(i);

				// 该行未着色
				Text[i]->Sign[0] = ' ';

                // 该行无标记
				Text[i]->Mark = false;

				// 该行无断点
				Text[i]->Break = false;

				// 准备下一行
				i++;
			}

			// 关闭文件
			fclose(fi);

			// 设置最后一行序号
			EndLine = i - 1;

			// 设置编辑窗口文本高度
			winEdit.SetTotHigh(EndLine);

			// 打印编辑窗口当前屏文本
			PrintText(winEdit.Top() + 1);
		}
		else if (fopen(Name, "w") == NULL)
		{
			// 无此文件

			// 打开文件错误
			ShowError(ErrorOpening);
		}
		else
		{
			// 是新文件

			// 打开新文件
			NewFile(Name);
		}
	}

	SetCursor();
}

int SaveFile
	(
	const char Name[MaxLenOfFileName]	// 文件名
	)
{
	// 存盘

	if (strcmp(Name, DefaultFileName) == 0)
	{
		// 当前使用默认文件名,需要输入文件名

		return SaveAsFile();
	}

	FILE *fo;

	if ((fo = fopen(Name, "w")) != NULL)
	{
		char Line[MaxY];
		for (int i = 0; i <= EndLine; i++)
		{
			// 清除尾部空格
			strcpy(Line, Text[i]->Line);
			ClearTailBlank(Line);

			// 将本行写入磁盘
			fprintf(fo, "%s", Line);
			if (i < EndLine)
			{
				// 不是最后一行

				// 打印回车
				fprintf(fo, "\n");
			}
		}

		// 关闭文件
		fclose(fo);

		// 设置修改标志
		ShowSaved(true);
	}
	else
	{
		// 存盘错误

		ShowError(ErrorSaving, -1, "");
	}

	return Yes;
}

int SaveAsFile()
{
	// 存储文件名
	char Name[MaxY];

	// 显示查询文件名窗口
	winGetFileName.Show();

	bool FileNameOK = false;
	do
	{
		// 等待用户输入文件名
		winGetFileName.GetInput(Name, 10, 46, MaxLenOfFileName);
		FileNameOK = IsFileName(Name);
		if (!FileNameOK)
		{
			Sound();
		}
	} while (Name[0] != '\0' && (strcmp(Name, DefaultFileName) == 0 || !FileNameOK));

	// 隐藏查询文件名窗口
	winGetFileName.Hide();

	if (Name[0] != '\0')
	{

		if (strlen(Name) > 8)
		{
			Name[8] = '\0';
		}

		if (!strchr(Name, '.'))
		{
			// 没有扩展名

			// 添加默认扩展名
			strcat(Name, ".BAS");
		}

		strupr(Name);

		FILE *fi;
		if ((fi = fopen(Name, "r")) != NULL)
		{
			// 文件已经存在

			// 关闭文件
			fclose(fi);

			// 询问用户是否覆盖
			winAsk.Clear();
			winAsk.Add(" Overwrite the file(Y/N)?");

			int Return = Ask();
			switch(Return)
			{
			case Yes:
				break;
			case No:
			case Cancel:
				return Return;
			}
		}

		// 存盘
		SaveFile(Name);

		if (Error)
		{
			Error = NoError;
			return No;
		}

		// 设置编辑窗口标题
		winEdit.SetTitle(Name);

		// 刷新标题
		winEdit.RefreshTitle();

		return Yes;
	}

	return No;
}

void PrintFile()
{
	// 输出文件到打印机

	if (fprintf(stdprn, "======= %s =======\n", winEdit.Caption()) != EOF)
	{
		// 打印机工作正常

		// 临时存储文本行
		char Line[MaxY];

		for (int i = 0; i <= EndLine; i++)
		{
			// 复制文本行
			strcpy(Line, Text[i]->Line);

			// 删除尾部空格
			ClearTailBlank(Line);

			// 输出到打印机
			fprintf(stdprn, "%s\n", Line);
		}
	}
	else
	{
		// 打印机无法正常工作

		// 输出错误
		ShowError(ErrorPrint);

		Error = NoError;
	}
}

void Quit()
{
	// 退出系统

	window(1, 1, 80, 25);

	// 设置颜色并清屏
	SetColor(WHITE,BLACK);
	clrscr();

	// 打印退出信息
	printf("Leaving from Cool Basic ...\n");

	// 程序中止
	exit(0);
}

void Standardize()
{
	// 对整个程序进行标准化

	for (int LineNo = 0; LineNo <= EndLine; LineNo++)
	{
		// 标准化一行

		StandardizeLine(LineNo);
	}
}

void StandardizeLine
	(
	const int LineNo	// 要处理的行号
	)
{
	// 标准化一行

	//暂存要标准化的字符串,便于扫描
	char Source[MaxY] = "";

	//标准化后的字符串
	char Return[2 * MaxY] = "";

	//暂存分隔的单词
	char Word[MaxY] = "";

	//暂存Word的大写字符串
	char WordUpcase[MaxY] = "";

	// 复制待处理的文本行到Source
	strcpy(Source, Text[LineNo]->Line);

	// 清除Source末尾的空格,便于处理
	ClearTailBlank(Source);

	// 复制Source前面的空格到Return,保持缩进
	int i = 0;
	while(Source[i] == ' ')
	{
		strcat(Return, " ");
		i++;
	}

	// 清除Source前部空格
	ClearHeadBlank(Source);

	// 取长度
	int Len = strlen(Source);

	// 置加锁标志,在涉及字符串处理中使用
	int Lock = false;

	for (i = 0; i <= Len; i++)
	{
		if (Source[i] == '"')
		{
			// 是字符串的开始或结尾

			// 加锁标志取反
			Lock = true + false - Lock;
		}

		if (Lock)
		{
			// 处于字符串中

			if (Word[0] != '\0')
			{
				// 单词非空

				// 做一份单词的全大写副本
				strcpy(WordUpcase, Word);
				strupr(WordUpcase);

				// 处理单词缓冲
				DealWord(Word, WordUpcase, Return, Lock);
			}

			if (Source[i] == '"')
			{
				// 本位是字符串开始处的引号

				if (Return[0] != '\0' && Return[strlen(Return) - 1] != ' ')
				{
					// 返回字符串非空,且返回字符串最后一位非空格

					// 返回字符串加空格
					strcat(Return, " ");
				}

				// 返回字符串添加本位的引号
				strcat(Return, "\"");
			}
			else
			{
				// 本位在字符串内部

				// 将本位原样复制到返回字符串中
				strcat(Return, " ");
				Return[strlen(Return) - 1] = Source[i];
			}

			// 处理下一位
			continue;
		}
		else if (Source[i] == '"')
		{
			// 本位是字符串结尾处的引号

			// 将本位的引号复制到返回字符串中
			strcat(Return, "\"");

			// 处理下一位
			continue;
		}

		if (Source[i] == ' ' || i == Len)
		{
			// 本位是空格,或已到源字符串末尾

			if (Word[0] != '\0')
			{
				// 单词非空

				// 做一份单词的全大写副本
				strcpy(WordUpcase, Word);
				strupr(WordUpcase);

				if (strcmp(WordUpcase, "REM") == 0)
				{
                    // 单词为REM

					// 将REM加入返回字符串
					strcat(Return, "REM");

					// 将后面的内容原样复制到返回字符串中
					for (int j = i; j <= Len; j++)
					{
						strcat(Return, " ");
						Return[strlen(Return) - 1] = Source[j];
					}

					// 处理完毕,退出循环
					break;
				}
				else
				{
					// 单词非REM,处理单词

					DealWord(Word, WordUpcase, Return, Lock);
				}
			}
		}
		else if (!Lock && IsSymbol(Source[i]))
		{
			// 非字符串,且本位是符号
			// 为了美观,必要的时候在符号的两边添加空格

			// 先处理单词
			if (Word[0] != '\0')
			{
				// 单词非空

				// 做一份单词的全大写副本
				strcpy(WordUpcase, Word);
				strupr(WordUpcase);

				// 处理单词
				DealWord(Word, WordUpcase, Return, Lock);
			}

			// 存储最后两位的字符串,用于下面在加前部空格时做双字节符号判断
			char Symbol2[3] = "00";

			if (i >= 1)
			{
				// 可以取源字符串的后两位

                Symbol2[0] = Source[i - 1];
				Symbol2[1] = Source[i];
			}

			// 开始加前部空格
			if (!strchr(",;()", Source[i]) &&

				strcmp(Symbol2, "<=") != 0 &&
				strcmp(Symbol2, ">=") != 0 &&
				strcmp(Symbol2, "<>") != 0 &&
				strcmp(Symbol2, "(+") != 0 &&
				strcmp(Symbol2, "(-") != 0 &&

				Return[0] != '\0' &&
				Return[strlen(Return) - 1] != ' ')
			{
				// 以下情况下,符号前面不加空格:
				// 1、逗号,分号,左括号,右括号
				// 2、前一位和本位连起来是下面这些情况:“<=”,“>=”,“<>”,“(+”,“(-”
				// 3、返回字符串末尾已经是空格

				strcat(Return, " ");
			}

			// 将本位的符号添加到返回字符串中
			strcat(Return, " ");
			Return[strlen(Return) - 1] = Source[i];

			strcpy(Symbol2, "00");
			Symbol2[0] = Source[i];
			if (i + 1 < strlen(Source))
			{
				Symbol2[1] = Source[i + 1];
			}

			// 开始添加尾部空格
			if (Source[i] != '(' &&
				Source[i] != ')' &&
				
				strcmp(Symbol2, "<=") != 0 &&
				strcmp(Symbol2, ">=") != 0 &&
				strcmp(Symbol2, "<>") != 0)
			{
				// 以下情况,符号后面不加空格:
				// 1、左括号,右括号
				// 2、本位和下一位连起来是下面这些情况:“<=”,“>=”,“<>”

				strcat(Return, " ");
			}
		}
		else
		{
			// 本位是字母和数字

			// 添加如单词
			strcat(Word, " ");
			Word[strlen(Word) - 1] = Source[i];
		}
	}

	Len = strlen(Return);

	if (Len > MaxY - 1)
	{
		Return[MaxY - 1] = '\0';
	}

	// 在末尾填充空格使其和编辑窗口等宽
	while(Len < MaxY - 1)
	{
		Len++;
		strcat(Return, " ");
	}

	// 用标准化后的字符串覆盖原文本
	strcpy(Text[LineNo]->Line, Return);

	Text[LineNo]->Sign[0] = ' ';
}

void DealWord
	(
	char *Word,						// 单词
	const char WordUpcase[MaxY],	// 单词的全大写副本
	char *Return,					// 返回字符串
	const int Lock					// 加锁标志
	)
{
	// 处理单词
	// StandardizeLine专用

	// 关键字序号,非关键字则为-1
	int KeyWordValue = -1;

	if (isalpha(Word[0]))
	{
		// 第一位是字母,是关键字的必要条件

		for (int i = 0; i < TotKeyWord; i++)
		{
			if (strcmp(KeyWord[i], WordUpcase) == 0)
			{
				// 关键字匹配成功,记下序号,退出
				KeyWordValue = i;
				break;
			}
		}
	}

	// 返回字符串的长度
	int Len = strlen(Return);

	if (Len > 0 && Return[Len - 1] != '(' && Return[Len - 1] != ' ' && !Lock)
	{
		// 以下情况,单词前不加空格:
		// 1、返回字符串最后一位是左括号
		// 2、返回字符串最后一位是空格
		strcat(Return, " ");
	}

	if (KeyWordValue >= 0)
	{
		// 是关键字,将大写的副本加入返回字符串

		strcat(Return, WordUpcase);

		if (strcmp(WordUpcase, "RND") != 0 &&
			strcmp(WordUpcase, "INT") != 0 &&
			strcmp(WordUpcase, "SQR") != 0)
		{
			strcat(Return, " ");
		}
	}
	else
	{
		// 不是关键字,将原文加入返回字符串
		strcat(Return, Word);
	}

	// 单词清空
	Word[0] = '\0';
}

void RunProgram()
{
	// 运行程序

	// 检查整个程序的语法
	CheckSyntax();

	if (Error)
	{
		return;
	}

	if (RunLineNo < 0)
	{
		// 从编辑状态开始运行程序

		// 清除全部变量空间
		ClearAll();

		window(1, 1, 80, 25);

		// 清屏
		CallCls();

		CreateTable();
		if (Error)
		{
			Error = NoError;
			return;
		}

		// 准备运行的行号
		RunLineNo = NextLine(0);
	}
	else
	{
		// 从调试状态继续执行

		// 保存当前准备执行的行号
		PreRunLineNo = RunLineNo;

		// 重新打印调试状态下准备执行的行,使其呈正常语句的颜色
		RunLineNo = -1;
		if (x0 <= PreRunLineNo && PreRunLineNo < x0 + winEdit.High())
		{
			// 准备执行的行在编辑窗口的本屏范围内

			// 重新打印该行
			PrintLine(PreRunLineNo);

			SetCursor();
		}
		RunLineNo = PreRunLineNo;

		// 存储编辑窗口画面
		gettext(1, 1, 80, 25, TextMirror);

		// 恢复输出窗口画面
		puttext(1, 1, 80, 25, OutMirror);

		// 置光标于当前输出的位置
		gotoxy(OutX, OutY);
	}

	do
	{
		// 执行当前语句,并返回下一个要执行的语句行号

		RunLineNo = NextLine(RunLine(RunLineNo));
	} while (!Finished && !Error && !Text[RunLineNo]->Break);

	if (!Error)
	{
		// 执行中没有错误,存储输出窗口画面

		gettext(1, 1, 80, 25, OutMirror);
	}
}

void DebugLine(const int LineNo)
{
	if (LineNo >= 0)
	{

		// 打印当前调试时的语句行

		gotoxy(winEdit.Left() + 1, LineNo + winEdit.Top() + 1 - x0);
		SetColor(BLACK, WHITE);
		cprintf("%-78s", Text[LineNo]->Line);
	}
}

void StepInto()
{
	// 单步执行语句,不进入SUB

	if (NextLine(0) == -1)
	{
		// 程序执行完毕,退出

		return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -