《C与指针》第七章练习

时间:2023-03-09 08:09:54
《C与指针》第七章练习

本章问题

1.具有空函数体的函数可以作为存根使用,你如何对这类函数进行修改,使其更有用?

answer:Have the stub(存根) print out a message when it is called,perhaps printing the values it was given as arguments.

(存根可以在它被调用的时候打印出相应的信息,可能打印出参数的值)

2.在ANSI C中,函数的原型非必需,请问这个规定是优点还是缺点?

answer:An advantage is that it allows you to be lazy;there is less code to write.The other consequences,such as being able to call functions with the wrong numbers or types of arguments,are all disadvantages.

(一个优点是它允许你偷懒,可以写更少的代码,其他后果比如调用函数时使用错误的数字或参数类型都是缺点)

3.如果在一个函数的声明中它的返回类型为A,但它的函数体内有一条return语句,返回了一个类型为B的表达式,请问,这将导致什么后果?

answer:The value is converted to the type specified by the function,The Standard indicates that this is done the same as if the value had been assigned to a variable of that type.

(这个值将会被函数转换成指定的类型A,标准显示将会把该值指定为返回类型的变量)

4.如果一个函数声明的返回类型为void,但它的函数体中包含一条return语句,返回了一个表达式,请问,这将导致什么后果?

answer:This is not allowed;the compiler should give an error message.

(编译器不会允许编译通过而将会给出一条错误信息)

5.如果一个函数被调用之前,编译器无法看到它的原型,那么当这个函数返回一个不是整型的值时,会发生什么情况?

answer:The value returned is interpreted as if it were an interger.

(这个值将会被理解为整型)

6.如果一个函数被调用之前,编译器无法看到它的原型,如果当这个函数被调用时,实际传递给它的参数与它的形参类型不匹配,会发生什么情况?

answer:The argument values are interpreted as the types of the formal paramenters,not their real types.

(参数的值将会被理解为形参的类型而不是它们实际的类型)

7.下面的函数有没有错误,如果有,错在哪里?

int
find_max(int array[])
{
int i;
int max = array[];
for(i = ; i < ; i += ){
if(array[i] > max)
max = array[i];
}
return max;
}

answer:The function assumes that it will be called with an array of exactly ten elements.If called with a larger array.it ignores the remaining elements,if called with a shorter array ,it accesses values outside of the array.

(这个函数假定被调用的时候数组有十个元素,当被一个更大的数组调用是,将忽略一些元素,当被一个更小的数组调用时,将访问数组之外的元素)

8.递归和while循环之间为什么相似?

answer:There must be some goal at which the recursion(递归) or the iteration(迭代) stops.and each recursive call and each iteration of the loop must make some progress toward this goal.

(它们必须有一些目标使递归和迭代停止运行,每个递归和迭代产生一些过程来接近目标)

9.请解释把函数原型单独放在#include文件中的优点

answer:

a. It is easier to use a #include in several source files than to copy the prototype.

(使用include包含与许多源文件中比福祉原型更容易)

b. There is only one copy of the prototype itself.

(只有一份原型的拷贝)

c. #includeing the prototype in the file that defines the function ensures that they match.

(包括原型在文件中,在定义函数时确保它们匹配)

10.在你的系统中,进入递归形式的菲波那契函数,并在函数的起始出增加一条语句,它增加一个全局整型变量的值。现在编写一个main函数,把这个全局变量设置为0并计算Fibonacci(1).重复这个过程,计算FIbonacci(2)至Fibonacci(10)。在在每个计算过程中分别调用了几次Fibonacci函数?这个全局变量值的增加和菲波那契数列本身有没有任何关联?基于上面这些信息,你能不能计算出Fibonacci(11)、Fibonacci(25)、Fibonacci(50)分别调用了多少次Fibonacci函数?

answer:

//参考程序,不含有检错操作
#include <stdio.h> int Fibonacci(int n);
static int count; int main()
{
count = ;
int x;
printf("please input the x:\n");
scanf("%d",&x);
Fibonacci(x);
printf("the count is %d",count);
return ;
} int Fibonacci(int n)
{
count++;
if(n == )
return ;
else if(n == )
return ;
else
return Fibonacci(n - ) + Fibonacci(n - );
}

The progression is indeed related to the Fibonacci numbers:each count is the sum of the two preceding counts plus one.Here are the values requested.plus some additional counts to show how bad the recursive function really is.

(这个过程确实跟fibonacci数字有关系,每一个计数加一是前两项的总和,下面是测试的结果,count显示使用递归计算fibonacci数列有多糟糕)

Fibonacci(n) Number of Calls
1 1
2 1
3 3
4 5
5 9
6 15
7 25
8 41
9 67
10 109
11 177
15 1219
20 13529
25 150049
30 1664079
40 204668309
50 25172538049
75 4222970155956099
100 708449696358523830149

本章练习

1.Hermite Polynominal(厄米多项式)是这样定义的

  n ≤ 0 :   1

Hn(x) =     n = 1 :  2x

      n ≥ 2 :  2xHn-1(x) - 2(n - 1) Hn-2(x)

