文档章节

从键盘读入实数

陈洪波
 陈洪波
发布于 2015/05/19 19:34
字数 1202
阅读 10
收藏 0

编制一个从键盘读入实数的函数readreal(double *rp)。函数将读入的实数字符列换成实数后,利用指针参数rp,将实数存于指针所指向的变量*rp

解析:
函数在返回之前,将最后读入的结束实数字符列的字符返还给系统,以便随后读字符时能再次读入该字符。函数若能正常读入实数,函数返回整数1,如果函数在读入过程中,未遇到数字符之前,遇到不能构成数字的情况,函数返回-1,表示为读到实数。

在输入实数时,在实数之前可以有一个数不定的空白类字符,组成实数的字符列有数的符号字符,实数的整数部分,小数点和实数的小数部分,其中,某些部分可以缺省。设实数字符列有以下几种可能形式:

数符 整数部分
数符 整数部分
数符 整数部分.小数部分
数符 .小数部分

其中数符或为空,或为’+’,或为’-‘,分别代表不带符号,带正号,带负号。整数部分和小数部分至少要有一个数字符组成。

上述实数形式说明,在实数转换过程中,同一字符在不同情况下会有不同的意义。为标记当前实数转换的不同情况,程序引入状态变量,有状态变量的不同值代表当前实数转换过程中的不同情况。

共有以下多种不同的情况:正准备开始转换,转换了数的符号字符,正在转换实数的整数部分,正在转换实数的小数部分,发现输入错误,转换正常结束。设状态变量为0表示正准备开始转换,还未遇到任何与实数有关的字符;1表示已经遇到数的符号字符;2表示正在转换实数的整数部分,3表示在未遇到数字字符之前先遇到小数点;4表示在转换整数部分之后遇到小数点;5表示转换发现错误,6表示转换正常结束。

读函数另外有两张表,一张是转换函数表,一张是状态表。函数反复读入字符,将字符分类,根据当前状态和当前字符类调用对应转换函数。

下面是程序的实现部分:

#include <stdio.h>
#define ERR 5
#define OK 6

int status;
double result,sig,scale;

/* * 处理数的符号函数 */
int sign(int c){
    if(c = '-') /* 若为负号,取负 */
        sig=-sig;
}

/** * @brief integer 转换整数部分 * @param c 要被转换的整数位 * @return 返回成功与否 */
int integer(int c){
    result = result * 10.0 + c - '0';
}

/** * @brief decimal 转换小数部分 * @param c 要被转换的小数位 * @return 返回成功与否 */
int decimal(int c){
    result += (c -'0') * scale;
    scale /= 10;
}

/* 状态表 */
/* * 0 - 正准备开始转换,还未遇到任何与实数有关的字符 * 1 - 已遇数的符号字符 * 2 - 正在转换实数的整数部分 * 3 - 在未遇数字字符之前先遇到小数点 * 4 - 在转换整数部分之后先遇到小数点 * 5 - 表示转换发现错误 * 6 - 转换正常结束 */
int statbl[][4]={
    {1,2,3,ERR},
    {ERR,2,3,ERR},
    {OK,2,4,OK},
    {ERR,4,ERR,ERR},
    {OK,4,OK,OK}
};

/* 转换函数表 */
int (*funtbl[][4])() = {
    {sign,integer,NULL,NULL},
    {NULL,integer,NULL,NULL},
    {NULL,integer,NULL,NULL},
    {NULL,decimal,NULL,NULL},
    {NULL,decimal,NULL,NULL}
};

/** * @brief readreal 用于对输入的字符串转换成浮点数 * @param dp 转换后的浮点数 * @return 返回是否转换成功 */
int readreal(double *dp){
    int c,ckind;
    sig = 1.0;
    result = 0.0;
    scale = 0.1;

    while((c=getchar()) == ' ' || c == '\n' || c == '\t'); //跳过这些字符

    status = 0; //重置初始状态
    for(;;){
        /* 分类当前字符 */
        if(c == '+' || c== '-') ckind = 0; /* 数的符号字符 */
        else if(c >= '0' && c <= '9') ckind = 1; /* 数字符 */
        else if(c == '.') ckind = 2; /* 小数点 */
        else ckind = 3; /* 其他字符 */

        if(funtbl[status][ckind]){
            (*funtbl[status][ckind])(c); /* 执行相应的转换函数 */
        }

        status = statbl[status][ckind]; /* 设置新的状态 */

        if(status == ERR || status == OK) break; /*结束,出错或成功 */

        c=getchar();
    }

    ungetc(c,stdin); /* 归还数的结束符*/
    if(status == OK){
        *dp = result * sig;
        return 1;
    }

    return -1;
}



int main()
{
    double x;
    printf("Please input real numbers:\n");

    while(readreal(&x) == 1)
        printf("The real number is : %f\n",x);

    return 0;
}

下面是我的程序的运行结果:

这里写图片描述

这个程序刚开始的时候,我的思路是,从第1个元素开始遍历,遍历过程中,在遇到”.”之前,类似于上面integer()函数的实现方式,当遇到点之后,就类似于上面decimal()函数的实现方式,但是看了作者的源码之后,发现需要学习一个做着的思路,思路敏捷,代码整洁,需要好好学习。

本文转载自:http://blog.csdn.net/hongbochen1223/article/details/45805259

陈洪波
粉丝 2
博文 76
码字总数 1552
作品 0
济南
程序员
私信 提问
scanf()函数的用法和实践

scanf()函数的用法和实践 摘要: 本文阐述了基于ANSI,Win 95,Win NT上的 C/C++语言中scanf()函数的用法,以及在实际使用中常见错误及对策。 关键词: scanf() 一、 序言 在CSDN论坛的C/C++...

晨曦之光
2012/03/09
312
0
用R语言做数据分析(7)——数据的输入与输出之Scan函数

前面系列文章,介绍了R语言中的几种数据格式;其它特殊的数据格式将在后续的文章中介绍,接下来的几篇文章,将讨论如何从外部中读入数据或者将其它格式的数据读入到R环境中; scan() 函数 sc...

师弟文
2015/11/30
4.2K
0
C++输入cin详解

输入原理: 程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直...

geek_loser
2016/03/24
29
0
fgets(),fscanf(),fprintf()

功能 从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'0'),如果文件中的该行,不足bufsize个字符,...

月moon
2017/03/09
0
0
c#知识点1.0数据类型

以前就说,要开始写c#的博客,最近把linux大约写完了,现在开始c#了,java的博客简书一大堆,我就避免撞车吧,其实我是菜鸟(嘻嘻,写不出更好的了) 数据类型 c#数据类型主要分为二大类:值...

东风冷雪
2017/11/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
41分钟前
2
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0
轻量级 HTTP(s) 代理 TinyProxy

CentOS 下安装 TinyProxy yum install -y tinyproxy 启动、停止、重启 # 启动service tinyproxy start# 停止service tinyproxy stop# 重启service tinyproxy restart 相关配置 默认...

Anoyi
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部