K&R exercise 5-1
#include <ctype.h>
#define Size 9
int main()
{
int n,array[Size];
int getint(int*);
for (n = 0; n < Size && getint(&array[n]); n++)//将第n个元素的地址传入getint函数的形参ip
//指针变量ip则存储着第n个元素array[n]的地址。通过其所存储的地址,getint函数就可以把输入的数据
//放入到相应的数组元素中。
//调用完getint函数后,指针形参存储的地址是所得到的整数的地址,然后再将其传回给主调函数。
//这就是间接访问。
printf("index %d :%d\n",n,array[n]);
return 0;
}
int getch(void);
void ungetch(char c);
int getint(int *pn)
{
char c;
while (isspace(c=getch()))//跳过空格符
;
if (!isdigit(c) && c != '+' && c != '-' && c != EOF)//输入的不是一个数字
{
ungetch(c);//压入缓存区中
return 0;
}
if (c == '+' || c == '-')//输入的是'+'后者'-',则继续读取下一个字符
c = getch();
for (*pn = 0; isdigit(c); c = getch())//不断读取,并放入指针pn所指向的内存空间(初始化空间存储的数字为0)
*pn = 10 * *pn + c - '0';//通过计算不断更新该空间内存储的值,直到所读取的字符不为数字为止
if (c != EOF)//多读取的内容放入缓存区中
ungetch(c);
return c;//若之前读取到的是数字,则返回正数;若读取到的是EOF,则直接返回EOF
}
char buf[MaxSize];
int bufp = 0;//缓存区中下一个空闲的位置
int getch(void)//getch函数:当缓存区为空时,从输入中读取一个字符
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(char c)//ungetch:当程序为了确保读取内容的准确性而多读取一个字符时,就会将多读取的字符放入到缓存区中
{
if (bufp > MaxSize - 1)
printf("too many characters\n");
else
buf[bufp++] = c;
}
分析原因:
为什么当符号字符’+’,’-'之后紧跟的不是数字时,getint函数将把符号视为数字0的有效表达式。
因为在读取完符号字符后,接着要读取它后面的字符。不论该字符是否为非数字字符,接下来的程序都会对指针参数pn所指向的内存空间进行写入操作(也就是将数字0放入到该空间中)。为了防止这种情况的发生,不能对pn存储地址的空间进行写入操作。所以在这之前就需要离开getint函数,返回到主调函数中。
if (c == '+' || c == '-')
c = getch();
for (*pn = 0; isdigit(c); c = getch())//不断读取,并放入指针pn所指向的内存空间(初始化空间存储的数字为0)
*pn = 10 * *pn + c - '0';//通过计算不断更新该空间内存储的值,直到所读取的字符不为数字为止
if (c == '+' || c == '-')//输入的是'+'或者'-',则继续读取下一个字符
{
d = c;//先将符号字符保存在变量d中,并继续读取下一个字符
getch();
if (!isdigit(c))//如果所读取的字符不是数字,再判断其是否为文件流结束标志(EOF)
{//如果两者都不是,则将该字符写回输入流中,之后将符号字符也写回输入流中,并返回
//该字符以表示这种情况的出现
//若为EOF标记,则先将符号字符写入输入流
if(c!=EOF)
ungetch(c);
ungetch(d);
return d;
}
}