user-0 提问: 控制输入只为数字的程序

回复:
user: user-1
content: 草了，居然没把数组类贴上来。。。。。。  class TABLE { 	long**m_data; public: 	long m_rowCount, m_colCount; 	long m_error, m_accept; public: 	TABLE() 	{ 		m_error = -1; 		m_accept = 1; 	} 	TABLE(long rowCount, long colCount) 	{ 		m_error = -1; 		m_accept = 1; 		Create(rowCount, colCount); 	} 	~TABLE() 	{ 	}  	long*&operator[](long rowIndex) 	{ 		return m_data[rowIndex]; 	} 	void Create(long rowCount, long colCount) 	{ 		m_data = new long*[rowCount]; 		for (long i = 0; i < rowCount; i++) m_data[i] = new long[colCount + 1]; 		for (long i = 0; i < rowCount; i++)for (long j = 0; j <= colCount; j++)m_data[i][j] = m_error; 	} 	void SetAccept(long rowIndex) 	{ 		m_data[rowIndex][m_colCount] = m_accept; 	} 	bool IsAccept(long rowIndex) 	{ 		if (m_data[rowIndex][m_colCount] == m_accept)return true; 		return false; 	} private:  };

user: user-1
content: 新的这个代码我写了一个类来简化二维数组的操作。  //把实际输入的字符映射成编号 long Map(char ch) { 	if (ch >= '0'&&ch <= '9')return 2; 	switch (ch) 	{ 	case '+': 		return 0; 		break; 	case '-': 		return 1; 		break; 	case '.': 		return 3; 		break; 	default: 		//当不是这里的字符集时，返回错误码-1. 		return -1; 		break; 	} } //这个DFA函数对每一个表都是适用的。 //返回匹配了的字符数，形参accLen（重要）返回最长接受的字符数 //函数返回值不一定与accLen相等。 long DFA(char*string, TABLE&table, long*accLen) { 	*accLen = -1; 	long row=0, col, value; 	long sp = 0; 	while (true) 	{ 		if (table.IsAccept(row))*accLen = sp; 		if ((col = Map(string[sp])) == -1)break; 		value = table[row][col]; 		if (value == -1)break; 		sp++; 		row = value;  	}  	return sp; } int _tmain() { 	/* 	EBNF表达式： 	数字=[+|-]整数[.整数] 	整数 = (0 - 9){ 0 - 9 }  	所对应的表： ------------------------------------------------------ 	编号:	0		1		2		3		4 ------------------------------------------------------ 	字符:	+		-		0-9		.		(接受) ------------------------------------------------------ 	0	:	1		1		2 	1	:					2 	2	:					2		3		1 	3	:					4 	4	:					4				1 ------------------------------------------------------ 	*/ 	//初始化table表（上表） 	TABLE table = TABLE(5, 4); 	table.SetAccept(2); 	table.SetAccept(4); 	table[0][0] = 1; table[0][1] = 1; table[0][2] = 2; 	table[1][2] = 2; 	table[2][2] = 2; 	table[2][3] = 3; 	table[3][2] = 4; 	table[4][2] = 4; 	//开始输入字符了。 	char s[100]; 	long sp = 0; 	long doneLen,accLen; 	while (true) 	{ 		if((s[sp] = _getch())=='\x1b')return 0;//按ESC退出 		//这个DFA函数对每一个表都是适用的，你可以把这里声明的table换成其他表。把与之相关的参数改一下就行了。 		doneLen = DFA(s, table, &accLen); 		sp = doneLen; 		s[sp] = NULL; 		printf("%s\n", s); 	} 	 	getchar(); 	return 0; }

