【C++習題筆記】譚浩強C++程式設計(第三版)第四章
1. 寫兩個函式,分別求兩個整數的最大公約數和最小公倍數,用主函式呼叫這兩個函式,並輸出結果
//兩個函式求最大公約數和最小公倍數 #include <iostream> using namespace std; int main() { int a,b,c,d; int maxcm(int a, int b); int mincd(int a, int b); cin >> a >> b; c = maxcm(a,b); cout << "最大公約數為:"<< c <<'\n'; d = mincd(a,b); cout <<"最小公倍數為:"<< d <<'\n'; } int maxcm(int a, int b) { int m,n,k; m = a; n = b; do{ k = m % n; m = n; n = k; }while(k); return m; } int mincd(int a, int b) { int c,d; c = maxcm(a,b); d = a*b/c; return d; }
此題注意:函式首部的形參不用在函式中再定義一次;呼叫函式時,實參前邊不用寫型別。
此題仍用的是輾轉相除法計算的最大公約數與最小公倍數,詳細解釋請見:https://blog.csdn.net/zl3090/article/details/84614046
2. 求方程ax2+bx+c=0的根.用三個函式分別求當:b2-4ac大於0、等於0和小於0時的根並輸出結果。在主程式中輸入a,b,c的值。
//三個函式求二次方程的根 #include <iostream> #include <cmath> using namespace std; float r1,r2;//全域性變數,實根 float p, q;//虛根 int main() { float a,b,c; float t; void root1(float a, float b, float c);//大於0 void root2(float a, float b, float c);//等於0 void root3(float a, float b, float c);//小於0 cin >> a >> b >> c; //判別式計算 t = b*b - 4*a*c; //分情況 if (t>0) { root1(a,b,c); cout << "r1 = " << r1 << '\t'<< "r2 = " << r2 <<'\n'; } else if (t == 0) { root2(a,b,c); cout << "r1 = " << r1 << '\t'<< "r2 = " << r2 <<'\n'; } else { root3(a,b,c); cout<<"r1="<< p <<'+'<< q <<'i'<<'\n'; cout<<"r2="<< p <<'-'<< q <<'i'<<'\n'; } } void root1(float a, float b, float c) { r1 = (-b+sqrt( b*b - 4*a*c))/(2*a); r2 = (-b-sqrt( b*b - 4*a*c))/(2*a); } void root2(float a, float b, float c) { r1 = r2 = (-b)/(2*a); } void root3(float a, float b, float c) { p = -b/(2*a);; q = sqrt(-(b*b - 4*a*c))/(2*a); }
此題注意的是,在一個函式中如果想實現多個輸出,最簡單的方法就是全域性變數和void函式的結合
還有其他方法可見:https://blog.csdn.net/qq_34489443/article/details/81274951
3. C++程式 寫一個判斷素數的函式,在主函式輸入一個整數,輸出是否為素數的資訊。
//素數的判別函式 #include <iostream> using namespace std; int main() { int a,r; r = 0; int prime(int a); cin >> a; r = prime(a); if (r == 1) cout << a <<"是素數"; else cout << a <<"不是素數"; } int prime(int a) { int i,r; r = 1; for (i=2;i<a/2;i++) { if (a % i == 0) { r = 0; break; } } return r; }
此題注意:素數即質數,優化在於for迴圈中放的是2到a/2之間的數字,只考慮一半即可,因為另一半是和前一半配對的。
4. 求a!+b!+c!的值,用一個函式fac(n)求n!。a,b,c的值由主函式鍵入,最終的值在主函式中輸出。
//遞迴求階乘
#include <iostream>
using namespace std;
int main()
{
int a,b,c,s;
int fac(int a);
cin >> a >> b >> c;
s = fac(a) + fac(b) +fac(c);
cout << a << ','<< b << ','<< c<<"的階乘之和為"<< s <<'\n';
}
int fac(int a)
{
long r;
r = 0;
if (a <0)
cout <<"error";
else if (a == 1 || a == 0)
r = 1;
else
{
r = a * fac(a-1);
}
return r;
}
此題注意,輸出的階乘為long型,不然太容易溢位。
5. 寫一函式求sinh(x)的值,求sinh(x)的近似公式為 sinh(x)=(ex-e(-x))/2其中用一個函式求ex (x在指數位置)
//ex函式的複合函式
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double x,sh;
double ex(double x);
cin >> x;
sh = (ex(x) - ex(-x))/2;
cout << "sinh(x)的值為:"<< sh <<'\n';
}
double ex(double x)
{
double e;
e = exp(x);
return e;
}
6. 用牛頓迭代法求根。方程為ax3+bx2+cx+d=0 係數a,b,c,d的值依次為1,2,3,4, 由主函式輸入。求x在1附近的一個實根。求出根後由主函式輸出。
牛頓迭代法公式詳見:https://baike.baidu.com/item/%E7%89%9B%E9%A1%BF%E8%BF%AD%E4%BB%A3%E6%B3%95/10887580?fr=aladdin
//牛頓迭代法求根
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double a,b,c,d,r;
double newton(double a, double b, double c, double d);
cin >> a >> b >> c >>d;
r = newton(a,b,c,d);
cout << "牛頓迭代法所得的根為:"<< r;
}
double newton(double a, double b, double c,double d)
{
double x= 1,x0,f,f1;
do {
x0 = x;
f=((a*x0+b)*x0+c)*x0+d;
f1=(3*a*x0+2*b)*x0+c;//一階導
x=x0-f/f1;
}while(fabs(x-x0)>=1e-5);
return x;
}
do-while的用法還要加強
7. 寫一個函式驗證哥德巴赫猜想:一個不小於6的偶數可以表示為兩個素數之和,如6=3+3,8=3+5,10=3+7……在主函式輸入一個不小於6的偶數N。然後呼叫函式gotbaha,在gotbaha函式中再呼叫prime函式,prime函式的作用是判別一個數是否為素數。在godbah函式中輸出以下形式的結果:34=3+31
//哥德巴赫猜想
#include <iostream>
using namespace std;
int main()
{
int e,flag = 0;
int gotbaha(int e);
cin >> e;
flag = gotbaha(e);
if (flag == 1)
cout << "gotbaha is true.";
}
int gotbaha(int e)
{
int a,b,flag = 0;
int prime(int a);
if (e <=5 || e % 2 !=0 )
cout << "Please enter odd number";
else
{
for(a=3;a<=e/2;a=a+2)
{
if(prime(a))
{
b=e-a;
if (prime(b))
flag = 1;
}
}
}
return flag;
}
int prime(int a)
{
int i,r;
r = 1;
for (i=2;i<a/2;i++)
{
if (a % i == 0)
{
r = 0; break;
}
}
return r;
}
此題的關鍵在於如何把一個偶數拆成兩個奇數的和,然後分別驗證這兩個奇數是不是素數。
8. 用遞迴方法求n階勒讓德多項式的值,遞迴公式為:
//遞迴求值
#include <iostream>
using namespace std;
int main()
{
float n,x,r;
float p(float n,float x);
cin >> n >> x;
r = p(n,x);
cout << "公式的值為"<< r ;
}
float p(float n, float x)
{
if (n==0)
return(1);
else if (n==1)
return(x);
else
return(((2*n-1)*x*p((n-1),x)-(n-1)*p((n-2),x))/n);
}
9. Hanoi(漢諾)塔問題。這是一個經典的數學問題:古代有一個梵塔,塔內有3個座A,B,C,開始時A座上有64個盤子,盤子大小不等,在的在下,小的在上(見下圖)。
有一個老和尚想把這64個盤子從A盤移到C座,但每次只允許移動一個盤,且在移動過程中有3個座上都始終保持在大盤在下,小盤在上。在移動過程中可以利用B座,要求編寫程式打印出移動的步驟。
解題思路:採用遞迴方法,關鍵在於可以逆向思考,即不考慮前邊n-1個盤子是怎麼移動的,直接考慮最後一次移動的情況,由題意知,A為原始塔,B為輔助塔,C為目標塔,分為以下三步:
(1)先把A上的n-1個盤子移動到B上(不考慮具體過程,交給遞迴);
(2)然後把A中最後一個盤子移動到C上;
(3)此時B成為原塔,A為輔助塔,將B中n-2個盤子放到A上(仍不考慮具體過程,交給遞迴);
此時,一輪移動已結束,下一次的開始,將B中的一個剩下的一個放在C上
理解過程如下動畫所示:(參考自:https://www.cnblogs.com/wuzhenbo/p/3496054.html)
三個圓盤的漢諾塔
四個圓盤的漢塔:
程式碼如下:
//漢諾塔
#include <iostream>
using namespace std;
int main()
{
int n;
char x, y ,z;
void Hanoi(int n, char x, char y, char z);//原塔,輔助塔,目標塔
cin >> n;
Hanoi(n,'A','B','C');
}
void Hanoi(int n, char x, char y, char z)
{
if (n == 1) cout<<"From "<< x <<" To "<<z <<'\t';
else
{
Hanoi(n-1,x,z,y); //將n-1個盤子從x移動到y
cout <<"From "<< x <<" To "<<z <<'\t';//將第n個盤子移動到z
Hanoi(n-1,y,x,z);//將y上的盤子移動到z
}
}
10. 用遞迴法將一個整數n轉換成字串。例如 輸入483,應輸出字串“483”。n的倍數不確定,可以是任意倍數的整數。
//遞迴將數字轉為字串
#include <iostream>
using namespace std;
int main()
{
int n;
void convert(int n);
cin >> n;
if (n<0)
{
cout << "-";
n = -n;
}
convert(n);
}
void convert(int n)
{
int i;
char c;
if ((i =n/10) != 0)
convert(i);
c = n % 10 + '0';
cout<<" "<<c;
}
單個數字變字串,給它+‘0’即可
11. 用遞迴方法求
n的值由主函式輸入。
//遞迴求函式值
#include <iostream>
using namespace std;
int main()
{
int n,s;
int fac (int n);
cin >> n;
s = fac(n);
cout <<"函式的值為:"<< s;
}
int fac(int n)
{
int s;
if (n==1)
s = n*n;
else
s = n*n + fac(n-1);
return s;
}
12. 三角形的面積為 area=s*(s-a)*(s-b)*(s-c) 其中,s=1/2*(a+b+c), a , b, c 為三角形的三邊。定義兩個帶引數的巨集,一個用來求S,另一個用來求 area 。 編寫程式,在程式中用帶實參的巨集名來求面積。
//帶實參的巨集求三角形面積
#include <iostream>
#include <cmath>
using namespace std;
#define S(a,b,c) (a+b+c)/2
#define AREA(a,b,c) sqrt(S(a,b,c)*(S(a,b,c)-a)*(S(a,b,c)-b)*(S(a,b,c)-c))
int main()
{float a,b,c;
cout<<"input a,b,c:";
cin>>a>>b>>c;
if (a+b>c && a+c>b && b+c>a)
cout<<"area="<<AREA(a,b,c)<<endl;
else
cout<<"It is not a triangle!"<<endl;
return 0;
}
這裡使用了巨集作為簡易函式的用法,關於巨集用法的總結請見: