从头学C(33)返回非整型值的函数

0

细心的同学从上一章节的函数定义可以看出来,函数的返回值并非只有 void 或 int 型,所以本章节我们就看下返回非整型值的函数是怎么做的。

第四章 函数与程序结构 >> 4.2 返回非整型值的函数

1. 返回值为 double 的 atof() 函数

来看个 atof(s) 函数,该函数用于把字符串 s 转换为相应的双精度浮点数。(标准库 stdlib.h 中包含了类似功能的 atof() 函数)

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

#define MAXLINE 100

double atof(char []);
int my_getline(char line[], int max);

/* rudimentary calculator */
int main()
{
        double sum;
        char line[MAXLINE];

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

        return 0;
}

/* atof: convert string s to double */
double atof(char s[])
{
        double val, power;
        int i, sign;

        for (i = 0; isspace(s[i]); i++) /* skip white space */
                ;
        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;
        }
        return sign * val / power;
}

/* my_getline: get line into s, return length */
int my_getline(char s[], int lim)
{
        int c, i;

        i = 0;
        while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
                s[i++] = c;
        if (c == '\n')
                s[i++] = c;
        s[i]= '\0';
        return i;
}

显然 atof() 函数的返回值应当是 double 型,因此,我们在程序的开头位置就显式的声明了函数的返回值是 double,且有一个 char [ ] 类型的参数。而在 atof() 函数定义的地方,我们也是与函数声明保持了相同的返回值类型和参数类型。

需要特别说明的是:atof() 函数的声明和定义必须一致。这是因为:

  1. 如果 atof() 函数和调用它的主函数 main() 在同一个源文件中编译,并且声明与定义的类型不一致,则编译器能检测到该错误;
  2. 如果 atof() 函数是单独编译,那这种函数声明与定义不匹配的错误,就无法被检测出来。这种情况下,atof() 返回 double 结果,而 main() 却将返回值当成 int 型处理,最后的结果将毫无意义。

实际编程中,恰恰是第 2 种情况更容易发生……

2. 参数为空的函数声明

如果函数声明中不包含参数,例如:

double atof();

则编译器不会对 atof() 函数的参数做任何假设,同时关闭所有的参数检查。对空参数列表的这种特殊处理是为了使新的编译器能编译比较老的C语言程序。不过在新的C语言程序中,我们提倡的是:如果函数带参数,则要声明它们;如果不带参数,则使用 void 声明。

3. 基于 atof() 的 atoi() 函数

在正确声明的函数 atof 基础上,我们可以利用它快速编写函数 atoi (将字符串转化为 int 类型):

/* atoi: convert string s to integer using atof */
int atoi(char s[])
{
        double atof(char s[]);

        return (int) atof(s);
}

其中 atof(s) 的值在返回前,进行了强制类型转换,转换成了 int 类型(和 atoi 函数的返回值类型一致)。

如果把上面的 return 语句改成:

return atof(s);

那么由于 atoi 函数的返回值类型是 int 型,因此 atof(s) 的返回值 double 类型会被自动转换为 int 类型值,这种操作可能会丢失信息。某些编译器可能会对此给出警告信息。

(然后前者由于显式的进行了类型转换,明确所要进行的转换操作,因此不会出现警告信息)

Leave A Reply