《C++程式設計上機實踐及學習輔導》實驗報告
額…本人大一新生,剛接觸C++,學期末作業是這本書的實驗報告,其中有十幾個實驗內容,這是我們新生第一學期的課,所以內容也很基礎,但我也是新接觸,外加C++課上無數次走神加之課后作業迷迷糊糊,所以現在感徑訓是很菜因此也是硬著頭皮完成作業,相信會遇到很多障礙,便在這里記錄一下自己的學習程序,還請各位大佬多多指教,希望自己能在這條路上一直走下去,
2020.12.30,19:35.
實驗一、簡單程式設計
1.撰寫程式,計算圓的面積,半徑從鍵盤輸入,
#include<iostream>
using namespace std;
int main()
{
double r; //定義半徑r
cin >> r; //輸入半徑r
const double Pi = 3.14; //定義常量π為3.14
double S; //定義面積S
S = Pi * r * r; //計算S
cout << "半徑為 " << r << " 的圓的面積為 " << S << endl;
//輸出面積S
return 0; // atFuRYh
}
運行結果如下
這個挺簡單的一個,畢竟第一個實驗,
2.撰寫程式,已知三角形的三邊a、b、c,求三角形的周長和面積,
#include <iostream>
#include<cmath>
using namespace std;
int main()
{
double a=3, b=5, c=4; //定義三邊,且長度已知
double C = a + b + c; //定義周長C,為abc的和
double CosC = (a * a + b * b - c * c) / (2 * a * b);
double SinC = sqrt(1 - (CosC * CosC));
double S = 1 / 2 * a * b * SinC;
cout << "三角形的周長為" << C << endl;
cout << "三角形的面積為" << S << endl;
return 0;
}
這是第一次撰寫完成的,發現輸出周長正常,面積為0,遂進行除錯,除錯發現SinC的值出了問題,
檢查半天未果,叫舍友幫忙,結果發現SinC也沒問題,,是我除錯沒除錯對,然后發現問題出在了這里,原因是我沒有加括號,
double S = 1 / 2 * a * b * SinC;
加上括號改成了這樣,結果還是不對,,提示未定義識別符號,,又搞了半天發現是用了中文輸入法的括號搞的,所以出了問題,改后,OK,
double S = (a * b * SinC)/2;
貼上最終的代碼
#include <iostream>
#include<cmath>
using namespace std;
int main()
{
double a=3, b=5, c=4; //定義三邊,且長度已知
double C = a + b + c; //定義周長C,為abc的和
//以下為求面積部分,將使用余弦定理計算,
double CosC = (a * a + b * b - c * c) / (2 * a * b); //利用余弦定理求CosC
double SinC = sqrt(1 - (CosC * CosC)); //求SinC
double S = (a * b * SinC)/2; //求面積
cout << "三角形的周長為" << C << endl;
cout << "三角形的面積為" << S << endl;
return 0; //atFuRYh
}
輸出結果
實驗二 回圈結構程式設計
1. 要求設計一個函式,求出一元二次方程ax2+bx+c=0的實根,系數a,b,c的值從鍵盤上輸入,求方程根的計算公式為x=,當b2-4ac小于0時,輸出“無實根!”;否則輸出x的兩個實根,
#include<iostream>
using namespace std;
void Gen(int a,int b,int c)
{
double X1,X2;
double De = b ^ b - 4 * a * c;
X1 = (-b + sqrt(De)) / 2 * a;
X2 = (-b - sqrt(De)) / 2 * a;
if (De < 0)
cout << "無實根" << endl;
if (De ==0)
cout << "X1=X2=" << X1 << endl;
if (De > 0)
cout << "X1=" << X1 << endl<<"X2=" << X2 << endl;
}
int main()
{
Gen(1, -2, 1);
return 0;
}
運行結果為X1=2,X2=0,顯然不對勁…遂進行除錯,發現De=4,顯然出錯了,,然后開始找原因,發現…是b*b打錯打成了b^b,改掉后一切正常,
但是在此處報錯,提示如圖,雖然未發現此報錯影響結果但還是嘗試解決,遂去百度,
百度了錯誤代碼后發現看不懂,,,在知乎找到如下回答
這個意思是你兩個float型相+之后,會再轉換為double輸入給函式,編譯器認為既然你最后會轉為double型、那么float型可能裝不下你那兩個float型的相+結果,存在溢位風險解決只需要float相+的兩個數任一強轉double就行了,不過你如果很清楚不會溢位的話只需無視即可另一常出現這個警告的情況是 地址+整*整
作者:袁方
鏈接:https://www.zhihu.com/question/352977886/answer/1187047126
可能還是因為我自己基礎不扎實反正我還是看不懂,大概理解為float形的存盤空間達到了上限制,改成double就好,但,我的本來就是double咋搞呢?于是看到了下面第二種解決方案,地址+整+整,于是猜想是不是我b*b讓編譯器誤以為這是一個地址了呢?于是更改為b^2,報錯解決,
題目中還要求abc通過鍵盤輸入,更改后完整代碼如下,
#include<iostream>
using namespace std;
void Gen() //定義函式Gen,求根函式
{
int a,b,c; //定義abc
cin >> a; //通過鍵盤輸入abc
cin >> b;
cin >> c;
double X1,X2; //定義兩根X1,X2
double De = b^2- (4 * a * c); //定義De
X1 = (-b + sqrt(De)) / 2 * a; //計算X1、X2
X2 = (-b - sqrt(De)) / 2 * a;
if (De < 0) //<0
cout << "無實根" << endl;
if (De ==0) //==0
cout << "X1=X2=" << X1 << endl;
if (De > 0) //>0
cout << "X1=" << X1 << endl<<"X2=" << X2 << endl; //atFuRYh
}
int main()
{
Gen();
return 0;
}
本次編程中還犯了一個錯誤,就是判斷De=0時候沒寫成==,報錯后才發現,
做到后面突然回頭看這里,發現又有了錯誤,,改成b^2之后,計算出來的De不對,而且我不知道怎么出了問題,,改回去b*b之后又出現了上述報錯但計算結果正確了,,然后想了一下才發現…C++中的 ^ 根本不是表示平方,得用pow函式,于是回傳頭cmath一下,然后pow(b,2)解決了這個問題,
感覺也是一個經常不注意就能犯了的錯誤吧…^ 可不是次方符號哈哈,
2. 撰寫程式,求出1~599中能被3整除,且至少有一位數字為5的所有整數,如15,51,513均是滿足條件的整數, 運行結果為15 45 51 54 57 … 594 597等,共66個數,
能被3整除好說,主要是含有5有點復雜…于是大概思考,準備用與或非來寫,表達含有5的部分大概思路為:如果除以10余數為5,那么說明最后一位是5.如果除以100為5,那么說明第一位為5,如果減去百位,再除以10的余數為5,那么說明十位為5,
#include<iostream>
using namespace std;
int main()
{
int j = 0;
for (int i = 1; i < 600; i++)
{
if (i % 3 == 0 && (i % 10 == 5 || i / 100 == 5 || (i - (i / 100)) / 10 == 5))
{
cout << i << endl;
j++;
}
}
cout << j << endl;
return 0;
}
加了一個j,用來統計一共輸出了多少位,便于校對答案正確與否,但發現…輸出了53個,與題目告的66個差了不少,,所以又得回去檢查- -(除了第一題仿佛沒有哪個題一次對了)
發現錯誤在這里
(i - (i / 100)) / 10 == 5)
我i/100忘了乘以100…加上之后就OK了,去除掉j,得到最終代碼如下
#include<iostream>
using namespace std;
int main()
{
for (int i = 1; i < 600; i++)
if (i % 3 == 0 && (i % 10 == 5 || i / 100 == 5 || (i - (i / 100) * 100) / 10 == 5)) //如果除以10余數為5,那么說明最后一位是5.如果除以100為5,那么說明第一位為5,如果減去百位,再除以10的余數為5,那么說明十位為5,
cout << i << endl; //atFuRYh
return 0;
}
我的作息比較奇葩,那天晚上大概十二點多開始肝到三點多,,現在是2021年第一天的早上6:30,跨年夜早早的睡了結果醒的格外的早就起床敲代碼了,,這么神奇的作息我也要記錄下來
3.撰寫程式,求100~200內所有的素數,
想到的是雙重回圈,判斷素數,如果i/j的余數為0,則說明除的盡,所以不是素數,反之則是,第一次敲出來代碼如下,
#include<iostream>
using namespace std;
int main()
{
for (int i = 100; i <= 200; i++)
{
for (int j = 2; j < i; j++)
{
if (i% j != 0)
cout << i << endl;
else
break;
}
}
return 0;
}
結果不對,,,發現給我輸出了一大堆,然后檢查了一會兒發現問題所在:在每次除不盡的時候都會輸出一下,而應該改成全部除不盡再輸出,
改為如下,結果發現啥都不輸出了,,,
for (int i = 100; i <= 200; i++)
{
for (int j = 2; j < i; j++)
{
if (i% j == 0)
break;
else
continue;
cout << i << endl;
}
}
參考大佬的文章,發現自己問題所在,然后修改…
https://blog.csdn.net/qq_39778967/article/details/79998529
(大佬的代碼如下)
#include <stdio.h> //參考檔案
main()
{
int i,j; //定義回圈變數
for(i=100;i<=200;i++) //定義從100-200之間的回圈數字
{
for(j=2;j<i;j++) //判定條件從(2)—(i-1)之間能否被i整除
{
if(i%j==0) break; //如果可以則跳出回圈,不是素數
}
if(j>=i) //如果j>=i則為素數,并輸出
printf("%d\t",i); //用表格的形式輸出結果
}
}
沒認真看改了還錯,再回去看才發現是自己又少了判斷j>=i這步的判斷,所以導致輸出了老多東西,,想了想仿佛明白了…如果自己沒有這一步的話那每次跳出來都會輸出一下,所以幾多了,,但沒懂他為什么是大于等于,光等于不就行了么?
思考完了之后動手,發現這步判斷時候還必須把for回圈里面的j拿出去int一下,,自己還是太菜了啊,,,
最終代碼如下
#include<iostream>
using namespace std;
int main()
{
int j; //定義j,在此處定義,否則最后一個if判斷時候用不了
for (int i = 100; i <= 200; i++) //第一重回圈,備選數i,
{
for ( j = 2; j < i; j++) //用j來一個一個的除
if (i% j == 0) //除盡了則說明不是素數,跳出,如果一直除不盡則說明是素數,輸出
break;
if(j==i) //當j=i時,說明i已經除完了,確實是素數
cout << i << endl; //atFuRYh
}
return 0;
}
4.撰寫程式,用迭代公式求
,迭代公式為
要求初始值y=x,精度為
求出當x=0.75時,對應的y值(答案:0.92856),***
首先吐槽一句…那個字念die,不念zhu,然后word里面圖片的公式添加過來有點別扭將就看(其實可能也就只有我日后回憶時候看看了哈哈)
然后開始做題,想法是用回圈,當精度達到要求時候停止回圈,然后還得用函式寫出來那個公式,然后迭代,去編一下試試,
參考了百度上的這個案例
https://zhidao.baidu.com/question/1639198818115717660.html
#include<iostream>
#include<cmath>
using namespace std;
double GongShi(double y,double x)
{
y = (2 / 3)*y + x / (3*y * y);
return y;
}
int main()
{
double y1, y0;
do
{
y1 = y0;
GongShi(y1, y0);
} while (abs(y1 - y0) > 1e-5);
cout << y1 << endl;
return 0;
}
提示我y0沒有初始化,但我不知道該初始化成幾…然后隨便初始化成1,2發現輸出還是1,2,,,所以開始改,
斷點除錯,首先發現一個問題就是形參變了實參沒變…所以加了個&符號,改成了這樣
double GongShi(double &y,double &x)
繼續除錯發現y1的值每次更改之后都會被y0重新賦成初始值,自己除錯了半天發現還是不會…然后放棄了函式,直接搞,
重新做了一下,做出來如圖
#include<iostream>
using namespace std;
int main()
{
double a,x1, x2, y;
cin >> a;
x1 = a;
x2 = 0;
while (abs(x2-x1)>1e-5)
{
x2 = x1;
x1= (2 / 3) * x1 + a / (3 * x1 * x1);
}
cout << x2 << endl;
}
輸出結果:

