状态机在程序设计中用处
【问题描述】
合法的实数书写格式分一般格式和科学格式两种。分别描述如下:
一般格式为常见的书写格式,分为整数部分和小数部分两部分,中间分用小数点.分隔。整数部分最开始可能含有正号或负号,之后为不含前导零的数字串;小数部分是由0-9十种字符组成的任意长的字符串。当小数部分为0时,小数部分和小数点可以省略。
科学格式由系数部分和指数部分两部分组成,中间用英文字母E分隔。系数部分为实数书写的一般格式;指数部分为可带有正负号数字串。
例如,+2、-1.56为一般格式的实数,而6.2E-2、-9E8为科学格式的实数。
只有小数点而没有小数部分的书写格式为不合法,例如,23.,23.E16均为不合法的实数书写格式。
编程分析哪些数的书写是正确的,是用哪种方式书写的。
【输入形式】
输入文件为当前目录下的real.in。 该文件包含一个字符串(长度不超过20个字符),以回车符结束,表示一个数据(无多余空格)。
【输出形式】
输出文件为当前目录下的real.out。 该文件有一行。如果输入数据的书写是非法的,输出Wrong;如果输入数据是用一般格式书写的,输出“Format1”;如果该数据是用科学格式书写的,输出“Format2”。输出的末尾均要以一个回车符作为结束。
【输入样例1】
+1.23
【输出样例1】
Format1
【输入样例2】
-5.1.1
【输出样例2】
Wrong
【输入样例3】
-5.1E-2
【输出样例3】
Format2
【时间限制】
1s
【空间限制】
65536KB
解决思路:
判断一个字符串是否符合格式
=>将一个字符串看成是输入流,从左到右的依次检查。
=>也就是说对于一个字符串我们可以将它归结于多种状态.
=>例如,一个正确的字符串有A,B,C,D四种状态。
=>x为从左到右的字符,
for(int i=0;i<strlen(字符串);++i){
x=字符串[i];
}
=>只有字符串处于D状态时才是正确的状态,A为初始状态,B,C为过程状态。
=>当状态处于A时,此时遍历到的x符合要求的字符串格式才能转化到B状态
=>因此可以将算法表示为;
for(int i=0;i<strlen(字符串);++i){
x=字符串[i];
当前状态加上x后,符合要求,保持当前状态或者进入到下一个状态。
否则认定该输入字符串不合法
}
#include<stdio.h>
#include<string.h>
#include<ctype.h>
//format1: <无前导零数字串>.<数字串>
//format2: <无前导零数字串>.<数字串>E<数字串>
typedef enum state{
initial,
posneg,
number1,
point,
number2,
e,
posneg2,
number3,
end
}state;
void input(char buf[]){
FILE* fd = fopen("real.in", "r+");
int i = 0;
fgets(buf, 25, fd);
for (i = 0; i < (int)(strlen(buf)); ++i){
if (buf[i] == '\n' || buf[i] == '\r'){
buf[i] = '\0';
}
}
fclose(fd);
}
int execute(char buf[]){
int i = 0;
state tempstate=initial;
for (i = 0; i < (int)(strlen(buf)); ++i){
if (tempstate == initial){
if (i == 0 && isdigit(buf[0])&&buf[0]!='0'){
tempstate = number1;
}
else if (i == 0 && (buf[0] == '+' || buf[0] == '-')){
tempstate = posneg;
}
else{
break;
}
}
else if (tempstate==posneg){
if (isdigit(buf[i]) && buf[i] != '0'){
tempstate = number1;
}
else{
break;
}
}
else if (tempstate == number1){
if (isdigit(buf[i])){
tempstate = number1;
}
else if (buf[i]=='.'){
tempstate = point;
}
else if (buf[i] == 'E'){
tempstate = e;
}
else{
break;
}
}
else if (tempstate == point){
if (isdigit(buf[i])){
tempstate = number2;
}
else{
break;
}
}
else if (tempstate==number2){
if (isdigit(buf[i])){
tempstate = number2;
}
else if (buf[i]=='E'){
tempstate = e;
}
else{
break;
}
}
else if (tempstate==e){
if (buf[i]=='+'||buf[i]=='-'){
tempstate = posneg2;
}
else if (isdigit(buf[i])&&buf[i]!='0'){
tempstate = number3;
}
else{
break;
}
}
else if (tempstate==posneg2){
if (isdigit(buf[i]) && buf[i] != '0'){
tempstate = number3;
}
else{
break;
}
}
else if (tempstate==number3){
if (isdigit(buf[i])){
tempstate = number3;
}
else{
break;
}
}
}
if (i == (int)(strlen(buf)) && tempstate == number1){
return 0;
}
if (i == (int)(strlen(buf)) && tempstate == number2 ){
return 0;
}
if (i == (int)(strlen(buf)) && tempstate == number3){
return 1;
}
else{
return 2;
}
}
void output(int flag){
FILE* wd = fopen("real.out", "w+");
switch (flag){
case 0:{
fprintf(wd,"Format1\n");
break;
}
case 1:{
fprintf(wd,"Format2\n");
break;
}
case 2:{
fprintf(wd,"Wrong");
break;
}
default:{
printf("wrong");
}
}
}
int main(){
char buf[30];
int flag = 0;
input(buf);
flag=execute(buf);
output(flag);
return 0;
}