1. 程式人生 > 其它 >c語言到c++從入門到入土

c語言到c++從入門到入土

\(\large C語言到C++從入門到入土\)

​ 孫培博 2022.4.11

1.基本介紹

2.例項

(1)特色寫法

(2) 過載運算子

(3)string

(4)algorithm庫

(5)STL

基本介紹

c是面向過程的,資料與演算法分開。它的重點在於演算法和資料結構。側重於計算機底層操作。 
c++是面向物件的,主要特點是類,封裝和繼承。與C的區別主要為 :類、繼承和多重繼承、運算子過載、類模板、C++標準庫、模板庫。
C程式的設計首要考慮的是如何通過一個過程,對輸入(或環境條件)進行運算處理得到輸出(或實現過程(事務)控制)。
C++,首要考慮的是如何構造一個物件模型,讓這個模型能夠契合與之對應的問題域,這樣就可以通過獲取物件的狀態資訊得到輸出或實現過程(事務)控制。


所以C與C++的最大區別在於它們的用於解決問題的思想方法不一樣。之所以說C++比C更先進,是因為“ 設計這個概念已經被融入到C++之中 

小總結:

1、首先C和C++在基礎語句上沒有太大區別。

2、往上一層,則是多出的語法,關鍵字。姑且可以認為是小特色。

語法的區別典型的標頭檔案的不同以及名稱空間的宣告。再如不易察覺的,像new delete等指標的封裝實現。

3、再往上,就和C相差越來越遠了,過載和虛擬函式的概念,可以認為是大特色。

一般說語言級別越高,程式設計師程式設計更方便,但編譯器就會越多出許多額外的工作。可以說C++編譯器就是勞模!經典的莫過於c++的過載和虛擬函式。這是和C完全不同的規定和機制,同名的函式你可以在C++程式碼中看到鋪天蓋地,各種操作符過載,各種虛擬函式宣告,各種指標和引用的轉換,讓很多剛從C跳過來的小白望而生畏。

4、再往上,就是完全獨立於C的概念,類,物件和繼承。

(在面嚮物件語言中類的概念很常見,但在C++也算是一個標籤了,人們認為這是C和C++的最大不同,這是可以理解的,因為程式碼整體上這是最明顯的區別。但不能認為這是“真正的區別”,這只是基於C的拓展。這裡有一個例項化的概念,物件是類的實體,而這個實體包含了各種變數和函式,有了類物件就有建構函式,解構函式,複製建構函式以及友元函式的概念…有的人可能會想到結構體,確實兩者有相似之處,但結構體卻不能有成員函式,只能用函式指標,沒有C++規範和方便。在實現上類才是物件程式設計的核心設計思想,它比結構體更能管理它的成員。有類就有許可權和繼承,什麼公有,私有,保護,單繼承,多繼承,虛繼承,父子類,基類派生類、、、單在繼承方面,就比C複雜了好多好多還多!)

5、再往上, 可以算接近“真正”的含義的區別了,那就是C++強大的獨立特性 ,支援正規化程式設計,如函式模板,模板類,怎麼也想不到可以用模板來重用程式碼,個人覺得這是C++較之C比較偉大的地方!C++還有異常機制,這也是C++的一個特性,還支援超程式設計,以及強大的STL標準庫、、、強大到那你懷疑人生,思考宇宙。。。

6、終極封頂!設計思想和應用場景的區別!

有一個很籠統的回答,就是C和C++的本質區別是面向過程和麵向物件。這種回答看似沒毛病,但是一看就知道水平不會有多高,應該是道聽途說的“主流”看法,忽悠外行的還可以。用過這兩門語言程式設計的人,不難體會,c可以實現面向過程,亦可實現類似的面向物件比如結構體封裝,但用法上沒有比真正有面向物件的C++高效和方便,只因為C++多了一個類的管理。而C++完全可以向下相容C,即可以面向過程,也可以面向物件,我們常說C++是一種半面向物件的語言,但它完全可以面向過程。高階的系統程式設計,多執行緒,資料結構等等C++也可以做到,只不過出於執行效率和記憶體佔用考慮,C的優勢使它趨向於底層,如核心驅動和作業系統,越精簡質量越高。對比C++,它更像是基於系統上的上層語言,可以做大型軟體,介面開發,遊戲開發等等等等。誠然,《C++ Primer Plus》中也說過,把C的繁雜的實現過程抽象成型別並且例項化來管理,是C++設計之初的動機,也就是OOP思想。使用者可以自定義型別,並且可以不斷往裡面新增和拓展,必須修改的時候不需要大改全域性,而只需要改區域性,這就是OOP的優勢之一。兩者的側重點會點不同,C更注重實現邏輯,C++更注重的是程式的整體設計,這就是常說的面向過程和麵向物件,其本質還是在其設計思想上,C++更加開放和自由,程式碼維護和管理更加高效。