哦豁…bug了?百度這個inf,告我說是超出資料范圍,浮點數溢位,一臉懵逼的去除錯,發現好像沒有能正確的終止回圈…然后我盯著回圈搞了半天,未果,
百度,參考此文,找到結果,因為我(2/3)=0.6666,編譯器默認int型,所以被除數成了0 ,所以就不對了,
https://zhidao.baidu.com/question/523420544.html
修改方案1:百度的方法,2改成2.0
修改方案2:與舍友討論后,參考他的,將(2/3)*x改成了2y13,因為之前y1定義過是double型,所以這里也就成了double型,就不會認為是0,
修改后成品如下:
(x1,x2,a的看的麻煩…搞錯了給,所以變數名字也改了一下)
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
double x,y1, y2; //y1,y2為題目中yn,yn+1,x就是x,
cin >> x;
y1 = x; //初始化y為x
y2 = 0;
while (fabs(y2-y1)>1e-5) //沒有用到do while,因為第一次的時候也滿足條件進入回圈
{
y2 = y1;
y1= 2*y1/ 3 + x / (3 * y1 * y1); //atFuRYh
}
cout << y2 << endl;
}
這個題大概就這樣結束了,不過上面那個想嘗試利用函式的方法失敗了…日后有空再回頭研究一下,
實驗三 函式的定義和呼叫
1. 利用弦截法求f(x)=0的一個實根,

