用自动状态变迁图从字符串中取符合双精度常量格式的字符串#C语言

用自动状态变迁图方案从表达式中取出运算数

问题:

从键盘输入一个包含数字字符的字符串,从中取出符合双精度常量格式的数字字符串,并将其转换成数值常量。

问题起因源于:要对一个表达式进行分析,发现可能存在的错误,若无错误,则进行表达式运算;想要解决该问题:首先得解决其中明显的技术性问题:括号匹配和从字符串中取数字字符串并转换成真正的数值常量。括号匹配在上一篇博文中已解决,在该篇中解决如何从字符串中取出符合双精度常量要求的字符串。

思路:

1.双精度常量由 正号、负号、小数点、数值组成。
2.结合实际思考:如 34 3.4 -1.2 .3 3. 0. 都符合双精度常量格式;而 -. +. . 不符合双精度常量格式。
3.双精度常量刚开始可以是:
(1)符号: +,- ;(2)数值 (3)小数点 .
如12.34.5 计算机能够正确取出12.34 和 .5 两个符合双精度格式的数值;但目前所编程序只能取出第一个正确的数值,12.34;

了解了双精度常量格式后,给出一种高级方案:
自动状态变迁图描述双精度常量格式且自动状态变迁图具有两种稳定状态: 开始状态 结束状态;

得到自动状态变迁图如下:在这里插入图片描述

根据自动状态变迁图编写代码如下:

c代码:

#include <stdio.h>
#include <ctype.h>
#include "glrError.h"

#define NUMBER_START_STATUS 1
#define NUMBER_INT_STATUS   2
#define NUMBER_SIGN_STATUS  3
#define NUMBER_DOT_STATUS   4
#define NUMBER_DEC_STATUS   5
#define NUMBER_END_STATUS   6

typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0

typedef struct ARG{
	int index;
	int status;
	boolean ok;
	boolean finished;
	double values;
	int sign;
	double dec;
}ARG;	

extern const char *errMess;

boolean getNumber(const char *str,int *count,double *result);

boolean isSign(int ch);
void dealStartStatus(int ch,ARG *arg);
void dealIntStatus(int ch,ARG *arg);
void dealSignStatus(int ch,ARG *arg);
void dealDotStatus(int ch,ARG *arg);
void dealDecStatus(int ch,ARG *arg);

void processInt(int ch,ARG *arg);
void processSign(int ch,ARG *arg);
void processDot(int ch,ARG *arg);
void processDec(int ch,ARG *arg);

void processDec(int ch,ARG *arg) {
	arg->values += arg->dec * (ch - '0');
	arg->dec/=10.0;
}

void processDot(int ch,ARG *arg) {
	arg->dec = 0.1;
}

void processSign(int ch,ARG *arg) {
	arg->sign = ('-' == ch ? -1 : 1);
}

void processInt(int ch,ARG *arg) {
	arg->values = arg->values*10.0 + (ch - '0');
}

void dealDecStatus(int ch,ARG *arg) {
	if(isdigit(ch)){
    		processDec(ch,arg);
      		arg->status = NUMBER_DEC_STATUS;
       		arg->index++; 
 	}else {
 		arg->status = NUMBER_END_STATUS;
 	}
}

void dealDotStatus(int ch,ARG *arg) {
	if(isdigit(ch)){
  		processDec(ch,arg);
     		arg->status = NUMBER_DEC_STATUS;
     		arg->index++;	
	}else {
	 	errMess = "不能只出现小数点!\n";
	 	arg->ok = FALSE;
	}
}

void dealSignStatus(int ch,ARG *arg) {
	if(isdigit(ch)){
		processInt(ch,arg);
   		arg->status = NUMBER_INT_STATUS;
   		arg->index++;
	}else if('.' == ch){
		processDot(ch,arg);
  		arg->status = NUMBER_DOT_STATUS;
 		arg->index++;
	}else {
		errMess = "不可识别字符!\n";
		arg->ok = FALSE;
	}
}

void dealIntStatus(int ch,ARG *arg) {
	if(isdigit(ch)){
		processInt(ch,arg);
 		arg->status = NUMBER_INT_STATUS;
 		arg->index++;
	}else if('.' == ch){
		processDot(ch,arg);
		arg->status = NUMBER_DEC_STATUS;
		arg->index++;
	}else {
		arg->status = NUMBER_END_STATUS;
	}
}

boolean isSign(int ch) {  
     return '+' == ch || '-' == ch;
}
 

void dealStartStatus(int ch,ARG *arg) {
	if(isdigit(ch)){
		processInt(ch,arg);
		arg->status = NUMBER_INT_STATUS;
		arg->index++;
	}else if(isSign(ch)){
		processSign(ch,arg);
		arg->status = NUMBER_SIGN_STATUS;
		arg->index++;
	}else if('.' == ch){
		processDot(ch,arg);
		arg->status = NUMBER_DOT_STATUS;
		arg->index++;
	}else{
		errMess = "出师未捷身先死!\n";
		arg->ok = FALSE;
	}
}

boolean getNumber(const char *str,int *count,double *result) {	
	ARG arg = {
	0,                         //index
	NUMBER_START_STATUS,       //status
	TRUE,                      //ok
	FALSE,                     //finished
	0.0,                       //values
	1,                         //sign
	0.0,                       //dec
	};
	
	int ch;
	
	while(arg.ok && !arg.finished) {
		ch = str[arg.index];
		if(NUMBER_START_STATUS == arg.status){
			dealStartStatus(ch,&arg);
		}else if(NUMBER_INT_STATUS == arg.status){
			dealIntStatus(ch,&arg);
		}else if(NUMBER_SIGN_STATUS == arg.status){
			dealSignStatus(ch,&arg);
		}else if(NUMBER_DOT_STATUS == arg.status){
			dealDotStatus(ch,&arg);
		}else if(NUMBER_DEC_STATUS == arg.status){
			dealDecStatus(ch,&arg);
		}else if(NUMBER_END_STATUS == arg.status){
		*count += arg.index;
		*result = arg.values * arg.sign;
		arg.finished = TRUE; 
		}
	}
	return arg.ok;
}

int main(){

	char str[80];
	boolean ok;
	int index = 0;
	double values = 0.0;

	printf("Input the str:");
	gets(str);
	
	ok = getNumber(str,&index,&values);
	if(ok) {
	printf("%lf\n",values);
	index++;
	ok = getNumber(str+index,&index,&values);
	if(ok){
	printf("%lf\n",values);
	}else{
		showError();
	}
	}else{
		showError();
	}
	
	return 0;
}			

专门针对错误给出一套错误处理机制,这里需要glrError.h和glrError.c文件支持,代码如下:

glrError.h文件:

#ifndef _GLR_ERROR_H_
#define _GLR_ERROR_H_

void showError();

#endif 

glrError.c文件:

#include <stdio.h>
#include "glrError.h"

const char *errMess = NULL;

void showError(){
	if(NULL == errMess) {
	return;
	}else{
	printf("%s\n",errMess);
	}
}

最后连编得到结果如下:

结果:

输入:-3.14+. 
输出:-3.140000 
      不能只出现小数点!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值