綜上,我們不難看出,每一個設計細節都不是為了設計而設計,而是為了更好的的去程式設計而設計,而設計之後不一定在每個領域都佔有優勢,只能說設計者在設計過程中考慮的管理策略和應用場景不同!當然C++也因其複雜多樣和不斷迭代的標準遭人詬病,學習曲線陡峭。C入門不難,精通可能也不難,但是想精通C++,就是非常非常非常難!能用到什麼程度,就表明對它掌握程度。甚至可以做到隨意切換。用的多了,你甚至會認為這倆根本就不是同一門語言,又可以是同一門語言!就是那樣一種境界!所以真正的區別的回答肯定會因人而異,可能就是取決於使用的人有幾斤幾兩的區別了。

就是說,絕大多數時候用C++會更加方便。

例項

1.特色寫法

基本格式

#include <bits/stdc++.h>
using namespace std;
int main()
{
	return 0;
}

bool 和 const 常量

bool a,b;
a = false , a = 0;
b = true , b = 1;
const int p = 1e9+7;

結構體(結構體的型別名可以省去前面的struct)

#include <bits/stdc++.h>
struct node
{
	int x, y, z;
};

int main()
{
	node a;
	a.x = a.y = a.z = 1;
	return 0;
}


引用

#include <bits/stdc++.h>
void swap(int &a,int &b)
{
	int c = a; a = b; b = c;
}
int main()
{
	int a = 1, b = 2;
	swap(a, b);
	return 0;
}

指標動態記憶體分配和賦值及結構體的建構函式

#include <iostream>
using namespace std;
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x): val(x),left(NULL),right(NULL) {}
};
int main() {
    TreeNode *p = new TreeNode(3);
    cout<<(p->val)<<endl;
    return 0;
}

過載運算子

我們C++語言中已經給出的運算子(包括算數運算子和邏輯運算子)只是針對C++語言中已經給定的資料型別進行運算,假如我們想要對我們的自定義資料型別進行運算的話,則需要過載運算子,我們可以把過載運算子理解成對已有的運算子的一種重新定義。

//格式
<返回型別> operator <運算子符號>(<引數>)
{
	<定義>;
}

eg:對兩個結構體進行比較

struct node
{
    int id;
    double x,y;
}//定義結構體
bool operator <(const node &a,const node &b)
{
    return a.x<b.x && a.y<b.y;
}//過載運算子“<”
int main()
{
    node a, b;
    if(a < b) ...l; else ...
}

注意:

以下運算子不可過載:

關係運算符"."

成員指標運算子".*"

作用域運算子"::"

sizeof運算子

三目運算子"?:"

過載運算子限制在C++語言中已有的運算子範圍內的允許過載的運算子之中,不能建立新的運算子。

運算子過載實質上是函式過載。

string

在c++中把string單獨作為一個數據型別, 用來儲存處理字串

string常用用法粗略的總結

#include <string>


//建構函式
string s1(); // si = ""
string s2("Hello"); // s2 = "Hello"
string s3(4, 'K'); // s3 = "KKKK"
string s4("12345", 1, 3); //s4 = "234",即 "12345" 的子串(1, 3),從下標 1 開始,長度為 3 的子串

//賦值
string s1;
s1 = "Hello";  // s1 = "Hello"
s2 = 'K';  // s2 = "K"
cin >> s1 >> s2;

//長度
string s1 = "12345";
s1.size(); // 5
s1.length(); // 5

//比較
 /*  除了可以用 <、<=、==、!=、>=、> 運算子比較 string 物件外,string 類還有 compare 成員函式,可用於比較字串。compare 成員函式有以下返回值:

    小於 0 表示當前的字串小;
    等於 0 表示兩個字串相等;
    大於 0 表示另一個字串小。
*/
string s1("hello"), s2("hello, world");
int n = s1.compare(s2);

//子串
string s1 = "this is ok";
string s2 = s1.substr(2, 4); // s2 = "is i"
s2 = s1.substr(2); // s2 = "is is ok"
//交換
string s1("West”), s2("East");
s1.swap(s2); // s1 = "East",s2 = "West"

除此之外還有具體位置的比較、查詢子串字元、替換子串、刪除子串、插入子串、放stl裡、轉換成整形等功能。不在一一舉例。

algorithm

algorithm意為"演演算法",是C++的標準模版庫(STL)中最重要的標頭檔案之一,提供了大量基於迭代器的非成員模版函式,庫中的演算法主要分為4類:

非修改性順序操作(Non-modifying sequence operations)
可變順序操作(Mutating sequence operations)
排序和關係操作(Sorting and related operations)
C庫演算法(C library algorithms)

常用的

1.reverse

reverse(it,it2) 可以將陣列指標在[it,it2)之間的元素或容器的迭代器在[it,it2)範圍內的元素進行反轉。reverse(it,it2) 可以將陣列指標在[it,it2)之間的元素或容器的迭代器在[it,it2)範圍內的元素進行反轉。

int a[4];
reverse(a + 1, a + 5);

2.返回全排列:next_permutation(it,it2)返回兩個位置[it,it2)之間的字典序的下一個全排列並原地賦值;

#include <cstdio>
#include <algorithm>
using namespace std;
int main(){
    int a[3]={1,2,3};
    printf("%d %d %d\n",a[0],a[1],a[2]);
    while(next_permutation(a,a+3)){
        printf("%d %d %d\n",a[0],a[1],a[2]);
    }
    return 0;
}

sort() 函式的排序:可以對陣列元素和結構體陣列排序; 對容器排序只能對vector, string, deque進行

#include<stdio.h>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
bool cmp(int a,int b){
    return a>b;
}
int main()
{
	int  a[11];
	sort(a, a + 11);
	sort(a, a +11, cmp);
    return 0;
}

lower_bound(), upper_bound()

返回兩個位置之間的大於等於某個數的第一個位置

返回兩個位置之間的大於某個數的第一個位置

#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
    int a[10]={1,2,2,3,3,3,5,5,5,5};
    int pos1 = lower_bound(a,a+10,3)-a;
    int pos2 = upper_bound(a,a+10,3)-a;
    return 0;
}

當然還有其他的如max(a1, a2), min(a1, a2), max_element(a, a + n), min_element(a, a+ n);

stable_sort(), partial_sort(), count()等;

STL簡介

STL 是 C++ 標準程式庫的核心。STL 內的所有元件都由模板構成,其元素可以是任意型別。程式設計師通過選用恰當的群集類別呼叫其成員函式和演算法中的資料即可,但代價是 STL 晦澀難懂。

STL 元件主要包括容器,迭代器、演算法和仿函式。

容器

容器即用來儲存並管理某類物件的集合。

每一種容器都有其優點和缺點。為滿足程式的各種需求,STL 準備了多種容器型別,容器可以是 arrays 或是 linked lists,或者每個元素有特別的鍵值。

迭代器

迭代器用於在一個物件群集的元素上進行遍歷動作。物件群集可能是容器,也可能是容器的一部分。

迭代器的主要用途是為容器提供一組很小的公共介面。利用這個介面,某項操作可以行進至群集內的下一個元素。

每種容器都提供了各自的迭代器。迭代器瞭解該容器的內部結構,所以能夠正確行進。迭代器的介面和一般指標類似。

演算法

演算法用來處理群集內的元素,可以出於不同目的搜尋、排序、修改、使用那些元素。所有容器的迭代器都提供一致的介面,通過迭代器的協助,演算法程式可以用於任意容器。

仿函式

STL中大量運用了仿函式。仿函式具有泛型程式設計強大的威力,是純粹抽象概念的例證。

STL 的一個特性是將資料和操作分離。資料由容器類別加以管理,操作則由可定製的演算法定義。迭代器在兩者之間充當“粘合劑”,以使演算法可以和容器互動運作。

STL 的另一個特性即元件可以針對任意型別運作。“標準模板庫”這一名稱即表示“可接受任意型別”的模板,並且這些型別均可執行必要操作。

在 STL 中,容器又分為序列式容器和關聯式容器兩大類,而迭代器的功能主要是遍歷容器內全部或部分元素的物件。迭代器可劃分為 5 種類屬,這 5 種類屬歸屬兩種型別:雙向迭代器和隨機存取迭代器。

SIL 中提供的演算法包括搜尋、排序、複製、重新排序、修改、數值運算等。

目前,STL 中已經提供的容器主要如下:

  • vector :一種向量。
  • list :一個雙向連結串列容器,完成了標準 C++ 資料結構中連結串列的所有功能。
  • queue :一種佇列容器,完成了標準 C++ 資料結構中佇列的所有功能。
  • stack :一種棧容器,完成了標準 C++ 資料結構中棧的所有功能。
  • deque :雙端佇列容器,完成了標準 C++ 資料結構中棧的所有功能。
  • priority_queue :一種按值排序的佇列容器。
  • set :一種集合容器。
  • multiset :一種允許出現重複元素的集合容器。
  • map <key, val>:一種關聯陣列容器。
  • multimap <key, val>:一種允許出現重複 key 值的關聯陣列容器。

常見的部分演算法如下:

size()

begin()

end()

empty()

find()

count()

pop()

push()

erase()

謝謝