按著去做,做出來如下,
#include<iostream>
using namespace std;
double Fx(double x)
{
double y;
y = x * x + 3*x - 4;
return y;
}
int main()
{
double x1, x2, x0;
cin >> x1;
cin >> x2;
do
{
x0 = (x1 * Fx(x2) - x2 * Fx(x1)) / (Fx(x2) - Fx(x1));
} while (fabs(Fx(x0)) > 1e-5);
return 0;
}
運行后輸入之后沒反應…與舍友交流,發現問題所在,一來是我執行完回圈之后沒有輸出(這個問題卡了他一天結果我倆交流了幾分鐘就發現了,,)二來是我完全沒讀懂題,題目中要求用弦截法,
數學知識不過關,所以開始自學弦截法是啥,,(其實書上有提示…)
按著書上的提示寫出來代碼如下:
#include<iostream>
using namespace std;
double Fx(double x)
{
double y;
y = x * x + 3*x - 4;
return y;
}
int main()
{
double x1, x2, x0;
cin >> x1;
cin >> x2;
do
{
x0 = (x1 * Fx(x2) - x2 * Fx(x1)) / (Fx(x2) - Fx(x1));
if (Fx(x0) * Fx(x1) < 0)
x2 = x0;
else
x1 = x0;
} while (fabs(Fx(x0)) > 1e-5);
cout << x0 << endl;
return 0;
}
運行,發現無論如何輸出的都是1…除錯,發現仿佛函式那里該加上&,加上之后還不對,,然后繼續試,與舍友交流之后發現自己又少了一步,判斷這個輸入的值是否正確,加了一些,
再百度參考了另一篇文章,將程式寫的更加模塊化了一些,但還是不對…除錯了半天也沒用找到問題所在,遂放棄,,等改日再研究研究知道了再改,
#include<iostream>
#include<cmath>
using namespace std;
double x1, x2, x0,x;
double Fx(double x)
{
double m;
m = x * x + 3*x - 4;
return m;
}
double Root(double x1, double x2)
{
do {
x0 = (x1 * Fx(x2) - x2 * Fx(x1)) / (Fx(x2) - Fx(x1));
if (Fx(x0) * Fx(x1) < 0)
x2 = x0;
else
x1 = x0;
} while (fabs(Fx(x0)) > 1e-5);
return Fx(x0);
}
int main()
{
do{
cin >> x1;
cin >> x2;
if (Fx(x1) * Fx(x2) >= 0)
cout << "輸錯了,請重輸" << endl;
} while (Fx(x1) * Fx(x2) >= 0);
Root(x1, x2);
cout << x0 << endl;
return 0;
}
2. 用遞回呼叫的方法撰寫本題,用牛頓迭代法求f(x)=0的一個實根,