例如,H3(2)的值是40,请编写一个递归函数,计算Hn(x)的值,你的函数应该与下面的原型匹配:

int hermite( int n, int x)

answer:

#include <stdio.h>

int hermite(int n, int x);

int main(void)
{
int n;
int x;
printf("please input n and x:\n");
scanf("%d%d",&n,&x);
printf("the Hn(x) is: %d",hermite(n,x));
} int hermite(int n, int x)
{
if(n <= )
return ;
else if(n == )
return * x;
else
return * x * hermite(n - ,x) - * (n - ) * hermite(n - ,x);
}

2.两个整型值M和N(M、N均大于0)的最大公约数可以按照下面的方法计算:

       M % N = 0  :   N

gcd(M,N)   =

       M % N = R, R > 0 :     gcd(N,R)

answer:

//迭代法
int gcd(int m, int n)
{
int r;
if(m <= || n <= )
return ;
do{
r = m % n;
m = n;
n = r;
}while(r > ); return m;
} //递归法
int gcd(int m, int n)
{
int r;
if(m <= || n <= )
return ;
r = m % n;
if(r == )
return n;
else if(r > )
return gcd(n,r);
}

3.为下面这个函数原型编写函数定义:

int ascii_to_integer(char *string);

这个字符串参数必须包含一个或多个数字,函数应该把这些数字字符转换为整数并返回这个整数,如果字符串参数包含了任何非数字字符,函数就返回零。请不必担心算数溢出。提示:这个技巧很简单,你每发现一个数字,把当前值乘以10,并把这个值和新数字所代表的值相加。

answer:

int ascii_to_integer(char *string)
{
int result = ;
char *p = string;
while(*p >= '' && *p <= ''){
result *= ;
result += *p - '';
p++;
} if(*p != '\0')
result = ;
return result;
}

4.编写一个名叫max_list的函数,它用于检查任意数目的整型参数并返回它们中最大值。参数列表必须以一个负数结尾,提示列表结束。

answer:

int max_list(int x,...){
int max = x;
va_list var_list;
va_start(var_list,x);
do{
int temp = va_arg(var_list,int);
if(temp > max)
max = temp;
}while(temp > );
   va_end(var_list);
return max;
}

5.实现一个简化的printf函数,它能够处理%d,%f,%s和%c格式码,根据ANSI标准的原则,其他格式码的行为是未定义的,你可以假定已经存在函数print_integer和print_float,用于打印这些类型的值,对于另外两种类型的值,使用putchar来打印。

answer:

void myprintf(char *string,...)
{
char *p = string;
va_list var_list;
va_start(var_list,string); while(*p != '\0'){
if(*p == '%'){
switch(*++p){
case 'd':
print_integer(va_arg(var_list,int));
break;
case 'f':
print_float(va_arg(var_list,float));
break;
case 'c':
putchar(va_arg(var_list,int));
case 's':
char *q = va_arg(var_list,char *);
while(*q != '\0')
putchar(*q++);
break;
default:
break;
}
}else{
putchar(*p);
}
p++;
}
va_end(var_list);
}

6.编写函数:

void written_amount(unsigned int amount,char *buffer);
它把amount表示的值转化为单词形式,并存储于buffer中,这个函数可以在一个打印支票的程序中使用。例如,如果amount的值是16312,那么buffer中存储的字符串应该是:SIXTEEN THOUSAND THREE HUNDRED TWELVE

调用程序应该保证buffer缓冲区的空间足够大。

有些值可以用两种不同的方法进行打印。例如,1200可以是ONE THOUSAND TWO HUNDRED或TWELVE HUNDRED。你可以选择一种你喜欢的形式。

answer:

#include <stdio.h>
#include <string.h> #define LONG 1000 char *unit[] = {" zero"," one"," two"," three",
" four"," five"," six"," seven",
" eight"," nine"}; char *ten[] = {" ten"," eleven"," twelve",
" thirteen"," fourteen"," fifteen",
" sixteen"," seventeen"," eighteen",
" nineteen"}; char *decade[] = {" "," "," twenty"," thirty",
" forty"," fifty"," sixty",
" seventy"," eighty"," ninety"}; void written_amount(unsigned long int amount,char *buffer); int main()
{
unsigned long int amount;
char buffer[LONG] = "";
scanf("%lu",&amount);
written_amount(amount,buffer);
printf("%s",buffer);
return ;
} void written_amount(unsigned long int amount,char *buffer)
{
unsigned long int n = ;
if(amount / n != ){
int temp = amount / n;
amount %= n;
written_amount(temp,buffer);
strcat(buffer," billion");
} n = ;
if(amount / n != ){
int temp = amount / n;
amount %= n;
written_amount(temp,buffer);
strcat(buffer," million");
} n = ;
if(amount / n != ){
int temp = amount / n;
amount %= n;
written_amount(temp,buffer);
strcat(buffer," hundred");
} n = ;
if(amount / n != ){
int temp = amount / n;
amount %= n;
if(temp == ){
strcat(buffer,ten[amount]);
}else{
strcat(buffer,decade[temp]);
if(amount != )
strcat(buffer,unit[amount]);
}
}else{
strcat(buffer,unit[amount]);
}
}