由于C语言是以传值的方式将参数值传递给被调用函数,因此,被调用函数不能直接修改主调函数中变量的值。例如,排序函数可能会使用一个名为swap的函数来交换两个次序颠倒的元素。但是,如果将swap函数定义为下列形式:
void swap(int x,int y) /* 错误定义的函数 */
{
int temp;
temp = x;
x=y;
y=temp;
}
则下列语句无法达到该目的。
swap(a,b);
这是因为,由于参数传递采用传值的方式,因此上述的swap函数不会影响到调用它的例程中的参数a和b的值。该函数仅仅交换了a和b的副本的值。
由于一元运算符&用来取变量的地址,这样&a就是一个指向变量a的指针。swap函数的所有参数都声明为指针,并且通过这些指针来间接访问它们指向的操作数。
void swap(int *p,int *py) /* 交换*px和*py */
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
指针参数使得被调用函数能够访问和修改主调函数中对象的值。我们来看这样一个例子,函数getint接受自由格式的输入,并执行转换,将输入的字符流分解成整数,且每次调用得到一个整数。getint需要返回转换后得到的整数,并且,在达到输入结尾时要返回文件结束标记。这些值必须通过不同的方式返回。EOF(文件结束标记)可以用任何值表示,当然也可一个输入的整数表示。
该版本的getline函数在到达文件结尾时返回EOF,当下一个输入不是数字时返回0,当输入中包含一个有意义的数字时返回一个正值。
#include
int grtch(void);
void ungetch(int);
{
int c,sign;
while (isspace (c = getch())) /* 跳过空白符 */
;
if (lisdigit(c) && c != EOF && c != '+' && c != '-'){
ungetch(c); /* 输入不是一个数字 */
return 0;
}
sign = (c == '-') ?-1 : 1;
if (c == '+' || c == '-')
c = getch();
for (*pn = 0;isdigit(c);c = getch())
*pn = 10 * * pn + (c - '0');
*pn *= sign;
if(c !=EOF)
ungetch(c);
return c;
}
在getint函数中,*pn始终作为一个普通的整型变量使用。其中还使用了getch和ungetch两个函数。借助这两个函数,函数getint必须读入的一个多余字符就可以重新写回到输入中。
练习5-1:
#include
#include
int getch(void);
void ungetch(int);
/* getint: get next integer from input into *pn */
int getint(int *pn)
{
int c, d, sign;
while(isspace(c = getch())); /*skip white space */
if(!isdigit(c) && c != EOF && c != '+' && c != '-')
{
ungetch(c); /* it's not a number */
return 0;
}
sign = (c == '-') ? -1 : 1;
if(c == '+' || c == '-')
{
d = c; /* remember sign char */
if(!isdigit(c = getch()))
{
if(c != EOF)
ungetch(c); /* push back non-digit */
ungetch(d); /* push back sign char */
return d; /* return sign char */
}
}
for(*pn = 0; isdigit(c); c = getch())
*pn = 10 * *pn + c - '0';
*pn *= sign;
if(c != EOF)
ungetch(c);
return c;
printf("%d\n",c);
}
练习5-2:
#include
#include
#define SIZE 10
#define BUFSIZE 10
int getch();
void ungetch(int c);
int getfloat(float *pn);
char buffer[BUFSIZE];
int bufp;
int main()
{
int n;
float array[SIZE];
for (n = 0; n < SIZE; array[n++] = 0)
;
for (n = 0; n < SIZE && getfloat(&array[n]) != EOF; n++)
;
for (n = 0; n < SIZE; printf("%.2f ", array[n++]))
;
return 1;
}
int getfloat(float *pn) {
int c, temp, sign;
while (isspace(c = getch()))
;
if (!isdigit(c) && c != EOF && c != '+' && c != '-')
return 0;
sign = (c == '-') ? -1 : 1;
if (c == '+' || c == '-') {
if (!isdigit(temp = getch())) { //如果‘+’,‘-’后面跟的不是数则出错
while (!isdigit(c = getch()) && c != '-' && c != '+' && c != EOF)
; //如果后面跟的不是数的话直接定位到下一个数或者正负号
ungetch(c); //返回刚刚读取的数或符号等到下一次调用getfloat的时候使用
return 0;
}
else
c = temp; //如果'-','+'后面紧跟的是数,则把刚刚因为判断而读取的值赋值给准备开始为数组赋值。c原来的值为'-'或者'+',此时已被赋值给了sign。
}
for (*pn = 0; isdigit(c); c = getch()) {
*pn = 10 * *pn + (c - '0');
}
if (c == '.') {
c = getch();
for (; isdigit(c); c = getch())
*pn += 0.1 * (c - '0');
}
*pn *= sign;
if (c != EOF)
ungetch(c);
return c;
}
int getch()
{
return (bufp > 0) ? buffer[--bufp] : getchar();
}
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("oversized...\n");
else
buffer[bufp++] = c;
return;
}
函数的返回值依然是int类型。