c++面向對象程序設計 譚浩強 答案 第一章
目錄:
第1章 C++ 的初步知識
1.請根據你的了解,敘述C++ 的特點。C++ 對C有哪些發展?
【解】 略。
2.一個C++的程序是由哪幾部分構成的?其中的每一部分起什么作用?
【解】 略。
3.從拿到一個任務到得到最終結果,一般要經過幾個步驟?
【解】 略。
4.請說明編輯、編譯、連接的作用。在編譯后得到的目標文件為什么不能直接運行?
【解】 編譯是以源程序文件為單位進行的,而一個完整的程序可能包含若干個程序文件,在分別對它們編譯之后,得到若干個目標文件(后綴一般為.obj),然后要將它們連接為一個整體。此外,還需要與編譯系統提供的標准庫相連接,才能生成一個可執行文件(后綴為.exe)。不能直接運行后綴為.obj的目標文件,只能運行后綴為.exe的可執行文件。
譚浩強 c++面向對象程序設計 課后答案
5.分析下面程序運行的結果。
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 cout << "This" << "is"; 6 cout << "a" << "C++"; 7 cout << "program." << endl; 8 return 0; 9 }
【解】 輸出的結果為
ThisisaC++program.
譚浩強
6.分析下面程序運行的結果。
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int a, b, c; 6 a = 10; 7 b = 23; 8 c = a + b; 9 cout << "a+b="; 10 cout << c; 11 cout << endl; 12 return 0; 13 }
【解】 前兩個cout語句在輸出數據后不換行,第3個cout語句輸出一個換行,因此輸出的結果為
a+b=33
7.分析下面程序運行的結果。請先閱讀程序寫出程序運行時應輸出的結果,然后上機運行程序,驗證自己分析的結果是否正確。以下各題同。
#include <iostream> using namespace std; int main( ) { int a,b,c; int f(int x,int y,int z); cin>>a>>b>>c; c=f(a,b,c); cout<<c<<endl; return 0; } int f(int x,int y,int z) { int m; if (x<y) m=x; else m=y; if (z<m) m=z; return(m); }
c++面向對象程序設計
【解】 程序的作用是:輸入3個整數,然后輸出其中值最小的數。在主函數中輸入3個整數,然后調用f函數,在f函數中實現找最小的整數,用if語句比較兩個數,將小者存放在變量m中,經過兩個if語句的比較,m中存放的是3個整數中最小的數。運行情況如下:
1 5 3↙ (輸入3個整數)
1 (輸出其中最小的數)
8.在你所用的C++系統上,輸入以下程序,進行編譯,觀察編譯情況,如果有錯誤,請修改程序,再進行編譯,直到沒有錯誤,然后進行連接和運行,分析運行結果。
int main( );
{
int a,b;
c=a+b;
cout >>" a+b=" >> a+b;
}
【解】 上機編譯出錯,編譯出錯信息告知在第2行出錯,經檢查,發現第1行的末尾多了一個分號,編譯系統無法理解第2行的花括號,導致報告第2行出錯。將第1行的末尾的分號去掉,重新編譯,編譯出錯信息告知在第5行和第6行出錯。第5行出錯原因是cout未經聲明,因為cout不是C++語言提供的系統的關鍵字,而是輸出流的對象,必須使用頭文件iostream。第6行出錯原因是main是int型函數,應返回一個整型值。將程序改為
#include <iostream>
int main( )
{
int a,b;
c=a+b;
cout >>" a+b=" >> a+b;
return 0;
}
重新編譯。編譯出錯信息告知在第5行和第6行出錯。第5行出錯原因是變量c未定義,第6行出錯原因是cout未經聲明,說明#include <iostream>命令行未能起作用,原因是未指明命名空間。將程序改為
#include <iostream>
using namespace std;
int main( )
{
int a,b,c;
c=a+b;
cout>>" a+b=" >>a+b;
return 0;
}
重新編譯。編譯出錯信息告知在第7行出錯,經檢查,是“>>”用得不當,“>>”是提取運算符,應與cin聯合使用,用來從輸入流中提取數據,輸出時應該用插入運算符“<<”。把兩處“>>”都改為“<<”,再重新編譯,發現沒有error錯誤,但有兩個警告(warning),原因是定義了a和b,但未對它們賦值。應增加賦值語句或輸入語句,使a和b獲得值,將程序改為
#include <iostream>
using namespace std;
int main( )
{
int a,b,c;
cin>>a>>b;
c=a+b;
cout>>" a+b=" >>a+b;
return 0;
}
重新編譯,沒有編譯錯誤,能通過編譯和連接,可以正常運行,在Visual C++ 6.0環境下運行時屏幕顯示如下:
5 9↙
a+b=14Press any key to continue
顯然這樣的輸出不理想,“Press any key to continue”是Visual C++系統在輸出了運行結果后自動顯示的一個信息,告訴用戶“如果想繼續工作,請按任何一個鍵”。當用戶按任何一個鍵后,顯示運行結果的窗口消失,屏幕顯示回到Visual C++的主窗口,顯示出源程序和編譯信息。
為了解決以上輸出不理想的情況,可以在最后一個輸出語句中增加輸出一個換行符。最后的程序如下:
#include <iostream>
using namespace std;
int main( )
{
int a,b,c;
cin>>a>>b;
c=a+b;
cout<<"a+b="<<a+b<<endl;
return 0;
}
運行時屏幕顯示如下:
5 9↙
a+b=14
Press any key to continue
這就完成了程序的調試。
這里對本題的調試過程作了比較詳細的分析,以便使讀者對如何調試程序有比較具體而清晰的了解。需要說明:
(1)編譯系統給出的編譯出錯信息,只是提示性的,引導用戶去檢查錯誤,用戶必須根據程序的上下文和編譯出錯信息,全面考慮,找出真正出錯之處。例如編譯出錯信息通知第2行出錯,其實可能是第1行出錯。
(2)有時,有的錯誤開始時未被檢查出來並告知用戶(例如未定義變量c),由於其他錯誤未解決,掩蓋了這個錯誤。當解決了其他錯誤后,這個錯誤會被檢查出來。有時在調試過程中會不斷檢查出新的錯誤,這是不奇怪的。一一處理,問題會迎刃而解。
(3)為了說明調試過程,這里全部依靠計算機系統來檢查錯誤,其實有些明顯的錯誤,完全可以由人工查出,這樣可以提高調試效率。由人工在紙面或屏幕上檢查錯誤,稱為靜態查錯,用計算機編譯系統檢查錯誤,稱為動態查錯。建議盡量先用靜態查錯的方法排除錯誤,只有人工檢查不出來的錯誤才讓計算機檢查。
9.輸入以下程序,進行編譯,觀察編譯情況,如果有錯誤,請修改程序,再進行編譯,直到沒有錯誤,然后進行連接和運行,分析運行結果。
#include <iostream>
using namespace std;
int main( )
{
int a,b;
c=add(a,b)
cout<<"a+b="<<c<<endl;
return 0;
}
int add(int x,int y);
{
z=x+y;
retrun(z);
}
【解】 發現7個錯誤:
(1)對add函數未聲明就調用,應在main函數中對add函數進行聲明。
(2)定義add函數時,函數首行末尾不應有分號。
(3)變量c未經定義。
(4)add函數中的變量z未經定義。
(5)第6行末尾少了一個分號。
(6)add函數中的retrun拼寫錯誤,應為return。編譯系統把retrun作為未聲明的標識符而報錯,因為retrun(z)會被認為是函數調用的形式。
(7)變量a和b未被賦值。
改正后的程序如下:
#include <iostream>
using namespace std;
int main( )
{int add(int x,int y);
int a,b,c;
cin >> a >> b;
c=add(a,b);
cout <<" a+b=" << c <<endl;
return 0;
}
int add(int x,int y)
{int z;
z=x+y;
return(z);
}
運行情況如下:
5 8↙
13
10.輸入以下程序,編譯並運行,分析運行結果。
#include <iostream>
using namespace std;
int main( )
{ void sort(int x,int y,int z);
int x,y,z;
cin >> x >> y >> z;
sort(x,y,z);
return 0;
}
void sort(int x, int y, int z)
{
int temp;
if (x>y) {temp=x;x=y;y=temp;} //{ }內3個語句的作用是將x和y的值互換
if (z<x) cout << z << ',' << x << ',' << y << endl;
else if (z<y) cout << x <<',' << z << ',' << y << endl;
else cout << x << ',' << y << ',' << z << endl;
}
請分析此程序的作用。sort函數中的if語句是一個嵌套的if語句。
運行時先后輸入以下幾組數據,觀察並分析運行結果。
① 3 6 10↙
② 6 3 10↙
③ 10 6 3↙
④ 10,6,3↙
【解】 程序的作用是對輸入的3個整數按由小到大的順序進行排序。sort函數中的第1個if語句的作用是先將x和y排序,使x小於或等於y。第2個if語句是一個嵌套的if語句,先比較z和x,如果z<x,顯然由小到大的順序應當是z,x,y,按此順序輸出;如果z不小於x,而小於y,顯然由小到大的順序應當是x,z,y,按此順序輸出;如果z既不小於x,又不小於y,顯然由小到大的順序應當是x,y,z,按此順序輸出。
按題目要求分別輸入以下幾組數據,運行結果如下:
① 3 6 10↙
3,6,10
② 6 3 10↙
3,6,10
③ 10 6 3↙
3,6,10
④ 10,6,3↙
-858993460,-858993460,10
以上是在Visual C++ 6.0環境下運行的情況,前3次運行正常,表明當輸入不同的數據時,程序能實現由小到大的排序功能。第4次運行的結果顯然不正常,這是由於輸入數據時出了問題,本來要求在輸入數據時,數據之間以空格或換行相隔,而現在卻以逗號相隔,只有第一個整數能正常賦給變量x,第二和第三個數據均無法正常賦給變量y和z,y和z的值來自輸入流中相應字節的內容。
11.求2個或3個正整數中的最大數,用帶有默認參數的函數實現。
【解】 可以編寫出以下程序:
#include <iostream>
using namespace std;
int main( )
{int max(int a,int b,int c=0);
int a,b,c;
cin >> a >> b >> c;
cout << " max(a,b,c)= " << max(a,b,c) << endl;
cout << " max(a,b)= " <<max(a,b) << endl;
return 0;
}
int max(int a,int b,int c)
{if(b>a) a=b;
if(c>a) a=c;
return a;
}
運行情況如下:
13 5 76↙
max(a,b,c)=76 (從3個數中找最大者)
max(a,b)=13 (從前2個數中找最大者)
如果想從3個數中找大者,可以在調用時寫成“max(a,b,c)”形式,如果只想從2個數中找大者,則在調用時寫成“max(a,b)”形式,此時c自動取默認值0,由於0比任何正整數都小,因此從14,5,0中選最大者和從14,5中選大者的結果是一樣的。
12.輸入兩個整數,將它們按由大到小的順序輸出。要求使用變量的引用。
【解】 可以編寫出以下程序:
#include<iostream>
using namespace std;
int main( )
{ void change(int &,int &);
int a,b;
cin>>a>>b;
if(a<b) change(a,b); //如果a<b,使a和b的值互換
cout<<"max="<<a<<" min="<<b<<endl;
return 0;
}
void change(int &r1,int &r2) //函數的作用是使r1與r2互換
{ int temp;
temp=r1;
r1=r2;
r2=temp;
}
運行情況如下:
12 67↙
max=67 min=12
13.對3個變量按由小到大順序排序,要求使用變量的引用。
【解】 可以編寫出以下程序:
#include <iostream>
using namespace std;
int main( )
{void sort(int &,int &,int &);
int a,b,c,a1,b1,c1;
cout<<" Please enter 3 integers:";
cin>>a>>b>>c;
a1=a;b1=b;c1=c;
sort(a1,b1,c1);
cout<<a<<" "<<b<<" "<<c<<" in sorted order is ";
cout<<a1<<" "<<b1<<" "<<c1<<endl;
return 0;
}
void sort(int &i,int &j,int &k)
{ void change(int &,int &);
if (i>j) change(i, j);
if (i>k) change(i, k);
if (j>k) change(j, k);
}
void change(int &x,int &y)
{ int temp;
temp=x;
x=y;
y=temp;
}
運行情況如下:
Please enter 3 integers:23 67 -55↙
23 67 –55 in sorted order is –55 23 67
這個程序很容易理解,不易出錯。由於在調用sort函數時虛實結合使形參i,j,k成為實參a1,b1,c1的引用(別名),因此通過調用函數sort(a1,b1,c1)既實現了對i,j,k排序,也就同時實現了對a1,b1,c1排序。同樣,執行change(i,j)函數,可以實現對實參i和j的互換。
14.編一程序,將兩個字符串連接起來,結果取代第一個字符串。要求用string方法。
【解】 可以編寫出以下程序:
#include <iostream>
#include <string> //程序中若使用字符串變量,必須包含頭文件string
using namespace std;
int main( )
{ string s1= " week ",s2= " end ";
cout << " s1= " << s1 << endl;
cout << "s2=" << s2 << endl;
s1=s1+s2;
cout<<" The new string is: "<<s1<<endl;
return 0;
}
運行情況如下:
s1=week
s2=end
The new string is: weekend
15.輸入一個字符串,把其中的字符按逆序輸出。如輸入LIGHT,輸出THGIL。要求用string方法。
【解】 可以編寫出以下程序:
#include <iostream>
#include <string>
using namespace std;
int main( )
{ string str; //定義字符串變量str
int i,n;
char temp; //定義字符變量temp
cout<<" please input a string: ";
cin>>str; //輸入一個字符串賦給字符串變量str
n=str.size( ); //測量str的長度n
for(i=0;i<n/2;i++) //使str中的字符對稱互換
{temp=str[i];str[i]=str[n-i-1];str[n-i-1]=temp;}
cout << str << endl;
return 0;
}
運行情況如下:
please input a string:
LIGHT↙
THGIL
注意:輸入的字符串中不能含有空格。
16.有5個字符串,要求將它們按由小到大的順序排列,用string方法。
【解】 可以編寫出以下程序:
#include <iostream>
#include <string>
using namespace std;
int main( )
{ int i;
string str[5]={" BASIC"," C"," FORTRAN"," C++","PASCAL"};
void sort(string [ ]);
sort(str); //對字符串排序
cout<<" the sorted strings : "<<endl;
for(i=0;i<5;i++)
cout<<str[i]<<" "; //按已排好的順序輸出字符串
cout<<endl;
return 0;
}
void sort(string s[ ])
{int i, j;
string t;
for (j=0; j<5; j++)
for(i=0; i<5-j; i++)
if (s[i]>s[i+1])
{t=s[i];s[i]=s[i+1];s[i+1]=t;}
}
運行結果如下:
the sorted strings :
BASIC C C++ FORTRAN PASCAL
17.編一個程序,用同一個函數名對n個數據進行從小到大排序,數據類型可以是整型、單精度型、雙精度型。用重載函數實現。
【解】 可以編寫出以下兩個程序:
(1)建立3個函數,分別用於處理整型、單精度型、雙精度型數據的排序,在3個函數中都采用選擇法排序方法。
#include <iostream>
#include <string>
using namespace std;
int main( )
{
long a[5]={10100,-123567, 1198783,-165654, 3456};
int b[5]={1,9,0,23,-45};
float c[5]={2.4, 7.6, 5.5, 6.6, -2.3 };
void sort(long [ ]);
void sort(int [ ]);
void sort(float [ ]);
sort(a);
sort(b);
sort(c);
return 0;
}
void sort(long a[ ])
{int i, j;
long t;
for (j=0; j<5; j++)
for(i=0;i<5-j;i++)
if (a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
void sort(int a[ ])
{int i, j, t;
for (j=0; j<5; j++)
for(i=0;i<5-j;i++)
if (a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
void sort(float a[ ])
{int i, j;
float t;
for (j=0;j<5;j++)
for(i=0;i<5-j;i++)
if (a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
運行結果如下:
the sorted numbers :
-123567 -165654 10100 3456 1198783 (長整型數據排序)
the sorted numbers : (整型數據排序)
-45 0 1 9 23
the sorted numbers :
-2.3 2.4 5.5 6.6 7.6 (單精度型數據排序)
(2)在第1種方法中,3個函數的函數體基本上是相同的,都是采用選擇法排序,在下面的程序中,3個函數的函數體不全相同,前兩個函數采用選擇法排序,最后一個函數采用起泡法排序。
#include <iostream>
#include <string>
using namespace std;
int main( )
{ long a[5]= {10100,-123567, 1198783,-165654, 3456};
int b[5]={1,9,0,23,-45};
float c[5]={2.4, 7.6, 5.5, 6.6, -2.3 };
void sort(int [ ]);
void sort(float [ ]);
void sort(long [ ]);
sort(a); //對長整型數據排序
sort(b); //對整型數據排序
sort(c); //對單精度型數據排序
return 0;
}
void sort(long a[ ]) //對長整型數據用選擇法排序的函數
{int i,j,min;
long t;
for(i=0;i<5;i++)
{min=i;
for (j=i+1;j<5;j++)
if(a[min]>a[j]) min=j;
{t=a[i]; a[i]=a[min]; a[min]=t; }
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
void sort(int a[ ]) //對整型數據用選擇法排序的函數
{int i, j, t;
for (j=0; j<5; j++)
for(i=0;i<5-j;i++)
if (a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
void sort(float a[ ]) //對單精度型數據用起泡法排序的函數
{int i, j;
float t;
for (j=0;j<5;j++)
for(i=0;i<5-j;i++)
if (a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
運行結果如下:
the sorted numbers :
-123567 -165654 10100 3456 1198783 (長整型數據排序結果)
the sorted numbers : (整型數據排序結果)
-45 0 1 9 23
the sorted numbers :
-2.3 2.4 5.5 6.6 7.6 (單精度型數據排序結果)
對比兩種方法,可以看到,並不要求重載函數的函數體相同,在本例中,采用不同的排序方法,結果是相同的。從理論上說,重載的函數可以用來實現完全不同的功能,但是應該注意:同一個函數名最好用來實現相近的功能,而不要用來實現完全不相干的功能,以方便用戶理解和使用。
18.對第17題改用函數模板實現。並與17題程序進行對比分析。
#include <iostream>
#include <string>
using namespace std;
template <typename T >
void sort(T a[ ]) //函數模板,采用選擇法排序
{int i, j, min;
T t;
for(i=0;i<5;i++)
{min=i;
for (j=i+1; j<5; j++)
if(a[min]>a[j]) min=j;
t=a[i]; a[i]=a[min]; a[min]=t;
}
cout<<" the sorted numbers : "<<endl;
for(i=0;i<5;i++)
cout<<a[i]<< " ";
cout<<endl<<endl;
}
int main( )
{ long a[5]={10100,-123567, 1198783,-165654, 3456};
int b[5]={1,9,0,23,-45};
float c[5]={2.4, 7.6, 5.5, 6.6, -2.3 };
sort(a);
sort(b);
sort(c);
return 0;
}
運行結果如下:
the sorted numbers :
-123567 -165654 10100 3456 1198783 (長整型數據排序)
the sorted numbers : (整型數據排序)
-45 0 1 9 23
the sorted numbers :
-2.3 2.4 5.5 6.6 7.6 (單精度型數據排序)
對比第17題和18題,可以看到,如果重載函數的函數體基本相同的話,用函數模板顯然更方便,可以壓縮程序篇幅,使用方便。