【C++学习之路】第二章——C++基础语法学习(1)之黑客攻击系统
2 C++基礎語法學習(1)之黑客攻擊系統(tǒng)
遵循原則:從實戰(zhàn)中學習知識
法律聲明:本系統(tǒng)僅能攻擊自己搭建的網站,作為學習使用,不會觸犯法律
time:2020.01.20
author:姜海天
IDE:VS C++2010 Express
2.0 VS C++ 2010 Express的使用
2.1 子項目一:功能菜單
2.1.0 本節(jié)大綱與知識清單
2.1.0.1 大綱
大綱是最重要的,一定要仔細閱讀,不可忽略!
- 2.1.1~2.1.7是項目設計、實現、測試與優(yōu)化部分,直接采用了數據結構知識,先不用管這是什么,先接受他的標題與設計過程。
- 2.1.8及其后面的小節(jié)是知識點講解部分
2.1.0.2 知識清單
本子項目涉及到的知識點如下
- C++的知識
- 數據結構的知識
2.1.1 項目需求
設計一個功能菜單,實現黑客攻擊系統(tǒng)基本信息的輸出
要求的必要信息: 實現網站404攻擊,網站篡改攻擊,DNS攻擊,服務器重啟攻擊,且記錄下來攻擊記錄
2.1.2 需求分析&整體架構設計
| 設計一個能夠輸出信息的菜單 |
2.1.3 ADT模型構建(抽象)
| 1. 網站404攻擊 |
| 2. 網站篡改攻擊 |
| 3. DNS攻擊 |
| 4. 服務器重啟攻擊 |
| 5. 查看攻擊記錄 |
2.1.4 實現抽象
本項目過于簡單,沒有這一項
2.1.5 實現
對于初學者并不知道我在干什么,沒有關系,請先接受這些內容,后面的小節(jié)會詳細講解這些內容。
2.1.6 單元測試
這里只有一個ADT模型的實現,并且由于是初學,所以只是借用了軟件工程中單元測試的名字,并不是標準的單元測試,只是單純的驗證程序結果的正確性
顯然,程序運行結果是正確的,并且是符合要求的。
2.1.7 結果評價與程序優(yōu)化
2.1.7.1 正確性
顯然,程序的結果是正確的
2.1.7.2 效率
對于此程序,效率是不夠高的,并且有一些冗雜的沒有必要的代碼。
思考:什么是高效率的程序?
在計算機工程中,需要綜合考量時間復雜度和空間復雜度。
時間復雜度:程序耗時多少
空間復雜度:占用計算機內存多少
2.1.7.3 程序優(yōu)化
改進后的高效率的程序應該是這樣的
#include <iostream> #include <Windows.h> using std::cout; using std::endl;int main() {cout << "1. 網站404攻擊" << endl;cout << "2. 網站篡改攻擊" << endl;cout << "3. DNS攻擊" << endl;cout << "4. 服務器重啟攻擊" << endl;cout << "5. 查看攻擊記錄" << endl;system("pause");return 0; }并且,經過單元測試后,沒有問題。
不過對于初級的簡單的項目來說,我們并不需要過多關注效率問題,而要關注于學習知識,因此,將上述代碼中的
using std::cout; using std::endl;改為
using namespace std;好吧到目前位置,你可能根本不知道我在說什么,沒有關系,下面的小節(jié)中,我將會一點點詳細講給你!
2.1.8 程序的創(chuàng)建過程
本內容適合于初學者,介紹了程序創(chuàng)建的簡易過程,內部細節(jié)暫時忽略,例如匯編過程等,并沒有詳細進行解釋和展開,只需要了解即可。
2.1.9 頭文件
我們先來放上代碼,這樣你就不需要再去前面翻閱了。
#include <iostream> #include <Windows.h> using namespace std;int main() {cout << "1. 網站404攻擊" << endl;cout << "2. 網站篡改攻擊" << endl;cout << "3. DNS攻擊" << endl;cout << "4. 服務器重啟攻擊" << endl;cout << "5. 查看攻擊記錄" << endl;system("pause");return 0; }2.1.9.1 頭文件的格式
最上面的兩行就是頭文件
#include <iostream> #include <Windows.h>頭文件的書寫有兩種形式
原始形式:
#include <頭文件名稱>
#include "頭文件名稱"
- 形式一:使用英文狀態(tài)在的一對兒尖括號(<、>)
- 形式二:使用英文狀態(tài)下的一對兒雙引號("、")
思考:兩種格式的區(qū)別是什么?
看此答案前,我建議你先看完后面講解頭文件的作用以及庫文件的小節(jié)。
先來一張表格,再詳細解釋
| < > | 編譯器默認目錄 | 找不到相應頭文件則編譯失敗 | 使用C++標準庫 |
| " " | 程序當前目錄 | 找不到就去默認目錄找,再找不到則編譯失敗 | 使用用戶自定義頭文件 |
對于使用尖括號< >:代表預處理器在替換頭文件部分時候,查找頭文件代碼的位置是直接從編譯器的默認目錄查找的。
并且要知道的是,編譯器的默認目錄,根據編譯器、IDE等的不同,它的位置也都是不一樣的,我們不需要關心它具體在哪里。
對于使用雙引號" ":代表預處理器在替換頭文件部分的時候,查找頭文件代碼的位置,先從當前程序目錄下查找,找到了就替換;如果沒有找到,則再從編譯器默認目錄下查找,如果還找不到,則會編譯失敗。
2.1.9.1.1 查看學習C++標準庫代碼
VS C++2010 Express中,可以直接看到編譯器的默認目錄,然后我們可以找到他們看一看。
我們找一下這個路徑,這也就是C++標準庫了
這里的文件都可以使用VS C++2010打開,我們可以先嘗試打開iostream看一下
也許你看不懂這些是什么,沒有關系,隨著知識的深入,這些內容你會明白的,不過你至少要明白的是,iostream頭文件里面也是一堆代碼,是的目前來說,明白這些就足夠了,在2.1.9.3小節(jié)中會用的到這個知識。
補充知識:std命名空間源代碼的位置
File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\new.h" 2 occurrences found on 2 lines52: namespace std {75: namespace std { File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\nothrow0.cpp" 1 occurrences found on 1 lines25: namespace std { File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\stddef.h" 1 occurrences found on 1 lines38: namespace std { typedef decltype(__nullptr) nullptr_t; } File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\yvals.h" 2 occurrences found on 2 lines554: #define _STD_BEGIN namespace std {566: #define _C_STD_BEGIN namespace std { /* only if *.c compiled as C++ */ File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\include\new.h" 2 occurrences found on 2 lines42: namespace std {64: namespace std { File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\include\stddef.h" 1 occurrences found on 1 lines38: namespace std { typedef decltype(__nullptr) nullptr_t; } File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\include\yvals.h" 2 occurrences found on 2 lines488: #define _STD_BEGIN namespace std {500: #define _C_STD_BEGIN namespace std { /* only if *.c compiled as C++ */| C++舊式風格 | 擴展名為.h | iostream.h | C++98標準已經拋棄它 |
| C舊式風格 | 擴展名為.h | math.h | C/C++中可以直接使用 |
| C++新式風格 | 無擴展名 | iostream | C++中可以使用,需要引入namespace std使用 |
| 轉換為C++新式風格的C | 加上前綴c,無擴展名 | cmath | C++中可以使用,既可以按照C舊式風格直接使用,也可以引入namespace std使用 |
備注:此處參考了《C++ Primer Plus》中的表2.1
在C++風格的代碼中,我們通常都會使用無擴展名的頭文件,例如iostream和cmath,并且C++提倡引入命名空間(后面會解釋這個),也就是C++風格的代碼應該是這樣的:
#include <iostream> //而不是 iostream.h #include <cstring> //而不是 string.h #include <cmath> //而不是 math.h #include <cstdio> //而不是 stdio.h using namespace std;值得一提的是,表格中的規(guī)則,我建議你掌握C++新風格的使用,至于舊風格,看到的時候能夠認識即可
也就是,你只需要掌握這些
| C++新式風格 | 無擴展名 | iostream | C++中在namespace std中使用 |
| 轉換為C++風格的C | 無擴展名,前綴為c | cstdio | C++中直接使用或者在namespace std中使用 |
并且能夠認識這些
| C舊式風格 | 以.h結尾 | stdio.h | C++中直接使用 |
不過也有一些特例,例如,Windows.h并沒有cWindows這種寫法,這涉及到Windows編程,先不用管它,你暫時只需要知道下面這兩條即可。
#include <Windows.h>//頭文件 system("pause"); //暫停功能,也可以寫成cin.get();順便說一句,在常用的頭文件中,有幾個頭文件很令人迷惑, 需要重點解釋一下,它們是
- string
- string.h
- cstring
其中,string是C++新增的頭文件,與后兩者一點關系都沒有,只是長得像,而string.h與cstring是一類頭文件,分別是舊式風格與轉換后的風格.
并且還要注意的是,string數據類型,只有在string頭文件中才有,C語言是沒有這種數據類型的。
下面用一個表格來描述。
| C++新式風格 | string | 能,并且必須使用std空間 |
| 轉換為C++后的C | cstring | 不能,因為C語言沒有string類型 |
| C舊式風格 | string.h | 不能,因為C語言沒有string類型 |
以上說了這么多,是幫助你深入理解頭文件的使用規(guī)則和頭文件名稱約定,下面將會給出,我們在編程的時候應該如何使用它們。
這一點非常重要,很多的書籍給出了很多的原理,但是不告訴我們實戰(zhàn)的時候應該怎么寫,應該用在哪里,最后讓人一頭霧水,難以快速掌握知識。
好的目前你已經知道這些寫法了,但是還會有疑惑,就是,頭文件有啥什么用?namespace std是什么?后面的小節(jié)會講解,請先接受這些內容,學習了后面的章節(jié)(頭文件的作用和命名空間的使用)后,再回看以上內容。
思考:這幾種寫法的區(qū)別是什么?
我建議你看懂上面講述的內容后,再看思考此問題。
我先抽象出三種寫法核心內容,再為你逐步拆解講解,請注意,下面的代碼只是一部分,不是完整的程序。
- 形式1:
- 形式2:
- 形式3
對于形式1,使用了完整的命名空間std,這樣后面的程序就可以直接使用std中的任意內容,而不需要加上 std:: 前綴。
但是如果你在接下來的代碼中,只是使用了cout命令,并且使用了例如100個之多,顯然沒有必要使用全部的命名空間,這很浪費,因此,可以使用形式2中的形式,單獨使用命名空間中的某一項指令。
如果你只使用了一個cout命令,形式2也是浪費的,因此可以使用形式3。
用一張表格來概括一下:
| iostream | using namespace std; | cout、endl | 不關注效率時(初學者)、大量使用std空間內容時 | 不建議 |
| iostream | using std::cout | cout、std::endl | 大量使用cout,但很少使用endl時 | 建議 |
| iostream | 不使用 | std::cout、std::endl | cout和endl使用都很少時 | 建議 |
說明一下,我們后續(xù)會詳細講解命名空間,之所以不建議使用第一種,是為了防止引發(fā)不必要的重名沖突,先了解一下即可,后續(xù)會深入講解。
附上一個拓展學習鏈接:std命名空間
2.1.9.2 頭文件的作用
關于頭文件的格式,大家應該很清楚了,不過應該也有一些不太清楚的地方,下面我來講解頭文件的作用,然后,請你回看上一小節(jié),并結合本節(jié)內容,重新進行理解。
如下程序是正確的,能夠編譯成功
#include <iostream>int main() {std::cout << "你好!" << std::endl;return 0; }而如下程序,缺少了頭文件,不能編譯成功
int main() {std::cout << "你好!" << std::endl;return 0; }啟動VS C++2010編譯后,會報錯
此時,我們稱編譯器不能識別cout和endl,不能識別的原因:
- 直接原因:沒有添加iostream頭文件
- 根本原因:編譯器不能識別cout和endl指令
思考:為什么加上頭文件,編譯器就能夠識別這兩個指令了?
很明顯,就是因為加上了頭文件iostream。
因此,頭文件的作用,就是幫助編譯器識別相應的指令。
但是這樣描述并不專業(yè),從專業(yè)的角度來說,頭文件iostream本身能夠實現cout指令,在程序編譯過程中,預處理器將iostream文件包含了進來,因此程序可以使用cout,請看下一小節(jié)后,再來回看這一段內容,這樣你就能夠理解了。
2.1.9.3 頭文件的預處理過程
對于程序員寫好的代碼,執(zhí)行編譯之后,會在編譯過程進行之前,編譯器會調用預處理器,進行預處理過程,請看下面的流程圖。
執(zhí)行編譯頭文件部分被替換為頭文件代碼源代碼編譯器調用預處理器執(zhí)行編譯過程也就是說,預處理器將下面這段內容
#include <iostream>替換為了iostream文件中的代碼,也就是這些:
這時候,我們稱預處理器將頭文件內容包含進了該程序中。
還記得2.1.9.1.1小節(jié)學到的內容嗎,如果忘記了請你回看一下,然后再來理解這一小節(jié)。
不過請注意,這種替換并不改變源代碼文件,是一種隱性替換,不是真正的替換掉了,這種說法只是為了方便你理解這件事。
當然,你也不妨理解為添加頭文件,就相當于添加了頭文件中的代碼,頭文件只是一個“代號”。因此,該源程序文件能夠使用頭文件中的功能。
2.1.9.4 頭文件的使用
不管是單文件還是多文件,頭文件一定要加在最前面,因為編譯的順序以及程序的執(zhí)行順序都是自上而下的,如果寫成下面這樣
std::cout << "你好!"; #include <iostream>這樣的程序是不能執(zhí)行的,一般情況下都是后面的內容可以調用前面的內容(不是絕對的,學到后面你會明白),因此來說:頭文件一定要寫在最前面,不過后面學習到多文件的時候,你會遇到這樣的命令
#pragma once我先告訴你這代表該文件只能被編譯一次,頭文件需要在它的下面寫。
2.1.9.5 頭文件在項目中的使用方法
我先給出你目前水平的簡單使用方法,再給出你專業(yè)的方法,專業(yè)的方法,我建議你學會了多文件的使用后再來回看。
- 簡單的方法
這是基礎款,必須要有的頭文件。
- 專業(yè)的方法
- 根據設計好的架構,建立好多個頭文件和源程序文件,每一個源程序文件代表一個功能模塊,其中一個是包含main函數的文件
- 然后設計好頭文件,注意加上#pragma once
- 每一個源程序文件,都要遵循上面說的簡單的方法來添加頭文件
- 先設計好模塊文件,最后編輯包含main函數的文件,它會調用剛才編輯好的其他模塊文件。
對于專業(yè)的方法,請掌握多文件之后,再來回看。
總結
以上是生活随笔為你收集整理的【C++学习之路】第二章——C++基础语法学习(1)之黑客攻击系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宏碁(acer)D101E投影机怎么样,
- 下一篇: 到窑湾之龙鼎风云剧情介绍