关键词理解
inline
#include <stdio.h>
//函数定义为inline即:内联函数
inline char* dbtest(int a)
{
return (i % 2 > 0) ? "奇" : "偶";
}
int main()
{
int i = 0;
for (i=1; i < 100; i++)
{
printf("i:%d 奇偶性:%s /n", i, dbtest(i));
}
}
其实在内部的工作就是在每个for循环的内部任何调用dbtest(i)的地方都换成了(i%2>0)?“奇”:"偶"这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。
如下风格的函数Foo 不能成为内联函数:
inline void Foo(int x, int y); // inline 仅与函数声明放在一起
void Foo(int x, int y)
{
}
而如下风格的函数Foo 则成为内联函数:
void Foo(int x, int y);
inline void Foo(int x, int y) // inline 与函数定义体放在一起
{
}
operator
operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名。
A: 操作符重载实现为类成员函数
class person{
private:
int age;
public:
person(int a){
this->age=a;
}
inline bool operator == (const person &ps) const;
};
inline bool person::operator==(const person &ps) const
{
if (this->age==ps.age)
return true;
return false;
}
#include
using namespace std;
int main()
{
person p1(10);
person p2(20);
if(p1==p2) cout<<”the age is equal!”< return 0;
}
这里,因为operator 是class person的一个成员函数,所以对象p1,p2都可以调用该函数,上面的if语句中,相当于p1调用函数,把p2作为该函数的一个参数传递给该函数,从而实现了两个对象的比较。
B:操作符重载实现为非类成员函数(全局函数)
对于全局重载操作符,代表左操作数的参数必须被显式指定。例如:
#include
#include
using namespace std;
class person
{
public:
int age;
public:
};
bool operator==(person const &p1 ,person const & p2)
//满足要求,做操作数的类型被显示指定
{
if(p1.age==p2.age)
return true;
return false;
}
int main()
{
person rose;
person jack;
rose.age=18;
jack.age=23;
if(rose==jack)
cout<<"ok"< return 0;
}
考试题目中出现的operator
struct Record {
int y;
int res;
Record(int _y, int _res) : y(_y), res(_res) {}
//重载操作符 与运算符一起使用,表示一个运算符函数
//理解时 应该把operator <
bool operator < (const Record &rhs) const {
return y < rhs.y;
}
};
vector
1. 介绍向量
vector 容器与数组相比其优点在于它能够根据需要随时自动调整自身的大小以便容下所要放入的元素。此外, vector 也提供了许多的方法来对自身进行操作。
2. 向量的声明和初始化
vector<int> a ; //声明一个int型向量a
vector<int> a(10) ; //声明一个初始大小为10的向量
vector<int> a(10, 1) ; //声明一个初始大小为10且初始值都为1的向量
vector<int> b(a) ; //声明并用向量a初始化向量b
vector<int> b(a.begin(), a.begin()+3) ; //将a向量中从第0个到第2个(共3个)作为向量b的初始值
除此之外, 还可以直接使用数组来初始化向量:
int n[] = {1, 2, 3, 4, 5} ;
vector<int> a(n, n+5) ; //将数组n的前5个元素作为向量a的初值
vector<int> a(&n[1], &n[4]) ; //将n[1] - n[4]范围内的元素作为向量a的初值
3. 元素的输入及访问
元素的输入和访问可以像操作普通的数组那样, 用cin>>进行输入, cout<<a[n]这样进行输出:
#include<iostream>
#include<vector>
using namespace std ;
int main()
{
vector<int> a(10, 0) ; //大小为10初值为0的向量a
//对其中部分元素进行输入
cin >>a[2] ;
cin >>a[5] ;
cin >>a[6] ;
//全部输出
int i ;
for(i=0; i<a.size(); i++)
cout<<a[i]<<" " ;
return 0 ;
}
(a.begin(), a.end())则表示起始元素和最后一个元素之外的元素位置。
向量元素的位置便成为遍历器, 同时, 向量元素的位置也是一种数据类型, 在向量中遍历器的类型为: vector::iterator。 遍历器不但表示元素位置, 还可以再容器中前后移动。
在上例中讲元素全部输出部分的代码就可以改写为:
//全部输出
vector<int>::iterator t ;
for(t=a.begin(); t!=a.end(); t++)
cout<<*t<<" " ;
*t 为指针的间接访问形式, 意思是访问t所指向的元素值。
4. 向量的基本操作
1>. a.size() //获取向量中的元素个数
2>. a.empty() //判断向量是否为空
3>. a.clear() //清空向量中的元素
4>. 复制
a = b ; //将b向量复制到a向量中
5>. 比较
保持 ==、!=、>、>=、<、<= 的惯有含义 ;
如: a == b ; //a向量与b向量比较, 相等则返回1
6>. 插入 - insert
①、 a.insert(a.begin(), 1000); //将1000插入到向量a的起始位置前
②、 a.insert(a.begin(), 3, 1000) ; //将1000分别插入到向量元素位置的0-2处(共3个元素)
③、 vector<int> a(5, 1) ;
vector<int> b(10) ;
b.insert(b.begin(), a.begin(), a.end()) ; //将a.begin(), a.end()之间的全部元素插入到b.begin()前
7>. 删除 - erase
①、 b.erase(b.begin()) ; //将起始位置的元素删除
②、 b.erase(b.begin(), b.begin()+3) ; //将(b.begin(), b.begin()+3)之间的元素删除
8>. 交换 - swap
b.swap(a) ; //a向量与b向量进行交换
5. 二维向量
#include<iostream>
#include<vector>
using namespace std ;
int main()
{
vector< vector<int> > b(10, vector<int>(5, 0)) ;
//对部分数据进行输入
cin>>b[1][1] ;
cin>>b[2][2] ;
cin>>b[3][3];
//全部输出
int m, n ;
for(m=0; m<b.size(); m++) //b.size()获取行向量的大小
{
for(n=0; n<b[m].size(); n++) //获取向量中具体每个向量的大小
cout<<b[m][n]<<" " ;
cout<<"\n" ;
}
return 0;
}
6. 向量的扩展操作
c.back() // 传回最后一个数据,不检查这个数据是否存在。
c.begin() // 传回迭代器中的第一个数据地址。
c.capacity() // 返回容器中数据个数。
c.clear() // 移除容器中所有数据。
c.empty() // 判断容器是否为空。
c.end() // 指向迭代器中末端元素的下一个,指向一个不存在元素。
c.erase(pos) // 删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end) //删除[beg,end)区间的数据,传回下一个数据的位置。
c.front() // 传回第一个数据。
c.insert(pos,elem) // 在pos位置插入一个elem拷贝,传回新数据位置。
c.insert(pos,n,elem) // 在pos位置插入n个elem数据。无返回值。
c.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据。无返回值。
c.max_size() // 返回容器中最大数据的数量。
c.pop_back() // 删除最后一个数据。
c.push_back(elem) // 在尾部加入一个数据。
c.rbegin() // 传回一个逆向队列的第一个数据。
c.rend() // 传回一个逆向队列的最后一个数据的下一个位置。
c.resize(num) // 重新指定队列的长度。
c.reserve() // 保留适当的容量。
c.size() // 返回容器中实际数据的个数。
c1.swap(c2)
swap(c1,c2) // 将c1和c2元素互换。同上操作。
operator[] // 返回容器中指定位置的一个引用。
c++中各种常用的库
cmath:
开根号:pow
#include<iostream>
#include<cmath>
using namespace std;
int main(){
double x=8;
cout<<pow(x,1.0/3)<<endl;
return 0;
}
输出:
2
反三角函数:
- arcsin用asin
- arccos用acos
- arctan用atan
#include<iostream>
#include<cmath>
using namespace std;
int main(){
cout<<asin(1)<<endl;
cout<<acos(0)<<endl;
cout<<atan(1)<<endl;
return 0;
}
输出:
1.5708
1.5708
0.785398
包含 pow、exp、log2、log、log10 等数学函数。
iomanip:
输出时保留小数:
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
double x=3.1415926;
cout<<fixed<<setprecision(3)<<x<<endl;
return 0;
}
输出:
3.142
algorithm
包含了常用的 max、min、sort、swap、reverse。
cctype
包含 isalnum、isalpha、islower、isupper、isdigit、tolower、toupper 等字符处理方法。
climits
包含 int、long、long long 等类型的最大最小值 INT_MAX、INT_MIN、LONG_MAX、LONG_MIN、LLONG_MAX、LLONG_MIN。
cstdlib
包含 rand() 随机数生成器。
取 [a, b]之间的均匀分布随机数:
number = (rand()%(b - a + 1)) + a;
取 [a, b)之间的均匀分布随机数:
number = (rand()%(b - a)) + a;
取 [0, 1] 之间的随机浮点数:
number = rand() / double(RAND_MAX)
functional
包含 less、greater、less_equal、greater_equal 等比较函数,可以在 sort、priority_queue 中使用。
queue
包含了 queue 和 priority_queue。
一般来说,STL 中的容器名和适配器名就是头文件名,如 vector、stack、list,但优先级队列例外。
sstream
包含了 stringsteam,从字符流中读取字符串。
【C++】以逗号为分隔符读取字符串
utility
包含 pair 和 make_pair。
References
C++ rand 与 srand 的用法 – playbar
vector
#include<vector>