…???牛頓迭代什么玩意,,感謝C++讓我意識到了學好高數的重要性,下學期高數一定認真聽講…!
先跳過了等等再寫這題
1.4回頭搞這道題,其實書上就有提示那天知識太晚懶得鼓搗…按書上提示,需要用到導數,所以我定義了Fx之后又定義了一個Dx(Fx的導數)
代碼如下:
#include<iostream>
using namespace std;
double Fx(double x) //Fx
{
double a;
a = x * x + 3 * x - 4;
return a;
}
double Df(double x) //Dx
{
return (2 * x + 3);
}
double DiGui(double x)
{
x = x - Fx(x) / Df(x);
if (fabs(Fx(x)) < 1e-5) //此句用來確認精度
return x;
else
return DiGui(x);
}
int main()
{
double x = 0; //atFuRYh
cout << DiGui(x)<<endl;
}
輸出答案是對的,結束!
實驗四 函式引數傳遞機制
撰寫程式驗證哥德巴赫猜想
一個不小于6的偶數可以表示兩個素數之和,如6=3+3,8=3+5,10=3+7,…,在主函式中輸入一個不小于6的偶數n,程式運行后輸出一下形式的結果:
若輸入34,則程式輸出為:
34=3+31
34=5+29
34=11+23
34+17+17
撰寫程式,編譯、運行,當輸入為56↙時,輸出為;
當輸入122↙時,輸出為:
驗證哥德巴赫猜想,那么…應該先是寫一個函式,判斷數是否為素數,然后再用把輸入的數成兩半,分開判斷是不是素數,如果是就輸出,不是就重新分,
按此思路寫出來結果如下:
#include<iostream>
using namespace std;
bool Su(int x)
{
bool m = true;
if (x <= 2)
m=false;
else
{
for (int i = 2; i < x; i++)
{
if (x % i == 0)
m=false;
else
continue;
}
}
return m;
}
int main()
{
int Num;
while (1)
{
cin >> Num;
if (Num < 6 || Num % 2 != 0)
cout << "請重新輸入" << endl;
else
{
break;
}
}
for (int i = 1; i < Num; i++)
{
int a = i;
int b = Num - i;
if (Su(a) == 1 || Su(b) == 1)
cout <<Num<< "=" << a <<"+"<<b<< endl;
else
continue;
}
}
輸出結果如下:

可以看到仿佛問題挺大…
首先1不是素數,其次9也不是素數,最后應該5+7和7+5只輸出一次,
所以回傳去檢查程式,
發現第一個問題,,,||是或,&&才是且,,看來還是基礎不扎實,默默擔心五天后的C++期末…
改掉第一個問題后,這樣的話剩下的問題只有5+7和7+5輸出了兩次這里,于是想,輸出一次之后,直接結束程式是不是就可以了呢?
搞定,完事!
最終代碼如下
#include<iostream>
using namespace std;
bool Su(int x) //判斷一個數是否為素數,如果是則回傳true,反之回傳false,
{
bool m = true;
if (x <= 2)
m=false;
else
{
for (int i = 2; i < x; i++)
{
if (x % i == 0)
m=false;
else
continue;
}
}
return m;
}
int main()
{
int Num;
cout << "請輸入一個不小于6的偶數" << endl;
while (1) //判斷輸入的數是否符合題意,為大于6的偶數
{ //回圈條件設定為1,即一直進行,直到跳出
cin >> Num;
if (Num < 6 || Num % 2 != 0)
cout << "請重新輸入" << endl;
else
break;
}
for (int i = 1; i < Num; i++) //驗證部分
{
int a = i; //將Num分成ab兩個整數,
int b = Num - i;
if (Su(a) == 1 && Su(b) == 1) //判斷ab是否均為素數
{ //atFuRYh
cout << Num << "=" << a << "+" << b << endl;
break; //如果不跳出,則會輸出兩次,例如5+7,7+5兩次
}
else
continue;
}
return 0;
}
實驗五 一維陣列的定義和使用
用選擇法對陣列元素進行從小到大的排序,請完善程式,編譯、連接,并寫出運行結果,
先是去百度了一下什么叫個選擇法…(其實書上講的很詳細,哈哈)
第一次敲出來的如下:(請忽略這個輸出陣列的方式,測驗一下就沒敲回圈)
#include<iostream>
using namespace std;
int main()
{
int a[6] = { 5,9,8,3,7,2 }; //定義一個6長度的陣列,隨機放幾個數,沒按書上的數字來
int min=0; //min,用于存放最小數的下標,初始化為0
int t; //t,交換時候中間變數
for (int i = 1; i < 6; i++)
{
if (a[min] < a[i])
continue;
else
{
t = a[min];
a[min] = a[i];
a[i] = t;
}
}
cout << a[0] << endl;
cout << a[1] << endl;
cout << a[2] << endl;
cout << a[3] << endl;
cout << a[4] << endl;
cout << a[5] << endl;
return 0;
}
輸出結果為
2,9,8,5,7,3,百思不得其解…咋排的???遂去除錯,發現問題所在,min本應是存盤一組中最小的一個,而我卻錯誤的將它存盤上了第一個比他小的,所以運行下來5與3交換,3再與2交換,就得到了這個錯誤的結果…
開始改代碼,再讀一次課本的提示發現自己錯誤挺大,還是沒有吃透這個方法,,于是 重新去看,發現他應該用兩個回圈,分開處理下標和陣列元素,修改后結果如下:
在這里插入代碼片#include<iostream>
using namespace std;
int main()
{
int a[6] = { 5,9,8,3,7,2 }; //定義一個6長度的陣列,隨機放幾個數,沒按書上的數字來
int min; //min,用于存放最小數的下標,初始化為0 atFuRYh
int t; //t,交換時候中間變數
for (int i = 0; i < 5; i++) //處理元素的回圈
{
min = i;
for (int j =i+1; j < 6; j++) //用于處理下標的回圈
if (a[min] > a[j])
min = j; //交換下標
t = a[min]; //交換元素
a[min] = a[i];
a[i] = t;
}
for (int x = 0; x < 6; x++) //輸出
cout << a[x] << endl;
return 0;
}
最終成功輸出,
實驗六 二維陣列的定義和使用
將二維陣列的各列按其所有元素的和從小到大進行排列,每一列元素的相對位置保持不變,

好家伙…看到這個題的時候是一臉迷茫的,多讀了幾次題感覺理解了點他的意思然后開始敲,自己編了三個函式,分別是求和、排序、交換xy列,排序的代碼來自上一個實驗中一位陣列的選擇法排序,大致思路是這樣的,先每一列去求和,求出來之后按要求將和從小到大排序,然后拍完得到一個新的陣列k,再用二維陣列每一列的和與k陣列比較,如果不一樣就交換,交換到一樣位置,那么這時候得到的新陣列即為所求,
卡了我好久的一個地方是…忘了把排序注釋掉了,所以拿著沒排序的k研究了半天為何if不對,,,
#include<iostream>
using namespace std;
int k[4];
int sum(int b[3][4], int k) //計算3行4列的二維陣列中第k列的和
{
int sum=0;
for (int i = 0; i < 3; i++)
sum += b[i][k];
return sum;
}
void PaiXu(int k[4]) //此段代碼復制自上一個實驗,并略加修改
{
int min; //min,用于存放最小數的下標,初始化為0 atFuRYh
int t; //t,交換時候中間變數
for (int m = 0; m < 3; m++) //處理元素的回圈
{
min = m;
for (int n = m + 1; n < 4; n++) //用于處理下標的回圈
if (k[min] > k[n])
min = n; //交換下標
t = k[min]; //交換元素
k[min] = k[m];
k[m] = t;
}
}
void Swapxy(int b[3][4], int x, int y) //交換陣列的X、Y列
{
int a[3];
for (int i = 0;i < 3;i++)
{
a[i] = b[i][x];
b[i][x] = b[i][y];
b[i][y] = a[i];
}
}
int main()
{
int arr[3][4] = { 5,8,10,15,17,6,4,8,6,15,9,12 };
for (int j = 0; j < 4; j++) //將每列的和賦給陣列k[]
k[j] = sum(arr, j);
PaiXu(k); //把求和出來的值進行排序
//交換xy列,直到交換出來的四列各列之和與k【】相等 atFuRYh
for (int i = 0; i < 4; i++)
for (int j = 0;j<4 ; j++)
if(sum(arr, i) != k[i])
Swapxy(arr, i, j);
for (int i = 0; i < 3; i++) //輸出部分
for (int j = 0; j <4; j++)
cout << arr[i][j] << endl;
return 0;
}
本實驗感悟:傳參時候陣列名后面不用加【】【】直接傳陣列名就好
好家伙好家伙,現在是2021年1月2日凌晨4:54分,我感覺自己作息好奇怪…1.1早上6:30起床敲,然后到中午吃個飯,回來玩了一會兒一覺睡到晚上七點半,,,起床吃個飯玩一下十一點開始肝到現在…然后準備睡覺去了,再一次打破我上大學以來最晚睡覺的記錄,,上一次是CTF新生校賽時候肝到四點半,現在是敲代碼到五點,,,目測一覺睡到十二點吧,然后吃飯下午有事出去晚上繼續!

