\(\large C语言到C++从入门到入土\)
1.基本介绍
2.实例
(1)特色写法
(2) 重载运算符
(3)string
(4)algorithm库
(5)STL
基本介绍
c是面向过程的,数据与算法分开。它的重点在于算法和数据结构。侧重于计算机底层操作。
c++是面向对象的,主要特点是类,封装和继承。与C的区别主要为 :类、继承和多重继承、运算符重载、类模板、C++标准库、模板库。
C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。
C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。
所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中
小总结:
\(\color{red}{1、首先C和C++在基础语句上没有太大区别。}\)
\(\color{red}{2、往上一层,则是多出的语法,关键字。姑且可以认为是小特色。}\)
语法的区别典型的头文件的不同以及名称空间的声明。再如不易察觉的,像new delete等指针的封装实现。
\(\color{red}{3、再往上,就和C相差越来越远了,重载和虚函数的概念,可以认为是大特色。}\)
一般说语言级别越高,程序员编程更方便,但编译器就会越多出许多额外的工作。可以说C++编译器就是劳模!经典的莫过于c++的重载和虚函数。这是和C完全不同的规定和机制,同名的函数你可以在C++代码中看到铺天盖地,各种操作符重载,各种虚函数声明,各种指针和引用的转换,让很多刚从C跳过来的小白望而生畏。
\(\color{red}{4、再往上,就是完全独立于C的概念,类,对象和继承。}\)
(在面向对象语言中类的概念很常见,但在C++也算是一个标签了,人们认为这是C和C++的最大不同,这是可以理解的,因为代码整体上这是最明显的区别。但不能认为这是“真正的区别”,这只是基于C的拓展。这里有一个实例化的概念,对象是类的实体,而这个实体包含了各种变量和函数,有了类对象就有构造函数,析构函数,复制构造函数以及友元函数的概念…有的人可能会想到结构体,确实两者有相似之处,但结构体却不能有成员函数,只能用函数指针,没有C++规范和方便。在实现上类才是对象编程的核心设计思想,它比结构体更能管理它的成员。有类就有权限和继承,什么公有,私有,保护,单继承,多继承,虚继承,父子类,基类派生类、、、单在继承方面,就比C复杂了好多好多还多!)
\(\color{red}{5、再往上, 可以算接近“真正”的含义的区别了,那就是C++强大的独立特性}\)
支持范式编程,如函数模板,模板类,怎么也想不到可以用模板来重用代码,个人觉得这是C++较之C比较伟大的地方!C++还有异常机制,这也是C++的一个特性,还支持元编程,以及强大的STL标准库、、、强大到那你怀疑人生,思考宇宙。。。
\(\color{red}{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()