user: user-1
content: 引用有更好的算法么？我觉得我的这个算法有点繁琐 简单说一下自动机的要求： 需要： 1.由正则表达式构造出来的表。 2.输入字符串。 下面是我写的，对所有表都适用：  //把实际输入的字符映射成编号 long Map(char ch) { 	if (ch >= '0'&&ch <= '9')return 2; 	switch (ch) 	{ 	case '+': 		return 0; 		break; 	case '-': 		return 1; 		break; 	case '.': 		return 3; 		break; 	default: 		//当不是这里的字符集时，返回错误码-1. 		return -1; 		break; 	} } //这个DFA函数对每一个表都是适用的。 //返回匹配了的字符数，形参accLen（重要）返回最长接受的字符数 //函数返回值不一定与accLen相等。 long DFA(char*string, long**table, long rowCount, long*accLen) { 	*accLen = -1; 	long row=0, col, value; 	long sp = 0; 	while (true) 	{ 		if (table[row][rowCount - 1] == 1)*accLen = sp; 		if ((col = Map(string[sp])) == -1)break; 		value = table[row][col]; 		if (value == -1)break; 		sp++; 		row = value;  	}  	return sp; } int _tmain() { 	/* 	EBNF表达式： 	数字=[+|-]整数[.整数] 	整数 = (0 - 9){ 0 - 9 }  	所对应的表： ------------------------------------------------------ 	编号:	0		1		2		3		4 ------------------------------------------------------ 	字符:	+		-		0-9		.		(接受) ------------------------------------------------------ 	0	:	1		1		2 	1	:					2 	2	:					2		3		1 	3	:					4 	4	:					4				1 ------------------------------------------------------ 	*/ 	//初始化table表（上表） 	long**table = new long*[5]; 	for (long i = 0; i < 5; i++)table[i] = new long[5];  	for (long i = 0; i < 5; i++)for (long j = 0; j < 5; j++)table[i][j] = -1; 	table[0][0] = 1; table[0][1] = 1; table[0][2] = 2; 	table[1][2] = 2; 	table[2][2] = 2; table[2][3] = 3; table[2][4] = 1; 	table[3][2] = 4; 	table[4][2] = 4; table[4][4] = 1; 	//开始输入字符了。 	char s[100]; 	long sp = 0; 	long doneLen,accLen; 	while (true) 	{ 		s[sp] = _getch(); 		//这个DFA函数对每一个表都是适用的，你可以把这里声明的table换成其他表。把与之相关的参数改一下就行了。 		doneLen = DFA(s, table, 5, &accLen); 		sp = doneLen; 		s[sp] = NULL; 		printf("%s\n", s); 	} 	  	getchar(); 	return 0; }

user: user-2
content: 采用有限状态机分享

user: user-3
content: 引用 4 楼 zhao4zhong1 的回复:参考《编译原理》中的词法分析和有限状态自动机。 正解！

user: user-0
content: 引用 5 楼 hhhhhhhhhhkkkkkkkkkk 的回复:还有点错，应该是： 数字=[+-]整数[.整数] 整数=(0-9){0-9} 有更好的算法么？我觉得我的这个算法有点繁琐

user: user-0
content: 引用 4 楼 zhao4zhong1 的回复:参考《编译原理》中的词法分析和有限状态自动机。 有没有更好的算法？？

user: user-1
content: 还有点错，应该是： 数字=[+-]整数[.整数] 整数=(0-9){0-9}

user: user-3
content: 参考《编译原理》中的词法分析和有限状态自动机。

user: user-1
content: 引用数字=[+-]整数[.整数] 整数=(0-9)[0-9] 有点小错，应该是： 数字=[+|-]整数[.整数] 整数=(0-9)[0-9]

user: user-1
content: 引用要求如下：第一个可为‘+’、‘-’、0~9，第二个可为0~9，其余的可为0~9、’.'。。本人写的程序如下 这里的数字设计有问题。照你这样设计，-0.2.3是可以被认为是数字的。 正确的假设应该是： 第一部分可为‘+’、‘-’，第二部分一定为'整数'，第三部分可以为 '.''整数' 整数定义为： 第一部分为0~9，第二部分可以为0~9的重复。写成EBNF表达式就是: 数字=[+-]整数[.整数] 整数=(0-9)[0-9]

user: user-3
content: 在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。