从键盘读入实数

编制一个从键盘读入实数的函数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()函数的实现方式,但是看了作者的源码之后,发现需要学习一个做着的思路,思路敏捷,代码整洁,需要好好学习。

时间: 2024-08-05 07:44:29

从键盘读入实数的相关文章

_02_从键盘读入用户的输入,格式化输出hello+用户输入的信息

Hello.cs文件 using System; //引用了一个叫System的名空间 class easyInput //类的名字与文件名(Hello.cs)不同也 无所谓 { public static void Main() { string strName; //声明一个string类型的值变量 Console.Write("please input your name:"); //输出一句话,但不换行 strName = Console.ReadLine(); //从键盘读入

201671010127 2016-2017-11 从键盘读入中文字符串遇到的问题

上周测试户籍管理系统时,我偶然发现了一个问题,在IDE下运行该程序时,如果输入为中文字符串时会遇到一些问题.下面我就以一个简单的程序来演示该问题: 首先我先写一个从键盘读入一个中文字符串,然后输出该字符串的程序,代码如下: import java.util.Scanner; public class Demo { public static void main(String[] args) { Scanner in=new Scanner(System.in); String t=new Str

(2019.3.15)if语句;从键盘读入3个数;三个数进行大小排序

import java.util.Scanner;class TestIf3{    public static void main(String[] args){        //1.从键盘获取三个数        Scanner s = new Scanner(System.in);        System.out.println("请输入第一个数:");        int num1 = s.nextInt();        System.out.println(&qu

Delphi下利用WinIo模拟鼠标键盘详解

http://www.cnblogs.com/rogee/archive/2010/09/14/1827248.html 本文最早在编程论坛上发表,文章地址:http://programbbs.com/bbs/view12-17207-1.htm,相关文件可以在上述地址的页面中下载.转载时请注明出处. 前言 一日发现SendInput对某程序居然无效,无奈只好开始研究WinIo.上网查了很多资料,发现关于WinIo模拟鼠标键盘的资料很少,有的也只是支言片语讲的不是很详细,而且大部分都是关于模拟键

在java中如何用键盘输入一个数,字符,字符串 (转)

ava不像C中拥有scanf这样功能强大的函数,大多是通过定义输入输出流对象.常用的类有BufferedReader,Scanner.实例程序:一,利用 Scanner 实现从键盘读入integer或float 型数据 Java代码 import java.util.*; public class test { public static void main(String args[]) { Scanner in=new Scanner(System.in); //使用Scanner类定义对象

BufferedReader由键盘输入数据

//使用InputStreamReader及BufferedReader由键盘输入数据 class Ex6_5_1 { public static void main(String[] args) { //1.以InputStreamReader为数据类型 //以键盘System.in为输入设备创建InputStreamReader新对象isr InputStreamReader isr=new InputStreamReader(System.in); //2.以BufferedReader为

C++学习45 流成员函数put输出单个字符 cin输入流详解 get()函数读入一个字符

在程序中一般用cout和插入运算符“<<”实现输出,cout流在内存中有相应的缓冲区.有时用户还有特殊的输出要求,例如只输出一个字符.ostream类除了提供上面介绍过的用于格式控制的成员函数外,还提供了专用于输出单个字符的成员函数put.如:    cout.put('a');调用该函数的结果是在屏幕上显示一个字符a.put函数的参数可以是字符或字符的ASCII代码(也可以是一个整型表达式).如    cout.put(65 + 32);也显示字符a,因为97是字符a的ASCII代码. 可以

关于读入优化的最终分析

关于读入优化的最终分析 摘要 身为一只以卡常为生的蒟蒻,总想着通过一些奇技淫巧来掩饰优化常数. 于是本文章就非正式地从最初的开始到最终的终止来谈谈在OI种各种主流.非主流读入的速度以及利弊. 序言 随着算法的发展各种数据结构等劲题出现,这些题除了思维难度的提高还带来者输入数据的增多(特别的有:uoj.ac上的一道题需要选手自己生成数据,而数论题往往输入较少),对于有追求有理想的选手快速读入是必不可少的技能. 尽管市面上有不同的主流读入优化,但是大多都是基于fread的,其余的只是一些小变动. 而

卡常神器——register 与 快速读入输出

快速读入模板 int read() { int s = 0, w = 1; char ch = getchar(); //getchar() 一次从键盘读入一个字符 while (ch <='0' || ch > '9') { if (ch == '-') w = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); } return