从输入流中读取整形和浮点型数据存储在实参所指的内存空间中

     源自《The C Programming Language》P83 pr5-2:

    模仿函数getInt 的实现方法,编写一个读取浮点数的函数getFloat,getFloat函数的返回值应该是什么类型呢?

    代码: 

View Code
1 #include <stdio.h>
2 #include <ctype.h>
3
4 int getInt(int *);
5 int getFloat(double *);
6
7 #define SIZE 100
8 #define MAX_FLT 2147483648 //double 8字节,但2^63太大,此处用2^31作为阈值,其实是不太准确的
9 //#defineMAX_FLT2.1474836e+009
10 //当arr_flt定义为float型数组时,if(arr_flt[n] == MAX_FLT)会失效,
11 //而定义为double型数组时,则有效(?),如果如上句那样定义MAX_FLT=
12 //2147483648则不会出现失效这个问题
13 int main()
14 {
15 int i;
16 int n;
17 int arr_int[SIZE];
18 double arr_flt[SIZE];
19 int dim;
20 int reNum;
21
22 //for(n = 0; n < SIZE && ((reNum = getInt(&arr_int[n])) != EOF); ++n)
23 // ;
24 //当getInt返回值是EOF或0或n >= SIZE时,退出循环
25 for(i = 0; i < SIZE; ++i)
26 arr_int[i] = MAX_FLT;
27 //for(n = 0; n < SIZE && ((reNum = getFloat(&arr_flt[n])) != EOF); ++n)
28 //if(arr_flt[n] == MAX_FLT)
29 //continue;//for循环中continue语句是直接跳到++n处执行,如果不想跳转到此处而是直接
30 //跳到条件测试部分,应该用while循环(如下代码)
31 n = 0;
32 while(n < SIZE && ((reNum = getInt(&arr_int[n])) != EOF))
33 {
34 if(arr_int[n] == MAX_FLT)
35 continue;
36 ++n;
37 }
38 dim = n - 1;
39 n = 0;
40 while(dim-- >= 0)
41 printf("%d ", arr_int[n++]);
42 printf("/n");
43
44 return 0;
45 }
46
47
48 int getch();
49 void ungetch(int );
50
51 /***************************************************************************
52 **名称:getInt
53 **功能:从输入流中读取若干字符将他们转化成一个int型数据,存储在实参所指的
54 内存空间中
55 **参数:pNum:指向一个int数据的指针
56 **返回:1:如果从输入流中读取的字符不是EOF,'0' ~ '9','+','-'时,返回0;
57 2:如果从输入流中读取的字符时EOF,则返回EOF(-1);
58 3:如果从输入流中读取的若干连续字符能转化成一个有意义的数字时,
59 返回一个正值;
60 ***************************************************************************/
61 int getInt(int *pNum)
62 {
63 int c;
64 int d;
65 int sign;
66
67 sign = 1;
68 while(isspace(c = getch())) //用库函数isspace更全面,不会发生遗漏情况
69 ;
70 if(!isdigit(c) && c != EOF && c != '+' && c != '-') //当不满足这4种情况时,返回0,下面对这4种情况分别处理
71 {
72 //ungetch(c);
73 //if(!isspace(c))
74 *pNum = c;
75 //else
76 //ungetch(c);
77 return 0;
78 }
79 sign = (c == '-') ? -1 : 1;
80 if(c == '+' || c == '-')
81 {
82 d = c;
83 if(!isdigit(c = getch()))
84 {
85 if(c != EOF)
86 ungetch(c);
87 //ungetch(d);
88 *pNum = d;
89 return d;
90 }
91 }
92 for(*pNum = 0; isdigit(c); c = getch()) //将若干连续数字字符转化成int型值
93 *pNum = 10 * *pNum + (c - '0'); //实参是指针的好处在于能改变其所指向的值
94 *pNum *= sign;
95 if(c != EOF)
96 ungetch(c);
97
98 return c;
99 }
100
101 int getFloat(double *pFlt) //从输入流中获取浮点型数据,不符合要求的字符,全部丢弃
102 {
103 int c;
104 int sign;
105 int pow;
106
107 pow = 1;
108 while(isspace(c = getch()))
109 ;
110 if(!isdigit(c) && c != EOF && c != '+' && c != '-' && c != '.')
111 return 0;
112 sign = (c == '-') ? -1 : 1;
113 if(c == '+' || c == '-')
114 if(!isdigit(c = getch()))
115 return 0;
116 for(*pFlt = 0; isdigit(c); c = getch())
117 *pFlt = 10 * *pFlt + (c - '0');
118 if(c == '.')
119 if(isdigit(c = getch()))
120 {
121 for(; isdigit(c); c = getch())
122 {
123 *pFlt = 10 * *pFlt + (c - '0');
124 pow *= 10;
125 }
126 *pFlt /= pow;
127 *pFlt *= sign;
128 }
129 if(c != EOF)
130 ungetch(c);
131
132 return c;
133 }
134
135 #define BUFSIZE 100 //自定义的输入缓冲区容量
136
137 int buf[BUFSIZE]; //自定义的输入缓冲区
138 int bufp; //指向输入缓冲区的指针
139
140 int getch() //从自定义的输入缓冲区或OS定义的输入缓冲区中读入一个字符
141 {
142 return (bufp != 0) ? buf[--bufp] : getchar();
143 }
144
145 void ungetch(int num) //将一个字符压回到自定义的输入缓冲区中
146 {
147 if(bufp >= BUFSIZE)
148 printf("error: buffer full!");
149 else
150 buf[bufp++] = num;
151 }

     分析:

     疑问:关于MAX_FLT定义:当arr_flt定义为float型数组时,if(arr_flt[n] == MAX_FLT)会失效,

             而定义为double型数组时,则有效,如果如上句那样定义MAX_FLT=2147483648则不会出现失效这个问题?

     易错:关于continue语句用在while循环和for循环中差异:

             for(n = 0; n < SIZE && ((reNum = getFloat(&arr_flt[n])) != EOF); ++n)

                   if(arr_flt[n] == MAX_FLT)

                       continue;

             for循环中continue语句是直接跳到++n处执行,如果不想跳转到此处而是直接跳到条件测试部分,应该用while循环(如下代码)

              n = 0;
              while(n < SIZE && ((reNum = getFloat(&arr_flt[n])) != EOF))
              {
                  if(arr_flt[n] == MAX_FLT)
                        continue;
                  ++n;
              }

     函数分析:getInt:

                    1,  丢弃字符序列头部的空白字符;

                    2,  分四种情况:isdigit(c),c == EOF, c == '+',c == '-'进行处理,

                         当不满足这四种情况时if(!isdigit(c) && c != EOF && c != '+' && c != '-'),说明c是其他字符(不包含空白字符)

                         将c其保存在*pNum中;

                         然后依次按照这四种情况分别进行处理('+', '-'一起处理)。

                    3,  本函数的实参是指向变量的指针,这样可以在函数中改变实参的值,从而达到一个函数返回多个值的目的。

                        

本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。

posted on 2011-06-22 19:40  将军之盾  阅读(365)  评论(0编辑  收藏  举报