`
nightkidzxc
  • 浏览: 10984 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

C++学习笔记

 
阅读更多
std就是C++的标准库 就是传说中的STL standard template libary
其中的iostream string vector等都是STL中定义的
标准库中的用<>来include 自己写的用" "引用


.是成员操作符 对象名.类函数名


::是作用域操作符 命名空间::类


想一直让输入值:while(cin>>value)


变量命名习惯:
变量都用小写命名 需要多个单词解释的时候用 _ 或者后面一个词第一个字母大写 textSize或者 text_size


初始化的两种方式
复制初始化:int i=1024;
直接初始化: int i(1024);


内置类型变量是否自动初始化决定于所在的位置:
如果在函数体外定义,默认初始化为0
如果在函数体内定义,不会自动初始化


extern
非const的变量默认都是extern,即可以被外部文件通过extern int i来调用。
而const的常量要在外部调用必须在本文件中显示声明extern const PI;才可以被外部调用


typedef
typedef double price; //就是给double类型起一个别名price


引用&
int x=5;
int &a=x; //引用就是把新的变量指向引用变量,之后对a的所有操作都跟直接对x操作一样


枚举用法
enum direction{north=1,south,east,west};
direction d1=north;
direction d2=2;


类的声明
class Sales_item
{
public:
...
private:
std::string isbn;
unsigned sales;
}; //这里要加分号 ★!!!★




类的数据成员只能通过构造函数进行初始化,不能直接初始化 ★!!!★




定义类在一个头文件中,被需要的文件引用
因为要被多个文件引用,所以注意不应该含有 变量或函数的 定义 可以有声明


头文件保护符避免了头文件在一个文件中多次被引用
#ifndef SALESITEM_H
#define SALESITEM_H
写类定义什么的
#endif


友元类
允许对其非公有成员访问授予给一个函数或者类。
friend开头,只能在类内部声明
friend class Window_mgr;
friend Window_mgr& Window_mgr::relocate(Window_mgr::index.Window_mgr::index,Screen&);






system("pause") 需要引用 cstdlib


引用命名空间时候可以这样using std::string;using std::cout;等


getline来读取一行
string line;
while(getline(cin,line))


string s;
s.zise()返回的是一个string::size_type类型的,不要把size返回值赋给一个int变量
s[i] 定义索引来取的时候i最好也是size_type的类型


头文件引用时候尽量用#include <cmath> 而不是<math.h>


#include <vector>
vector是一个类模板,使用模板可以编写一个类定义或函数定义,而用于多个不同的类型
vector<int> a;vector<myClass> b;
vector不是一个数据类型 vector<int> 是一个数据类型
几种初始化:
vector<Type> v1; //默认v1为空
vector<Type> v2(v1);
vector<Type> v3(n,i); //包含n个值为i的元素
vector<Type> v4(n);


v1.push_back(x);
v1.insert(v1.begin()+2,5);
v1.erase(v1.begin()+1,v1.begin()+3);//删除v1中第2个到第4个元素
v1.clear();//清空
v1.empty();//是不是空的?
v.size();
reverse(v1.begin(),v1.end());


vector操作效率较高的是先定义一个空的vector然后再动态的添加元素


不进行值的初始化 vector会调用默认的构造函数初始化(除非没有默认构造函数,只有自定义的构造函数,此时必须提供元素的个数及初值)


size_type的类型是vector<int> 而不是vector 所以定义时 vector<int>::size_type


C++程序员习惯在写for时用 != 而不是 <
通过下表操作对vector里的元素赋值,不会添加出新的元素(数量不会加)


迭代器对所有容器都支持,但下标操作不是所有容器都支持
各种容器都定义了 各种容器 自己的 iterator类型


vector<int> ivec;
vector<int>::iterator iter=ivec.begin(); //begin()是一个函数,如果容器不为空,返回第一个值
end()也是一个函数,返回最后一个值的下一个,即end()指向一个不存在的元素,如果vector空,end和begin返回的迭代器相同,只是起一个哨兵的作用,代表已经处理完了所有的vector数据
*iter=0; 此时*为解引用操作符 *iter代表里面某个下标的值 *iter++代表往后渐进


vector<int> v1(9,1); //声明一个v1 里面有9个元素 初始都为1
for(vector<int>::iterator iter=v1.begin();iter!=v1.end();iter++) //实现了把每个元素都变成0
*iter=0;


for(vector<int>::const_iterator iter=v1.begin();iter!=v1.end();iter++)//const_iterator类型不会改变值,只能读取
cout<<*iter<<endl;


iter +n -n会产生新的游标
两个游标相减会产生一个difference_type类型的值(这个也是vector里定义的,类似于size_type类型)


vector<int>::iterator mid=v1.begin()+v1.size()/2;


任何改变vector长度的操作都会使已存在的迭代器失效,如push_back之后就不能信赖vector迭代器的值了












bitset类来简化类集的处理
#include <bitset>
using std::bitset;
初始化
bitset<32> bit1; //32个位的bitset对象 记住 灵活定义的初始化只能通过str实现,不能直接=
比如
bitset<16> bit2(0xffff);


string str("1100");
bitset<32> bit3(str); //此时的bit3为 28个0 后面是1100


bitset中的位处理
b.any();//是否存在为1的二进制
b.none();//不存在为1的位?
b.count();//为1的位的个数
b.size();//
b[pos];//
b.test(pos);//为1么?
b.set();//都设置成1
b.set(pos);//某个位置设置成1
b.reset();//都设置成0
b.reset(pos);//某位置成0
b.flip();//反转
b.flip(pos);//某位置反转
b.to_ulong();//转化成一个十进制整数
os<<b;//流入某个输出流


对string对象中字符的处理 #include <cctype>
isalnum(c)//是否为字母或数字
isalpha(c)// 是否为字母
isdigit(c)//是否为数字
islower(c)//是否为小写
isupper(c)
tolower(c)
toupper(c)


string s1;
s1.insert(s1.begin(),'p');
s1.erase(s1.begin(),s1.end());
s1.length();
s1.empty();
s1.replace(2,4,"mygod");//从第二个字符开始(包括),再加上后面4个字符替换为"mygod"
s1.find("ahaha");//在s1中查找ahaha,找到返回第一次出现的下标
reverse(s1.begin(),s1.end());//需要#include <algorithm>


string对象与字符数组互操作
string s;
char ss[100];


scanf("&s",&ss);//string可以直接用字符数组赋值
s=ss;


printf(s.c_str());//用string.c_str()转化为字符数组


按格式分解字符串
string s1,s2,s3;
char sa[100],sb[100],sc[100];
sscanf("abc 123 pc","%s %s %s",sa,sb,sc);
s1=sa;s2=sb;s3=sc;//这样就把一个字符串按格式分解开来


int a,b,c;
sscanf("1 2 3","%d %d %d",&a,&b,&c);//此时是数字格式,要传递指针地址来改变变量的值


int x,y,z;
sscanf("4,5&^1","%d,%d&^%d",&x,&y,&z);//按照字符串的格式来分解


通过字符流转化
把数值转化为string
string convertToString(double x)
{
ostringstream o;
if(o<<x)
return o.str();
return "conversion error";
}
把string转化为数值
double convertFromString(const string &s)
{
istringstream i(s);
double x;
if(i>>x)
return x;
return 0.0;
}








关联容器set
s.insert(5);
s.erase(5);
s.size();
s.find(5);//返回迭代器的位置




#include <set>
int main()
{
set<int> s;//定义一个set
s.insert(8);//插入一个元素
s.insert(1);
s.insert(12);
s.insert(8);//重复插入不生效
set<int> iterator it;
//set<int> reverse_interator rit//反向迭代器
//for(rit=s.rbegin();it!=s.rend();rit++)
for(it=s.begin();it!=s.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
//s.erase(6);//删除键值为6的元素
return 0;
}


自定义myComp
struct myComp //从大到小
{
myComp()(const int &a,const int &b)
{
if(a!=b)
return a>b;
else
return a>b;
}
};


set<int,myComp>::iterator it;






multiset允许插入重复键值的点
也有erase find方法


map容器的数据元素由一个键值和一个映照数据组成
#include <map>
map<string,float> m;
插入元素
m["JACK"]=90.3;
m["Bomi"]=43.2;
m["Kate"]=23.3;
m.insert(pair<string,float>("Zoe",76.3))
map<string,float>::iterator it;
for(it=m.begin();it!=m.end();it++)
cout<<(*it).first<<":"<<(*it).second;//使用first,second
也可以用rbegin rend来反转
m<string,float>::iterator it=m.find(90.3);//返回指针位置


deque双端队列
#include <deque>
deque<int> d;
d.push_back(5);//从队列后插入,使队列元素值增加
d.push_front(3);//从队列前插入,替代队列前端的树
d.insert(d.begin()+1,7);//在某个位置插入,代替所在元素
deque<int>::iterator it;
deque<int>::reverse_iterator rit;
pop_front();//从头部删除元素
pop_back();//从尾部删除元素
d.erase(d.begin()+1);//删除某个元素




list双向链表
只能对迭代器使用++ --来移动,不能直接+n -n来移动
#include <list>
list<int> l;
l.push_back(5);
l.push_front(6);//都会增加长度
list<int>::iterator it;
it++;
l.insert(it,20);
l.remove(20);//这里是remove
l.erase(it);//删除迭代器上的值
l.pop_front();
l.pop_back();
it=l.find(l.begin(),l.end(),5);//需要声明#include <algorithm>
l.sort();




stack堆栈
#include <stack>
stack<int> s;
s.push(5);
s.pop();
s.top();
s.empty();
s.size();




queue队列
#include <queue>
queue<int> q;
q.push();
q.pop();
q.front();
q.back();




priority_queue最大的元素在最前,也可重载<运算符
pop每次pop最前端,也即是最大的元素




一般只转换bitset的某一个段
string str("1111111000000011001101");
bitset<32> bit4(str,5,4); //这里从str[5] 注意 不是第5个字符开始,往后找4位,即1100
bitset<32> bit5(str,str.size()-4);意味着从开始处取到最后,此处为后四位数1101


对bitset对象的操作
b.any() b中存在置为1的位?存在返回TRUE 不存在返回FALSE
b.none() b中不存在为1的位?不存在返回TRUE 存在返回FALSE


b.count() b中为1的位数
b.size() b的位数
这两个函数返回值的类型是size_t类型,定义在cstddef头文件中,是一个与机器相关的unsigned类型


b[pos] b中的二进制位
b.test(pos) b中pos处的二进制位是否为1


b.set() 全置1 b.set(pos) pos设1
b.reset() 全置0 b.reset(pos) pos设0
b.flip() 全取反 b.flip(pos) pos取反


unsigned long ulong=bit1.to_ulong(); //把位所表示的值转化为 平时见的 值 比如“1111”为15


直接对bitset对象进行cout 得到的是其一位位的1010的排序值








数组 长度是固定的,没有获取其长度的size操作,也不提供push_back操作


只有当性能测试表明使用vector无法达到必要的速度要求时,才使用数组


字符数组
char a[]={'c','+','+'};
char b[]="c++";
char c[]={'c','+','+','\0'};//和上式等价


指针,保存的是一个对象的地址
用*把一个标识符声明为指针


要么修改指针指向的对象,要么修改指针中存储的地址
即 通过指针进行赋值 和 给指针赋值
比如有
string s1("i am a string"); string *sp1=&s1;
如果*sp1="a new string"; 实际上改变了(sp1所指向的对象)s1的值
如果sp1=sp2; 实际上改变了这个指针所引用的对象




指针和引用的区别:
引用&一经初始化就不能改变 int &a=x; 看到a就跟看到x一样
指针string *a=" " a只是后面的一个代理,之后也可以转去代理别的值


若指针直接指向一个数组,则其实是指向了数组的第一个元素 int *ip=array; //int *ip=&array[0];


int *p=&ia[2];
int j=*(p+1) 后者 int j=p[1] 都是代表访问p所在下一个位置的数据


用指针遍历数组
const size_t arr_az=5;
int a[arr_az]={2,3,1,9,5};
for(int *abegin=a,int *aend=abegin+arr_az;abegin!=aend;aend++)
//定义指针指向数组开始第一个元素,再定义一个指针指向最后一个元素后一个位置
*abegin=0;


const double *d; //自以为指向const的指针,不能通过他来改变指向的值


int *const d; //不能指向别的对象的指针


const double *const d; //既不能修改指向对象的值,也不能修改指的方向


#include <string> 跟 #include <cstring> 不是一回事


C风格的字符串使用strlen strcmp strcat等函数进行操作
不要忘记最后必须有一个null,但是strlen返回是不带最后null的数
程序员必须自己保证目标字符串足够大
尽量使用string 避免使用cstring


创建动态的数组
string *psa=new string[n]; //不声明名字,指针*psa指向数组第一个元素的位置
用法:
for(int *q=psa;q!=psa+n;q++)
{ ...... }
用完以后释放掉
delete [] *psa; //注意要加[]




用数组来初始化一个vector
需要两边两个指针
const size_t arr_size=6;
int arr[arr_size]={1,4,5,2,3,2};
vector<int> ivec(arr,arr+arr_size); //两端的指针,其中后一个是指被复制的最后一个元素后的地址空间




多维数组
int ia[3][4];
int (*ip)[4]=ia; //这个指针的类型为 维数为4的int数组
ip=ia[2]; //把指针指向ia[2]


用typedef简化
typedef int int_array[4];
int_array *ip=ia;


for(int_array *p=ia;p!=ia+3;++p)
for(int *q=*p;q!=*p+4;q++)
cout<<*q<<endl;




++i的效率比i++要高


箭头操作符:
MyItem a;
MyItem *sp=&a;
则要获取a中的成员时 用a.foo 或者用指针形式 sp->foo; ★!!!★


sizeof() 可以知道一个类型或者对象所占的长度 单位为字节


在循环语句中创建的变量每一次都要经历创建啊和撤销的过程


标准库定义的异常类,在stdexcept头文件中
exception 常见的问题
runtiem_error 运行时错误,仅在运行时才能检测到的错误
range_error 运行时错误,结果超出了有意义的值域




try
{
....
throw runtime_error("Data illegal!!!");
}
catch(runtime_errr)
{
cout<<err.what();
...
}




一些常量
__FILE__ __LINE__ __TIME__ __DATE__




文件的读写
#include <iofstream>
ofstream a("a.txt");//把a绑定为向a.txt文件的输出流
ifstream b("a.txt");//把b绑定为输入a.txt文件的输入流
a<<something; //把something写入a
b>>something; //把b中的值写入something


switch(a)
{
case 1:
case 2:
do something;
break;
case 3:
lalala;
break;
defalt:
blabla;
break;
}








如果只是单纯的为了避免使用复制引用(比如只是为了引用而不需要修改引用参数),把引用参数为const
bool aa(const string &s1,const string &s2)


函数的参数 如果不是&引用 只是对实参的一个副本引用,任何赋值操作不会改变原实参


如果使用指针作为参数,可以改变指针所指向的变量的值


引用形式参数 void swap(&s1,&s2);


//如果数组作为非引用参数,实际上是以指向数组第一个元素的指针为参数
//作为引用,则传递整个数组


static int i;无论在哪里声明 都是全局变量








(inline) //这样可以内联函数
const string &shorterString(....) //解析:返回的类型是一个对string的引用 这个引用指向是不变的,所以有const




this是一个指针 用的时候this->isbn; 但一般不些this也默认是隐士定义




类的构造函数
名字与类名相同,没有返回值


构造函数的初始化列表,函数名冒号后面是对类的一个或多个数据成员指定初值
Sales_item():units_sold(0),revenue(1,5)
{


}




▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲第9章顺序容器▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲


▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲第10章关联容器▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲


▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲第11章泛型算法▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲




类中的成员函数声明
double avg_price() const;//后面的const代表这个函数不改变成员函数


友元 以关键字friend开始,只能在类中出现,友元类可以访问本类的私有成员


▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲第13章复制控制▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲第14章重载运算符与转换▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲




重载运算符
在类中定义
bool operator==(const Date&a,const Date&b)
{
return a.year()==b.year()&&aa.month()==b.month()&&a.day()==b.day();
}




使用 string名.c_str()转化为c风格字符串


cin除了普通的用法外还可以cin.getline(ch,26)一行获得 cin.get(ch)一个一个获得 其中char ch[256];


'\0'表示字符串的结束符


char(65)可以输出字母


printf("%d%c",amount,str[i]);
scanf();


strcmp(show1,show2) 要求两个参数都为const
show1.compare(show2);不需要为const


控制小数精度
cout.preision(2);
printf("%.2f\n",i);


二维数组int p[10][10]


字符串的长度用length()
vector长度用size()


reverse(xx.begin(),xx.end())
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics