《c and pointer》第7章問題與練習整理
#問題 1.具有空函式體的函式可以作為存根使用,你如何對這類函式進行修改,使其更有用? Have the stub(存根) print out a message when it is called,perhaps printing the values it was given as arguments. 當存根函式被呼叫時,列印一條資訊,或者列印作為引數傳遞給它的值
2.在ANSI C中,函式的原型非必需,請問這個規定是優點還是缺點? 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的表示式,請問,這將導致什麼後果? 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. 該值將轉換為函式指定的型別。 標準表明這與將值分配給該型別的變數的方式相同。
4.如果一個函式宣告的返回型別為void,但它的函式體中包含一條return語句,返回了一個表示式,請問,這將導致什麼後果? This is not allowed; the compiler should give an error message. 這是不允許的; 編譯器應該給出錯誤訊息。
5.如果一個函式被呼叫之前,編譯器無法看到它的原型,那麼當這個函式返回一個不是整型的值時,會發生什麼情況? The value returned is interpreted(解釋)as if it were an integer. 返回的值被解釋為它是一個整數。
6.如果一個函式被呼叫之前,編譯器無法看到它的原型,如果當這個函式被呼叫時,實際傳遞給它的引數與它的形參型別不匹配,會發生什麼情況? The argument values are interpreted(解釋) as the types of the formal parameters(形參), not their real types. 引數值被解釋為形式引數的型別,而不是它們的真實型別。
7.下面的函式有沒有錯誤,如果有,錯在哪裡?
int find_max(int array[10])
{
int i;
int max = array[0];
for(i = 1; i < 10; i += 1){
if(array[i] > max)
max = array[i];
}
return max;
}
這個函式假定當它被呼叫時傳遞給它的正好是10個元素的陣列。如果引數陣列更大一些,它就會忽略剩餘的元素。如果傳遞一個不足10個元素的陣列,函式將訪問陣列邊界之外的值。
8.遞迴和while迴圈之間是如何相似的? 遞迴和迭代都必須設定一些目標,當達到這些目標時便終止執行。每個遞迴呼叫和迴圈的每次迭代必須取得一些進展,進一步靠近這些目標。
9.請解釋把函式原型單獨放在#include檔案中的優點 1.在幾個原始檔中使用#include比複製原型更容易 2.原型本身只有一個副本 3.#include原型在定義函式的檔案中確保它們匹配
10.在你的系統中,進入遞迴形式的菲波那契函式,並在函式的起始出增加一條語句,它增加一個全域性整型變數的值。現在編寫一個main函式,把這個全域性變數設定為0並計算Fibonacci(1).重複這個過程,計算FIbonacci(2)至Fibonacci(10)。在每個計算過程中分別呼叫了幾次Fibonacci函式?這個全域性變數值的增加和菲波那契數列本身有沒有任何關聯?基於上面這些資訊,你能不能計算出Fibonacci(11)、Fibonacci(25)、Fibonacci(50)分別呼叫了多少次Fibonacci函式? 進展確實與斐波納契數相關:每個計數是前兩個計數加1的總和。下面是測試的結果,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)
VC6.0環境
#include "stdafx.h"
int hermite(int n,int x);
int main(int argc, char* argv[])
{
printf("Hn(x) = %d\n",hermite(3,2));
return 0;
}
int hermite(int n,int x)
{
if(n <= 0)
return 1;
if(n == 1)
return 2*x;
if(n >= 2)
{
return 2*x*hermite(n-1,x) - 2*(n-1)*hermite(n-2,x);
}
return false;
}
2.兩個整型值M和N(M、N均大於0)的最大公約數可以按照下面的方法計算: M % N = 0 : N gcd(M,N) = M % N = R, R > 0 : gcd(N,R) 請編寫一個名叫gcd的函式,接受兩個整數引數,並返回這 兩個數的最大公約數。如果這兩個引數中的任何一個不大於 零,函式應該返回零。 VC6.0環境
#include "stdafx.h"
int gcd(int M,int N);
int main(int argc, char* argv[])
{
printf(" greatest common divisor= %d\n",gcd(12,5));
return 0;
}
/*
** Return the greatest common divisor of the arguments m and n (recursively).
*/
int gcd(int M,int N)
{
int R = 0;
if( M <= 0 || N <= 0 )
return 0;
R = M % N;
return R > 0 ? gcd( N , R ) : N;
}
3.為下面這個函式原型編寫函式定義: int ascii_to_integer(char *string); 這個字串引數必須包含一個或多個數字,函式應該把這些數字字元轉換為整數並返回這個整數,如果字串引數包含了任何非數字字元,函式就返回零。請不必擔心算數溢位。提示:這個技巧很簡單,你每發現一個數字,把當前值乘以10,並把這個值和新數字所代表的值相加.
VC6.0環境
#include "stdafx.h"
char *str = "1234567890";
int ascii_to_integer(char *string);
int main(int argc, char* argv[])
{
printf(" ascii to integer result = %d\n",ascii_to_integer(str));
return 0;
}
int ascii_to_integer(char *string)
{
int value = 0;
/*逐個把字串的字元轉換為數字*/
while( *string >= '0' && *string <= '9')
{
value *= 10;
value += *string - '0';
string++;
}
/*錯誤檢查:如果由於遇到一個非數字字元而終止,把結果設定為0*/
if( *string != '\0')
value = 0;
return value;
}
4.編寫一個名叫max_list的函式,它用於檢查任意數目的整型引數並返回它們中最大值。引數列表必須以一個負數結尾,提示列表結束。
VC6.0環境
#include "stdafx.h"
#include <stdarg.h>
int max_list( int first_arg, ... );
int main(int argc, char* argv[])
{
printf(" max_list result = %d\n",max_list(1,2,3,4,5,-1));
return 0;
}
/*
** Return the largest value from the argument list. The list is terminated by a
** negative value.
*/
int max_list( int first_arg, ... )
{
va_list var_arg;
int max = 0;
/*
** Get the first arg if there is one and save it as the max.
*/
if( first_arg >= 0 )
{
int this_arg;
max = first_arg;
/*
** Get the remaining arguments and save each one if it is
** greater than the current max.
*/
va_start( var_arg, first_arg );
/*va_arg( var_arg, int )每呼叫一次返回當前引數的值,並使var_arg指向下一個可變引數*/
while( ( this_arg = va_arg( var_arg, int ) ) >= 0 )
if( this_arg > max )
max = this_arg;
va_end( var_arg );
}
return max;
}
5.實現一個簡化的printf函式,它能夠處理%d,%f,%s和%c格式碼,根據ANSI標準的原則,其他格式碼的行為是未定義的,你可以假定已經存在函式print_integer和print_float,用於列印這些型別的值,對於另外兩種型別的值,使用putchar來列印。
/*
** Bare–bones printf function: handles the %d, %f, %s, and %c format codes.
*/
void printf( char *format, ... )
{
va_list arg;
char ch;
char *str;
va_start( arg, format );
/*
** Get the format characters one by one.
*/
while( ( ch = *format++ ) != ’\0’ )
{
if( ch != ’%’ )
{
/*
** Not a format code –– print the character verbatim.
*/
putchar( ch );
continue;
}
/*
** We got a % –– now get the format code and use it to format
** the next argument.
*/
switch( *format != ’\0’ ? *format++ : ’\0’ )
{
case ’d’:
print_integer( va_arg( arg, int ) );
break;
case ’f’:
print_float( va_arg( arg, float ) );
break;
case ’c’:
putchar( va_arg( arg, int ) );
break;
case ’s’:
str = va_arg( arg, char * );
while( *str != ’\0’ )
putchar( *str++ );
break;
default:
break;
}
}
va_end( var_arg );
}
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。你可以選擇一種你喜歡的形式。
VC6.0環境
#include "stdafx.h"
#include <string.h>
char buffer[20];
void written_amount(unsigned int amount,char *buffer);
/*
** Convert a numeric value to words.(digits數字 magnitudes大小)
**陣列下標和數字對應digits[0] = "",digits[1] = "ONE",digits[2] = "TWO" ......
*/
static char *digits[] =
{
"", "ONE ", "TWO ", "THREE ", "FOUR ", "FIVE ", "SIX ", "SEVEN ",
"EIGHT ", "NINE ", "TEN ", "ELEVEN ", "TWELVE ", "THIRTEEN ",
"FOURTEEN ", "FIFTEEN ", "SIXTEEN ", "SEVENTEEN ", "EIGHTEEN ",
"NINETEEN "
};
/*陣列下標和數字表示的含義對應tens[2] = "TWENTY" tens[3] = "THIRTY"......*/
static char *tens[] =
{
"", "", "TWENTY ", "THIRTY ", "FORTY ", "FIFTY ", "SIXTY ", "SEVENTY ",
"EIGHTY ", "NINETY "
};
static char *magnitudes[] =
{
"", "THOUSAND ", "MILLION ", "BILLION "
};
/*
** Convert the last 3–digit group of amount to words. Amount is the value
** to be converted, buffer is where to put the words, and magnitude is the
** name of the 3–digit group we’re working on.
*/
static void do_one_group( unsigned int amount, char *buffer, char **magnitude )
{
int value;
/*
** Get all the digits beyond the last three. If we have any value
** there, process those digits first. Note that they are in the next
** magnitude.
*/
value = amount / 1000;
if( value > 0 )
do_one_group( value, buffer, magnitude + 1 );
/*
** Now process this group of digits. Any hundreds?
*/
amount %= 1000;
value = amount / 100;
if( value > 0 )
{
strcat( buffer, digits[ value ] );
strcat( buffer, "HUNDRED " );
}
/*
** Now do the rest of the value. If less than 20, treat it as a single
** digit to get the teens names.
*/
value = amount % 100;
if( value >= 20 )
{
/*
** Greater than 20. Do a tens name and leave the units to be
** printed next.
*/
strcat( buffer, tens[ value / 10 ] );
value %= 10;
}
if( value > 0 )
strcat( buffer, digits[ value ] );
/*
** If we had any value in this group at all, print the magnitude.
*/
if( amount > 0 )
strcat( buffer, *magnitude );
}
int main(int argc, char* argv[])
{
written_amount(123456789,buffer);
return 0;
}
void written_amount( unsigned int amount, char *buffer )
{
if( amount == 0 )
/*
** Special case for zero.
*/
strcpy( buffer, "ZERO" );
else
{
/*
** Store an empty string in the buffer, then begin.
*/
*buffer = '\0';
do_one_group( amount, buffer, magnitudes );
}
}