用自动状态变迁图从字符串中取符合双精度常量格式的字符串#C语言
用自动状态变迁图从字符串中取符合双精度常量格式的字符串#C语言
用自动状态变迁图方案从表达式中取出运算数
问题:
从键盘输入一个包含数字字符的字符串,从中取出符合双精度常量格式的数字字符串,并将其转换成数值常量。
问题起因源于:要对一个表达式进行分析,发现可能存在的错误,若无错误,则进行表达式运算;想要解决该问题:首先得解决其中明显的技术性问题:括号匹配和从字符串中取数字字符串并转换成真正的数值常量。括号匹配在上一篇博文中已解决,在该篇中解决如何从字符串中取出符合双精度常量要求的字符串。
思路:
1.双精度常量由 正号、负号、小数点、数值组成。
2.结合实际思考:如 34 3.4 -1.2 .3 3. 0. 都符合双精度常量格式;而 -. +. . 不符合双精度常量格式。
3.双精度常量刚开始可以是:
(1)符号: +,- ;(2)数值 (3)小数点 .
如12.34.5 计算机能够正确取出12.34 和 .5 两个符合双精度格式的数值;但目前所编程序只能取出第一个正确的数值,12.34;
了解了双精度常量格式后,给出一种高级方案:
自动状态变迁图描述双精度常量格式且自动状态变迁图具有两种稳定状态: 开始状态 结束状态;
得到自动状态变迁图如下:
开始状态(即第一个字符)可能有四种可能性: 数值、小数点、符号、错误;若第一个字符为数值则变为状态1,即数值状态;变为状态1后考虑第一个字符后面可以是数值、小数点或结束字符;若第一个字符后面是数值,则考虑数值的后面又可以是:数值、小数点、结束字符;与状态1相同,则若第一个字符后面是数值的话,再次变为状态1。若第一个字符后面是小数点,则考虑小数点后面可以是:数值、结束字符;则状态变为状态4;变为状态4后;若小数点后面是数值,则考虑数值后面可以是:数值、结束字符,与状态4相同,则若小数点后面是数值的话,再次变为状态4.若小数点后面是结束字符,则直接变为结束状态。若第一个字符后面是结束字符,则直接变为结束状态。状态2与状态3同上所述思路一致,如图。
c代码:
#include
#include
#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;
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 {
printf("不能只出现小数点!\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 {
printf("不可识别字符!\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{
printf("出师未捷身先死!\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{
printf("存在错误!\n");
}
}else{
printf("存在错误!\n");
}
return 0;
}
结果:
输入:-3.14+.
输出:-3.140000
不能只出现小数点!
存在错误!
用自动状态变迁图从字符串中取符合双精度常量格式的字符串#C语言相关教程
java学习之路7--桥接模式(自动售货机的改善)
java学习之路7--桥接模式(自动售货机的改善) java7--桥接模式(自动售货机的改善) 功能简介 不用桥接模式实现 使用桥接模式实现 什么是桥接模式 桥接模式使用场景 桥接模式的概念 桥接模式的组成 代码实现 总结 功能简介 java学习之路2–简单工厂模式实现
Springboot的mybatis逆向工程自动生成代码+神坑规避指南(全网最
Springboot的mybatis逆向工程自动生成代码+神坑规避指南(全网最全攻略|附思维导图) 项目版本概况 mybatis-generator-core:1.3.4 mybatis-generator-maven-plugin:1.3.4 mysql-connector-java(项目运行):8.0.22 mysql-connector-java(逆向工程):5.1.
Word2007 表格换页自动“续表”方法
Word2007 表格换页自动“续表”方法 最近对一些word资料进行标准化,排版中的表格需要自动续表,测试了网上各种方法后,总结了最简洁高效的添加续表方法。 步骤1:实现标题行重复,这个用word 2007自带的功能就能实现。先将标题行选中,在表格工具的“布局”
python unittest自动化测试
python unittest自动化测试 1、unittest自动化测试结构 2、加载测试用例,生成测试报告 import unittestimport timeimport HTMLTestRunnerimport osimport sysfrom config import readconfigimport datetime # 当前脚本所在文件真实路径cur_path = os.path.di
java-实现桌面壁纸自动切换(有界面,可还以自己设置时间的那种
java-实现桌面壁纸自动切换(有界面,可还以自己设置时间的那种哦) 前言 界面以及功能实现 本篇文章主要讲java的GUI技术搭建页面和java的时间驱动来监听操作,jsoup分析网页数据,以及用到fastjson来进行json数据交互。 项目结构如下: 效果图: 文章很长,
python自动构建Markdown博客列表
python自动构建Markdown博客列表 python 构建博客列表 这篇博客中我给出了一个python程序代码,用来输出所有博客的标题和url 因为CSDN恶心的限制,一篇文章不能超过64000字,所以我不得不用Markd
RocketMQ--生产者消息返回状态
RocketMQ--生产者消息返回状态 SendStatus package org.apache.rocketmq.client.producer;public enum SendStatus { SEND_OK, //消息已经发送成功 //后面这三种情况,如果业务不允许丢消息,需要做相应的补偿,做可靠性的重投 FLUSH_DISK_TIMEOUT, //消息发送成
iOS自动化环境搭建(超详细)
iOS自动化环境搭建(超详细) libimobiledevice brew install libimobiledevice 使用本机与苹果iOS设备的服务进行通信的库。 ideviceinstaller brew install ideviceinstaller 获取设备udid、安装app、卸载app、获取bundleid carthage brew install carthage