两个断点定位问题
用两个断点,不断缩少出现bug范围,定位错误位置.
方块为中文字符占2个字符
对于上次方块占位的时候,有空心方块
解决的方案是:以前是合起来,再分开避免的问题
现在直接用 showbrick 直接不画空心方块 就不做什么就可以了
这样直接ShowBackground ShowBrick 就可以了
对于词法分析器我们先从 单词数量开始.
如何统计一段文字中的单词个数
这是一道平时很常见的习题或者面试题
Hello World. I love you.
对以上文本(以空格作为单词分隔),统计单词个数
下面比较简单的版本:
#include"stdafx.h"
#include<stdio.h>
#include<string.h>
int WordNum(char *str)
{
int nCount = 0;
while (*str != 0)
{
if (*str == ' ')
{
nCount++;
}
str++;
}
return ++nCount;
}
int main(void)
{
char nArry[] = "Hello World. I love you. ";
printf("%d\r\n",WordNum(nArry) );
return 0;
}
这个版本是有bug的 :比如中间加空格,后面加空格都会影响结果。
所以就知道,不能仅仅以空格为评判标准
就像我们怎么知道这是一个单词,以人的直观角度去判断
那就是遇到空格前面是什么状态 如果是非空格 那么计数加一,如果是空格那么不计数
讲一下算法:
- 分为两种状态,分为空格,非空格状态;
- 由非空格到空格那么计数加一
- 其他情况不计数
用图解释:
然后根据图去写程序:
多余结束的时候我就图示舍去了
判断结束是否要加上1 就是判断‘\0’前面是否为非空格如果是那么计数加一
#include"stdafx.h"
#include<stdio.h>
#include<string.h>
#define STATE_START 0
#define STATE_BLANK 1
#define STATE_NONSPACE 2
int WordNum(char *pszContent)
{
int nState = STATE_START;
int nCount = 0;
while (*pszContent != '\0')
{
if (nState == STATE_START)
{
if (*pszContent == ' ')
{
nState = STATE_BLANK;
}
else
{
nState = STATE_NONSPACE;
}
}
else if (nState == STATE_BLANK)
{
if (*pszContent != ' ')
{
nState = STATE_NONSPACE;
}
}
else if (nState == STATE_NONSPACE)
{
if (*pszContent == ' ')
{
nState = STATE_BLANK;
nCount++;
}
}
pszContent++;
}
if (nState==STATE_NONSPACE)
{
if (*pszContent == '\0')
{
nCount++;
}
}
return nCount;
}
int main(void)
{
char nArry[] = "Hello World. I love you. ";
printf("%d\r\n",WordNum(nArry) );
return 0;
}
以上就是状态机(又称自动机,有限状态的自动机)
常常用于词法分析过程制作词法分析器
初级版本的词法分析器
词法分析就是将单词分类。比如C语言的字符,由多种分类:
- 标识符:以字母下划线开头,后面接字母,下划线,数字。
- 数字:以数字开头,后面接任意数字
- 分隔符号:\n \r \t ’ ’ 等
当然有人会说0x1234 分隔符号还有其他等问题 ,今天讲的初级版本就不涉及了。
我们可以将以上版本同时用状态机器表达出来
对应程序如下
如果不用彩色的化 将printf解锁,将wirtchar注释掉就可以了
#include"stdafx.h"
#include<stdio.h>
#include<string.h>
#include"setdisplay.h"
#define STATE_START 0
#define STATE_ID 1
#define STATE_NUM 2
#define STATE_DELM 3
#define STATE_EOF 4
int g_nCount = 0;
char* g_szWord = "int nValue1 = 1234;\nint nValue2 =5678;\n";
int IsDeline(char* pszContent)
{
if (*pszContent == '_')
{
return 1;
}
else
{
return 0;
}
}
int IsNum(char* pszContent)
{
if ((*pszContent >= '1'&&*pszContent <= '9'))
{
return 1;
}
else
{
return 0;
}
}
int IsID(char* pszContent)
{
if ((*pszContent >= 'a'&&*pszContent <= 'z') ||
(*pszContent >= 'A'&&*pszContent <= 'Z'))
{
return 1;
}
else
{
return 0;
}
}
int IsDelimter(char* pszContent)
{
if (*pszContent == ' '
|| *pszContent == '\n'
|| *pszContent == '\r'
|| *pszContent == '\t'
|| *pszContent == ';')
{
return 1;
}
else
{
return 0;
}
}
void ShowIt(char* pszContent1, char* pszContent2)
{
for (size_t i = 0; i < pszContent2 - pszContent1; i++)
{
printf("%c", *(pszContent1 + i));
}
printf("\r\n");
pszContent1 = pszContent2;
}
void Lexer(char *pszContent)
{
char* pStartContent = NULL;//开始指针
int nState = STATE_START;
while (*pszContent != '\0')
{
char* pszNextContent = pszContent;
if (nState == STATE_START)
{
if (IsID(pszNextContent) || IsDeline(pszNextContent))
{
pStartContent = pszContent;//记录开始标识
nState = STATE_ID;
}
else if (IsNum(pszNextContent))
{
pStartContent = pszContent;
nState = STATE_NUM;
}
else if (IsDelimter(pszNextContent))
{
nState = STATE_DELM;
}
}
else if (nState == STATE_ID)
{
if (IsDelimter(pszNextContent))
{
WriteChar(g_nCount, 0, "找到一个变量", SetConsoleColor(COLOR_LIGHTBLUE, COLOR_BLACK));
g_nCount++;
/* printf("找到一个变量");*/
ShowIt(pStartContent, pszContent);
nState = STATE_DELM;
}
else
{
}
}
else if (nState == STATE_NUM)
{
if (IsDelimter(pszNextContent))
{
WriteChar(g_nCount, 0, "找到一个数字", SetConsoleColor(COLOR_THIN_LIGHT_GREEN, COLOR_BLACK));
/*printf("找到一个数字");*/
g_nCount++;//坐标加1
ShowIt(pStartContent, pszContent);
nState = STATE_DELM;
}
else
{
}
}
else if (nState == STATE_DELM)
{
if (IsID(pszNextContent))
{
pStartContent = pszContent;
nState = STATE_ID;
}
else if (IsNum(pszNextContent) || IsDeline(pszNextContent))
{
pStartContent = pszContent;
nState = STATE_NUM;
}
}
pszContent++;
}
}
int main(void)
{
Lexer(g_szWord);
return 0;
}