果不其然一覺十二點,,起床吃飯下午有事然后晚上回來休息一下,現在九點半接著搞,吐槽一下江蘇這鬼天氣,空調壞了凍死人,,手腳冰涼,穿的倆毛衣+羽絨服敲代碼,,,,
實驗七 類和物件的定義與訪問
撰寫Money類,資料成員為Yuan、Jiao、Fen,函式成員包括兩筆Money的加和減,
#include<iostream>
using namespace std;
class money
{
public:
int Yuan;
int Jiao;
int Fen;
money operator+(money a)
{
money g;
g.Yuan = a.Yuan + Yuan;
g.Jiao = a.Jiao + Jiao;
g.Fen = a.Fen + Fen;
return g;
}
money operator-(money a)
{
money g;
g.Yuan = Yuan - a.Yuan;
g.Jiao = Jiao - a.Jiao;
g.Fen = Fen - a.Fen;
return g;
}
};
其實說實話沒看懂這個題是要干嘛,,,去百度看了看類似的案例,發現應該還有一個功能,就是實作進位,即 十角表示成一元 這樣,,所以回傳進行修改,加了檢查是否大于9,和輸出兩個函式,代碼如下
#include<iostream>
using namespace std;
class money
{
public:
int Yuan;
int Jiao;
int Fen;
money operator+(money a)
{
void CheckDate(money m);
money g;
g.Yuan = a.Yuan + Yuan;
g.Jiao = a.Jiao + Jiao;
g.Fen = a.Fen + Fen;
CheckDate(g);
return g;
}
money operator-(money a)
{
void CheckDate(money m);
money g;
g.Yuan = Yuan - a.Yuan;
g.Jiao = Jiao - a.Jiao;
g.Fen = Fen - a.Fen;
return g;
CheckDate(g);
}
};
void CheckDate(money m)
{
if (m.Fen >= 10)
{
m.Jiao += m.Fen / 10;
m.Fen = m.Fen % 10;
}
if (m.Jiao >= 10)
{
m.Yuan += m.Jiao / 10;
m.Jiao = m.Jiao % 10;
}
}
void print(money m)
{
cout << m.Yuan << "元" << m.Fen << "角" << m.Fen << "分" << endl;
}
int main()
{
money m1{ 1, 2, 3 };
money m2{ 2,9,8 };
money m3{};
m3 = m1 + m2;
print(m3);
}
但隨便輸了一個數字測驗一下…發現CheckDate函式還是出了,遂 回傳檢查修改,
哦豁…回去修改了半天,無果,,,除錯時候發現問題,感徑訓是函式傳值的時候沒有加&,導致沒成功修改,但加了之后發現報錯,如圖,然后修改了半天不知道咋辦,,,,百度也沒有解決,遂放著日后再看吧,,,
1.3中午,開工開工!
與舍友交流后作出了修改,將函式改到了類內,然后就解決了上述問題,
但是遇到的新問題是…print出來的不對,然后設斷點除錯了半天,發現資料沒錯,CheckDate函式也正常運行,但是列印的不對,,去問老師,然后老師提醒我去print函式里面看,我進去一看發現…自己列印的東西錯了,,,丟臉丟大發的一個錯誤,
貼上最終成功運行的代碼,
#include<iostream>
using namespace std;
class money
{
public:
int Yuan;
int Jiao;
int Fen;
money operator+(money a) //多載,加
{
money g;
g.Yuan = a.Yuan + Yuan;
g.Jiao = a.Jiao + Jiao;
g.Fen = a.Fen + Fen;
g.CheckDate();
return g;
}
money operator-(money a) //多載,減
{
void CheckDate(money m);
money g;
g.Yuan = Yuan - a.Yuan;
g.Jiao = Jiao - a.Jiao;
g.Fen = Fen - a.Fen;
g.CheckDate();
return g;
}
void CheckDate() //檢查數字是否正確,11分則表示成1角1分
{
if (Fen >= 10)
{
Jiao += Fen / 10;
Fen = Fen % 10;
}
if (Jiao >= 10)
{
Yuan += Jiao / 10;
Jiao = Jiao % 10;
}
}
};
void print(money m) //輸出
{
cout << m.Yuan << "元" << m.Jiao << "角" << m.Fen << "分" << endl; //atFuRYh
}
int main()
{
money m1{ 1, 2, 3 };
money m2{ 2,9,8 };
money m3{}; //測驗,用m3存放m1,m2相加后結果
m3 = m1 + m2;
print(m1);
cout << "加上" << endl;
print(m2);
cout << "等于" <<endl ;
print(m3);
}
實驗八 建構式與解構式
定義一個類STR,將一個字串中指定位置的連續字符拼接到另一個字串的尾部
具體要求如下:
(1)私有資料成員,
char *p;存放一個字串,
(2)公有成員函式,
?STR(char *s):建構式,為資料成員p動態記憶體分配空間,并利用引數s初始化資料成員p,
?void fun(char *s,int nl, int n2):將字串s從第n1(從0開始計數)個字符開始的連續n2個字符拼接到資料成員p所指向的字串之后,形成第一個新的字串,注意,必須為p重新分配記憶體空間,
?Void print():按輸出指示例格式輸出資料成員p,
?~STR():解構式,釋放動態記憶體,
(3)在主函式中完成對該類的測驗,
輸入輸出示例(下畫線部分為鍵盤輸入):
字串1:abcdefg
字串2:12345678
輸入起始位置和字符個數:2 5↙
處理后的字串1為:abcdefg34567
哦豁…好長的任務要求,不過按部就班的一步一步來吧,先敲一下試試,
第一版如下:
#include<iostream>
#include<string>
using namespace std;
class STR
{
private:
char *p=0;
public:
STR(char* s)
{
char *p = new char[10];
p = s;
}
void fun(char* s, int n1, int n2)
{
char m[20] = {};
char* p = new char[20];
for (int i = 0; i < n2-n1; i++)
{
m[i] = s[n1 + i];
}
//定義一個陣列m,用于存放s中n1---n2段的字串,然后用strcpy函式鏈接p和m
p = strcat(p, m);
}
void print(char* p)
{
cout<<"拼接后的字串為:"<<p << endl;
}
~STR()
{
delete p;
}
};
int main()
{
char* a = "abcdefg";
char* b = "12345678";
STR s1(a);
/*STR s2(char *b);*/
s1.fun(b, 2, 5);
s1.print(a);
return 0;
}
運行報錯,C4996,,按照此文所說,關閉之后出現了其他問題,,,
https://blog.csdn.net/weixin_44171004/article/details/86675605
所以猜測是自己strcat函式用錯了,,就去百度這個函式教程,百度的一半恍然大悟,,仿佛我這道題本來就不是字串啊,,,應該是個陣列?所以應該用陣列賦值的方法來做,遂回傳重新修改,
改完之后如下:
#include<iostream>
#include<string>
using namespace std;
class STR
{
private:
char *p=0;
public:
STR(char* s)
{
char *p = new char[10];
p = s;
}
void PinJie(char *a,char *b)
{
int Len_a=sizeof(a);
int Len_b = sizeof(b);
a = (char*)malloc(sizeof(a) + sizeof(b));
for (int i = 0; i < Len_b; i++)
{
a[Len_a + i] = b[i];
}
/*return a;*/
}
void fun(char* s, int n1, int n2)
{
char m[10] = {};
char* p = new char[20];
for (int i = 0; i < n2-n1; i++)
{
m[i] = s[n1 + i];
}
//定義一個陣列m,用于存放s中n1---n2段的字串,然后用strcpy函式鏈接p和m
//修改:恍然大悟我用的不是字串,,所以不能用strcut,該按照陣列來處理,
PinJie(s, m);
}
void print(char* p)
{
cout<<"拼接后的字串為:"<<p << endl;
}
~STR()
{
delete p;
}
};
int main()
{
char* a = "abcdefg";
char* b = "12345678";
STR s1(a);
/*STR s2(char *b);*/
s1.fun(b, 2, 5);
s1.print(a);
return 0;
}
成功運行但是輸出的字串就是a,,,沒有進行拼接,所以設斷點回傳呼試,發現問題出在了初始化那里,,,p沒有被成功的賦值為s,所以后續拼接也不對,,不會解決,等明天舍友醒了商討一下再解決這個,(我又是陰間作息- -現在凌晨2點)
第二天醒后的修改:malloc那里sizeof改成了strlen,析構里面改成了delete[]p; 然后pinjie函式改成了char型,回傳a,,,但還是不行,現在運行不了了,提示觸發一個斷點,百度發現研究這個問題所需知識過多,,放棄,等再與其他人交流,
實驗九 繼承和派生的應用
撰寫順序表類,由順序表類派生出堆疊類,
看到這個題目一臉懵逼,,,線性表上課提過,是存盤資料的一片連續的空間,但堆疊表…??百度了半天依舊懵逼,然后懵逼的我看著懵逼的題敲出了懵逼的代碼,沒報錯就撤了 ,,,有大神的話還請指導一下,萬分感謝,
#include<iostream>
using namespace std;
class SqList
{
public:
int* pdate;
int top;
int size;
SqList()
{
top = -1;
size = 100;
pdate = new int[size];
}
~SqList()
{
top = -1;
for (int i = 0; i < size; i++)
pdate[i] = 0;
delete[]pdate;
}
};
class StackList :private SqList
{
public:
StackList()
{
top = -1;
}
StackList(int m)
{
pdate = new int[100];
top = m;
size = 100;
}
~StackList()
{
top = -1;
for (int i = 0; i < size; i++)
pdate[i] = 0;
delete[]pdate;
}
int gettop()
{
if (top == -1)
cout << "top==-1" << endl;
return top;
}
bool empty()
{
if (top == -1)
return true;
else
return false;
}
void tianjia(int x)
{
if (top == size - 1)
cout << "top==size-1";
else
pdate[top++] = x;
}
void daying()
{
if (top == -1)
{
cout << "top==-1";
return;
}
for (int i = 0; i < top; i++)
{
cout << pdate[i] << endl;
}
return;
}
};
實驗十 虛函式與多型性
撰寫多邊形類,具備每邊長度的資料成員和計算周長的函式成員、計算面積的純虛函式成員,由多邊形類派生出正多邊形類(非抽象類),
#include<iostream>
using namespace std;
class dbx //定義多邊形類
{
public:
int num; //邊數
int size_long; //邊長
virtual int zhouchang() = 0; //求周長的函式
dbx()
{
num = 100;
size_long = 100;
}
};
class zdbx :public dbx //派生,正多邊形
{
public:
zdbx(int x, int y)
{
dbx::num = x;
dbx::size_long = y;
}
int zhouchang() //正多邊形邊長,順便輸出了
{
cout << "該正多邊形的長度是:" << zdbx::num * zdbx::size_long << endl;
return 0; //隨便回傳一下,,void的話會報錯 //atFuRYh
}
};
int main()
{
zdbx a(3, 4);
a.zhouchang();
}
實驗十一 檔案操作
建立一個有若干個字串的文本檔案str.txt,形式如圖1.42所示,檔案用“End of String”字串結尾,計算出字串的個數,同時對這些字串進行排序,將排序的結果輸出至文本檔案strout.txt中,如圖1.43所示,

