当前位置: 首页 > article >正文

C语言KR圣经笔记 4.2返回非整数的函数

4.2 返回非整数的函数

到目前为止,我们给出的函数样例,不是不返回值(void)就是返回 int。如果函数必须要返回其他类型呢?许多的数值函数如 sqrt,sin 和 cos 返回 double;其他特定的函数返回其他类型的值。为了说明该如何处理这种情况,我们来编写并使用函数 atof(s),它将字符串 s 转换成对应的双精度浮点数。 atof 是 我们在第二章和第三章所展示的 atoi 函数的扩展。它能处理可选的正负号和小数点,以及可能缺失的整数或小数部分。我们即将给出的版本不是一个高质量的输入转换例程,因为我们不想占用更多篇幅。标准库中包含了一个 atof,在头文件 <stdlib.h>中声明。

首先,因为不返回int,故atof 必须声明它的返回值。返回类型放在函数名称的前面:

#include <ctype.h>

/* atof: 将字符串s转换成double */
double atof(char s[])
{
	double val, power;
	int i, sign;
	
	for (i = 0; isspace(s[i]); i++)  /* 跳过空格 */
		;
	sign = s[i] == '-' ? -1 : 1;
	if (s[i] == '+' || s[i] == '-')
		i++;
	for (val = 0.0; isdigit(s[i]); i++)
		val = 10.0 * val + (s[i] - '0');
	if (s[i] == '.')
		i++;
	for (power = 1.0; isdigit(s[i]); i+) {
		val = 10.0 * val + (s[i] - '0');
		power *= 10.0;
	}
	return sign * val / power;
}

其次,但是也同样重要的,调用者必须知道 atof 返回非int值。保证这一点的一种办法是在调用者函数内显式声明 atof。这种方法展示在下面这个简单的计算器中(勉强够用来做账单结算)。计算器每行读取一个可能带符号的数,将它们加起来,并在每次输入后打印当前的和。

#include <stdio.h>

#define MAXLINE 100

/* 简单的计算器 */
main()
{
	double sum, atof(char []);
	char line[MAXLINE];
	int getline(char line[], int max);

	sum = 0;
	while (getline(line, MAXLINE) > 0)
		printf("\t%g\n", sum += atof(line));
	return 0;
}

其中的声明

double sum, atof(char []);

表示sum 是一个double变量,而 atof 是一个函数,它有一个 char[] 参数,并返回double。

函数 atof 的声明和定义必须一致。如果在同一个源文件内, atof 自身定义的类型与 main 调用它时声明的类型不一致,则编译器能检测到这个错误。但如果(更有可能)atof 是分开编译的,无法检测到两者不匹配,atof 返回 double 而 main 将它当作 int,就会得到无意义的结果。

鉴于我们说过声明必须与定义匹配,这个说法可能令人吃惊。导致不匹配发生的原因在于,如果没有函数原型,则该函数第一次在表达式中出现时,它会被隐式声明,比如

sum += atof(line)

如果一个没有被事先声明的名称出现在表达式中,而且名字后面还跟着左括号,则它被根据上下文声明为一个函数名称,该函数被假定返回int,且对其参数不做任何假定。更进一步,如果函数声明没有包括参数,例如

double atof();

此时同样也不会对 atof 的参数做任何假定;所有参数校验都会被关闭。对空参数列表的这种特殊处理,是为了让新编译器能够编译旧的C程序。但新写的程序如果还这么做,会是非常糟糕的。如果函数有参数,就要声明出来;如果没有参数,使用void。

有了正确声明的atof,我们就能用它来写atoi(把字符串转换成int):

/* atoi: 使用atof将字符串s转换成整数 */
int atoi(char s[])
{
	double atof(char s[]);
	return (int) atof(s);
}

注意其中的声明结构和 return 语句。

return 表达式;

在返回发生之前,其中表达式的值会被转换成函数的类型。因此,当出现在这个 return 里面时,atof 的值 ,一个 double,会自动被转换成 int,因为 atoi 函数返回一个 int。然而,这个操作会潜在地丢失信息,因此一些编译器会给出警告。强制类型转换显式地告知编译器,这个操作是有意的,从而抑制了告警。

练习 4-2:扩展 atof,使之能处理科学计数形式

123.45e-6

其中的浮点数后面可以跟着 e 或 E,以及可选的带符号的幂。


http://www.kler.cn/a/154132.html

相关文章:

  • Vue实现响应式导航菜单:桌面端导航栏 + 移动端抽屉式菜单
  • 亿咖通科技应邀出席微软汽车行业智享会,分享ECARX AutoGPT全新实践
  • 【机器学习】聚类算法原理详解
  • SpringSecurity+jwt+captcha登录认证授权总结
  • C语言导航 4.1语法基础
  • Excel单元格中自适应填充多图
  • Mysq8l在Centos上安装后忘记root密码如何重新设置
  • 使用策略模式彻底消除if-else
  • 代币化:2024年的金融浪潮预示着什么?
  • TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
  • Redis部署-主从模式
  • 【Vulnhub 靶场】【CEREAL: 1】【困难】【20210529】
  • 如何查看当前conda可供安装的所有pytorch版本
  • 智慧工地平台源码,支持多端展示:PC端、手机端、平板端,实现数据同步
  • iview弹窗提交问题优化
  • 安卓开发学习---kotlin版---笔记(一)
  • Mongodb使用killCursors停止运行的cursor
  • JOSEF 快速中间继电器 KZJ-4H-L DC220V 导轨安装
  • Jetson Nano部署YOLOv5与Tensorrtx加速
  • 【LittleXi】2023年广东工业大学腾讯杯新生程序设计竞赛
  • JavaWeb | JavaScript基础
  • 视频监控平台EasyCVR多场景应用,AI视频分析技术助力行业升级转型
  • 国内某知名半导体公司:实现虚拟化环境下的文件跨网安全交换
  • 解锁 ElasticJob 云原生实践的难题
  • AWS中使用ECS时ecsTaskExecutionRole缺失
  • Linux:锁定部分重要文件,防止误操作