檔案讀取,基本沒講過的內容,,,百度自學外加借鑒同學,,參考此文:
https://blog.csdn.net/qq_34097715/article/details/79970860
代碼如下:
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream infile("C:\\Users\\76138\\Desktop\\str.txt"); //打開檔案
ofstream outfile("C:\\Users\\76138\\Desktop\\str_out.txt", ios::app); //輸出檔案
char string[100][30], temp[30];
if (!infile.is_open())
{ //此行代碼參考自百度
cout << "未成功打開檔案" << endl;
}
int i = 0;
infile.getline(string[i], 30);
while (strcmp(string[i], "end of string"))
{
i++;
infile.getline(string[i], 30);
}
int n = 0;
for (i; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++)
if (strcmp(string[j], string[j + 1]) > 0)
{
strcpy(temp, string[j]);
strcpy(string[j], string[j + 1]);
strcpy(string[j + 1], temp);
}
outfile << "字串個數:" << n << endl;
outfile << "排序后字串:" << endl;
for (int i = 0; i < n; i++)
outfile << string[i] << endl;
infile.close();
outfile.close();
return 0;
}
不過感覺這塊還是懵逼的,,,準備寒假再看看C+,
歷時半個多星期十幾個小時肝完了這個作業,最大感悟是學會了除錯…原來在學RE在IDA中用過幾次除錯,然后現在在VS繼續用了用感覺更順了哈哈,其次就是繼續認識到了“百度”的重要性…當然最重要的還是感慨要上課好好聽講啦…秦爺yyds,可惜我這學期的課走神無數錯過了很多精彩,,最后導致做起來的時候好多東西都似曾相識結果還得百度的去學,
第一次嘗試認真的寫一個博客,沒指望有什么人來看只是當做一個學習的記錄,大神莫嘲笑哈,
2020.1.4.16:22,距離1.7考試還有…兩三天,保佑自己不要掛科吧,哈哈!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/245210.html
標籤:其他
下一篇:2021-01-05
