C++学习笔记(乱序版)


以下的文件名或者代码中的中文字符都是娱乐或者为了方便查找,大家写代码时推荐使用英文字符

变量的声明与定义

变量的声明和变量.cpp

#include<iostream>
using namespace std;
int i;//变量的定义
extern int j;//变量的声明,且声明的类型要与原定义的类型相同
extern double q=3.1475926;//赋值了就变成了定义而不是声明
int main(){
	j++;
	cout<<j<<endl;
	system("pause");
	return 0;
}

extern int x;变量的声明,且声明的类型要与原定义的类型相同

  1. 若给声明的变量赋值则变成了定义

two.cpp

#include<stdio.h>
int j=55;
void foo(){
	printf("%d",j);
}

利用变量的声明可以使变量在不同的文件中传递数值!

const限定符

const限定符.cpp

#include<iostream>
#include<stdlib.h>
const int play=3;/*const会让play只在此项中可用,若想其他项可用,则加上extern
                   const的对象为项内的局部变量*/
extern const int play2=4;
//以下三个为原型
extern int bb;
extern float cc;
extern double dd;
using namespace std;
int main(){
	system("pause");
	return 0;
}
  1. const定义的常量为局部常量,其他的项无法使用,若是想让其他的项也可以调用,则需要加上extern
  2. 类似于这样 int j;的代码的原型是extern int j;

two.cpp

#include<iostream>
//extern const int play;这样会报错
extern const int play2;
using namespace std;
void foo(){
	//不可用main
}
  1. 无法声明上一个项中的play变量,因为play是局部变量
  2. 其他项的函数名不要重复

引用

引用.cpp

#include<iostream>
using namespace std;
int main(){
	const int aa=0;
	const int &ddd=aa;//const引用必须引用const类型
	//int &x=aa;非const引用不可以引用const类型
	const int &y=42;//const引用可以引用常量
	
	int 张飞=99;
	const int &yy=张飞;//const可以是非const类型的别名
	int &张翼德=张飞;//张翼德是张飞的别名
	int c;
	int &d=c;
	int e;
	//int &f;定义引用必须马山个初始化,否则报错
	//int &f=10;别名必须是变量,因为是别名
	张飞++;
	cout<<张翼德<<endl;
	system("pause");
	return 0;

}
  1. 引用用的是取地址符&,但是不要跟指针搞混淆。
  2. 只能引用同类型的变量,const也是如此
  3. const引用可以引用常量
  4. 但是const可以是非const类型的别名,但是反过来就不行
  5. 定义引用如int &f;int &f=10;这两个都会报错,因为定义引用要马上初始化,别名也必须是变量,除非是const类型。

::作用域解析

下面讲到的vector的循环中会用到::
"::“在C++中表示作用域,和所属关系。”::"是运算符中等级最高的,它分为三种,分别如下

  • 作用域符号
    作用域符号”::“的前面一般是类名称,后面一般是该类的成员名称
    例如:A,B表示两个类,在A,B中都有成员member。
    那么:
    1、A::member就表示类A中的成员member。
    2、B::member就表示类B中的成员member。
  • 全局作用域符号
    当全局变量与局部变量重复时可以用来区分,例如
#include<iostream>
using namespace std;
int a=1;
int main() {
	int a=0;
	printf("%d \n",::a);
	printf("%d \n",a);
	system("pause");
	return 0;
}
}

输出为1和0。

  • 作用域分解运算符
    ::是C++里的作用域分解运算符,“比如声明了一个类A,类A里声明了一个成员函数int b(),但没有在类的声明里给出f的定义,那么在类外定义b时,就要写成int A::b(),表示这个f()函数是类A的成员函数,例如:
class A {
public:
	int b();
};
int A::b() {

}

vector向量

vector可以理解为动态数组

vector类型.cpp

#include<iostream>
#include<vector>//vector类型的头文件
//vector可以理解为动态数组
#include<string>
using namespace std;
class Dog
{
	//
};
int main(){
	vector<int> ival;//保存int类型的一个向量
	vector<double> idouble;
	vector<string> istring;
	vector<Dog> idog;
	vector<int> a;//a是一个空的容器
	vector<int> b(10,2);//b容器中有10个2
	vector<int> cc(10);//c容器里有10个0
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	b.push_back(10);
	b.push_back(11);
	cout<<a.size()<<endl;
	cout<<b.size()<<endl;
	cout<<b[0]<<endl;
	for(vector<int>::size_type bb=0;bb!=a.size();bb++)//vector<type>也有自己的类型
	{
		break;
	}
	//**********************
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(11);
	vector<int> v2(v1);//将v1传入v2中,要同类型
	//vector<string> v3(v1);这样是错误的
	//***************************
	//向量的下标元素不添加元素
	vector<int> dd;//空的,所以没有下标
	//推荐
	int k;
	cin>>k;
	dd.push_back(k);
	system("pause");
	return 0;
}

vector的语法:
vector();
vector( size_type num, const TYPE &val );
vector( const vector &from );
vector( input_iterator start, input_iterator end );

C++ Vectors可以使用以下任意一种参数方式构造:

无参数 - 构造一个空的vector,
数量(num)和值(val) - 构造一个初始放入num个值为val的元素的Vector
vector(from) - 构造一个与vector from 相同的vector
迭代器(start)和迭代器(end) - 构造一个初始值为[start,end)区间元素的Vector(注:半开区间).
举例,下面这个实例构造了一个包含5个值为42的元素的Vector
vector v1( 5, 42 );

  1. void ==push_back==( const TYPE &val );
    push_back()添加值为val的元素到当前vector末尾
  2. vector也有自己的类型,size_type
  3. vector<int> v2(v1);//将v1传入v2中,要同类型,非同类型会报错

using 名称空间

using 名称空间.cpp

#include<iostream>
using std::cout;
using std::cin;//cin就可以直接使用了
int main(){
	//::叫做作用域操作符,前面就是名称空间
	std::cout<<"hello world"<<std::endl;
	system("pause");
	return 0;
}
  • 自己看一下代码吧,没啥好说的

指针和数组

指针和数组.cpp

#include<iostream>
#include<vector>
using namespace std;
int main(){
	system("color 0a");
	int ia[]={1,2,4,6,8};
	int* ip=ia;//ia就是&ia[0]
	cout<<*ia<<" and "<<ia<<" and "<<&ia[0]<<endl;
	ip=ia;
	int* ip2=ip+4;//等于ia+4;
	cout<<*ip2<<" and "<<ip2<<" and "<<&ia[4]<<" and "<<&ia[0]+4<<endl;
//***************************
	int* ip4=ia+10;//超过了,很危险,但是不会报错,取的是其他的数据
	cout<<*ip4<<endl;
//*****************************
	ptrdiff_t n=ip2-ip;//表示的是两个地址之间的距离,类型为ptrdiff_t
	cout<<"距离为:"<<n<<endl;
//*****************************
	int* p=ia+1;
	int j=p[2];//p=&ia[0],p[2]=p+2=&ia[0]+2
	int k=p[-1];
	//方框的下标为指针的加法,负数也可以
	cout<<j<<endl;
	cout<<k<<endl;
//**************************
	const size_t arr_size=5;
	int arr[arr_size]={1,2,3,4,5};
	int* ar=arr;//首指针
	int* br=arr+arr_size;//超出末端的指针,即指向最后元素的下一个,c++允许这样做
	//主要是为了写循环,与向量循环很相似
	cout<<"指针循环"<<endl;
	for(int* ptt=arr;ptt!=br;ptt++){
		cout<<*ptt<<endl;
	}
	//相似的向量循环
	vector<int> aa;
	aa.push_back(1);
	aa.push_back(2);
	aa.push_back(3);
	aa.push_back(4);
	aa.push_back(5);
	cout<<"向量循环"<<endl;
	for(vector<int>::iterator nn=aa.begin();nn!=aa.end();nn++){
		//aa.begin()指的就是aa向量里的第一个元素
		//aa。end()指的就是aa向量里的最后一个元素的下一个
		cout<<*nn<<endl;//迭代器也需要*来解引用
	}
	system("pause");
	return 0;
}
  1. 数组名称就是数组首元素的地址
    int ia[]={1,2,3}; //ia=&ia[0]
  2. 我个人推荐指针这样写int* a而不是int *a,这两个是相同的,但是前者更容易理解,后者新手学习容易误会。
  3. 指针加法:&ia[0]+4就是&ia[4],这是用地址来写,可以以指针的方式来写,如:int* ip=&ia; 再ip+4;
  4. 但是如果ip后的值加的很大,这很危险,编辑器不会报错,但是取的是其他的地方的数据
  5. 以上述的代码为基础ptrdiff_t n=ip2-ip;//表示的是两个地址之间的距离,类型为ptrdiff_t,ptrdiff_t可以用int来代替,但是逼格高呀。
int* p=ia+1;
	int j=p[2];//p=&ia[0],p[2]=p+2=&ia[0]+2
	int k=p[-1];

对于这里,指针也可以使用下标运算,表示的是加法,负数即为减法,表示的意义即为上面的指针加法

7.指针循环与向量循环

const size_t arr_size=5;
	int arr[arr_size]={1,2,3,4,5};
	int* ar=arr;//首指针
	int* br=arr+arr_size;//超出末端的指针,即指向最后元素的下一个,c++允许这样做
	//主要是为了写循环,与向量循环很相似
	cout<<"指针循环"<<endl;
	for(int* ptt=arr;ptt!=br;ptt++){
		cout<<*ptt<<endl;
	}
	//相似的向量循环
	vector<int> aa;
	aa.push_back(1);
	aa.push_back(2);
	aa.push_back(3);
	aa.push_back(4);
	aa.push_back(5);
	cout<<"向量循环"<<endl;
	for(vector<int>::iterator nn=aa.begin();nn!=aa.end();nn++){
		//aa.begin()指的就是aa向量里的第一个元素
		//aa。end()指的就是aa向量里的最后一个元素的下一个
		cout<<*nn<<endl;//迭代器也需要*来解引用
	}

先看看这个

	int* br=arr+arr_size;//超出末端的指针,即指向最后元素的下一个,c++允许这样做
	//主要是为了写循环,与向量循环很相似

这是一个超出末端的指针,指向最后元素的下一个,c++允许这个样子

for(vector<int>::iterator nn=aa.begin();nn!=aa.end();nn++){
		//aa.begin()指的就是aa向量里的第一个元素
		//aa。end()指的就是aa向量里的最后一个元素的下一个
		cout<<*nn<<endl;//迭代器也需要*来解引用
	}

这里用到的是迭代器。迭代器的begin()end()与上面的指针循环很像,begin()指的就是向量的第一个元素,而end()指的是最后一个的下一个元素。

来说说迭代器

先说说为什么我不把迭代器放到指针与数组前,因为我懒!
迭代器.cpp

#include<iostream>
#include<vector>
using namespace std;
int main(){
	vector<int> val(10,8);
	vector<int> val2(10,9);
	//                           begin()返回一个迭代器
	//                           指向第一个元素
	vector<int>::iterator it=val.begin();
	vector<int>::iterator it2=val2.begin();
	//常迭代器
	vector<int>::const_iterator it3=val.begin();//不能修改
	while (it2!=val2.end)
	{
		*it2=11;
		it2++;
	}
	//迭代器实际就是指针
	*it=9;
	cout<<val[0]<<val[1]<<endl;
	*it++;
	cout<<val[1]<<endl<<"后面的"<<endl;
	//迭代器用来替代下标
	for(vector<int>::iterator itt=val.begin();itt!=val.end();itt++){
		cout<<*itt<<endl;
	}
	
	system("pause");
	return 0;
}
  1. 来看看迭代器的API
    C++ Iterators(迭代器)
    迭代器可被用来访问一个容器类的所包函的全部元素,其行为像一个指针。举一个例子,你可用一个迭代器来实现对vector容器中所含元素的遍历。有这么几种迭代器如下:
迭代器描述
input_iterator提供读功能的向前移动迭代器,它们可被进行增加(++),比较与解引用(*)。
output_iterator提供写功能的向前移动迭代器,它们可被进行增加(++),比较与解引用(*)。
forward_iterator可向前移动的,同时具有读写功能的迭代器。同时具有input和output迭代器的功能,并可对迭代器的值进行储存。
bidirectional_iterator双向迭代器,同时提供读写功能,同forward迭代器,但可用来进行增加(++)或减少(–)操作。
random_iterator随机迭代器,提供随机读写功能.是功能最强大的迭代器, 具有双向迭代器的全部功能,同时实现指针般的算术与比较运算。
reverse_iterator如同随机迭代器或双向迭代器,但其移动是反向的。(Either a random iterator or a bidirectional iterator that moves in reverse direction.)(我不太理解它的行为)

第种容器类都联系于一种类型的迭代器。第个STL算法的实现使用某一类型的迭代器。举个例子,vector容器类就有一个random-access随机迭代器,这也意味着其可以使用随机读写的算法。既然随机迭代器具有全部其它迭代器的特性,这也就是说为其它迭代器设计的算法也可被用在vector容器上。

如下代码对vector容器对象生成和使用了迭代器:

vector the_vector;
vector::iterator the_iterator;

for( int i=0; i < 10; i++ )
the_vector.push_back(i);

int total = 0;
the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
total += *the_iterator;
the_iterator++;
}
cout << “Total=” << total << endl;

提示:通过对一个迭代器的解引用操作(*),可以访问到容器所包含的元素。

  1. begin()end()前面已经讲过了,不讲了
  2. 常迭代器vector<int>::const_iterator it3=val.begin();,顾名思义,它不能修改。
  3. 迭代器与指针十分相像。

typeder

typeder.cpp

#include<iostream>
typedef int 整形;
typedef float 浮点型;

using namespace std;
int main(){
	int c;
	整形 a;
	浮点型 b;
	system("pause");
	return 0;
}

没啥好讲的,自己看吧

C++标准库string(1)

C++标准库string(1).cpp

#include<iostream>
#include<string>
using namespace std;
int main(){
	char a[10];//c语言的做法
	string aa;//c++的做法
	//string的4中初始化方法
	string s1;
	string s2("hello world");
	string s3(s2);
	string s4(10,'hse');
	cout<<"第一种"<<s1<<endl;
	cout<<"第二种"<<s2<<endl;
	cout<<"第三种"<<s3<<endl;
	cout<<"第四种"<<s4<<endl;//只会输出eeeeee,输出最后一个
	string s5="hahha";//这是一种不好的方法,原理是s5先被默认初始化然后再复制,效率低
	cout<<"hello wprld"<<endl;//这个是字符数组类型
	cout<<s2<<endl;//s2是string类型
	system("pause");
	return 0;
}
  1. C++的string与C语言的char数组不一样,string功能更加强大,并且更加好用。
  2. 来看看C++ API吧
    语法:
    string();
    string( size_type length, char ch );
    string( const char *str );
    string( const char *str, size_type length );
    string( string &str, size_type index, size_type length );
    string( input_iterator start, input_iterator end );

字符串的构造函数创建一个新字符串,包括:

以length为长度的ch的拷贝(即length个ch)
以str为初值 (长度任意),
以index为索引开始的子串,长度为length, 或者
以从start到end的元素为初值.
例如,

string str1( 5, 'c' );
string str2( "Now is the time..." );
string str3( str2, 11, 4 );
cout << str1 << endl;
cout << str2 << endl;
cout << str3 << endl;

显示

ccccc
Now is the time...
time

即为代码中的四种初始化方法

  1. 而对于string s5="hahha";这是一种不好的方法,因为他的原理是s5先被默认初始化然后赋值,效率低下

C++标准库string(2)

C++标准库string(2).cpp

#include<iostream>
#include<string>
using namespace std;
int main(){
	string s1("hello  world");
	string::size_type a =s1.size();//size_type类型专门保存字符串大小,但是要用string在前面,using无效

	cout<<"字符个数(字符串大小)"<<s1.size()<<endl;//空格也算
	//判断空字符串
	string b;
	if(b.size()==0){
		cout<<"这是一个空字符串"<<endl;
	}
	if(b.empty()){
		cout<<"这是空字符串"<<endl;
	}
//***********************************************
	string ss1("张飞");
	string ss2("刘备");
	if(ss1>ss2){
		cout<<"张飞比刘备大"<<endl;
	}
//********************************************
	//字符串相加
	string sss1("hello ");
	string sss2("world\n");
	string sss3=sss1+sss2;
	//string sss4="hello"+"world";有些语言可以这样写,但c++不允许
	string sss6=sss1+"hello"+"world";/*里面只要有一个string的值就可以用加号连接
	                                  因为" "char类型*/
	cout<<sss3;
	system("pause");
	return 0;
}
  1. string::size_type a =s1.size();size_type类型专门保存字符串大小,但是要用string在前面,using无效,也可以用int类型替代。更容易让人理解,主要还是逼格高。
  2. size语法:
    size_type size();
    size()函数返回字符串中现在拥有的字符数。空格也算
  3. empty语法:
    bool empty();
    如果字符串为空则empty()返回真(true),否则返回假(false).
  4. string的拼接
string sss1("hello ");
	string sss2("world\n");
	string sss3=sss1+sss2;
	//string sss4="hello"+"world";有些语言可以这样写,但c++不允许
	string sss6=sss1+"hello"+"world";/*里面只要有一个string的值就可以用加号连接
	                                  因为" "是char类型*/

这样可以将两个string类型的字符串拼接在一起,但是拼接的时候,其中一定要有一个string类型才可以,否则报错

C++标准库string(3)

C++标准库string(3).cpp

#include<iostream>
#include<string>
//#include<ctype.h>c++中不提倡
#include<cctype>//提倡这样的写法
using namespace std;
int main(){
	//string不是c语言中的字符数组
	string a("hello world");
	cout<<a[0]<<endl;
//********************************
	//标点符号的个数
	string a2("hello world!!!");
	string::size_type b=0;
	for(string::size_type index=0;index!=a2.size();index++){
		if (ispunct(a2[index]))
		{
			b++;
		}
	}
	cout<<"标点符号共有:"<<b<<endl;
	//isalnum()如果参数是数字或字母字符,函数返回非零值,否则返回零值。
	//isalpha()如果参数是字母字符,函数返回非零值,否则返回零值。
	//iscntrl()如果参数是控制字符(0和0x1F之间的字符,或者等于0x7F)函数返回非零值,否则返回零值
	//isdigit()如果参数是0到9之间的数字字符,函数返回非零值,否则返回零值.
	//isgraph()如果参数是除空格外的可打印字符(可见的字符),函数返回非零值,否则返回零值
	//islower()如果参数是小写字母字符,函数返回非零值,否则返回零值。
	//isprint()如果参数是可打印字符(包括空格),函数返回非零值,否则返回零值。
	//ispunct()如果参数是除字母,数字和空格外可打印字符,函数返回非零值,否则返回零值。
	//isspace()如果参数是空格类字符(即:单空格,制表符,垂直制表符,满页符,回车符,新行符),函数返回非零值,否则返回零值。
	//isupper()如果参数是大写字母字符,函数返回非零值,否则返回零值。
	//isxdigit()如果参数是十六进制数字字符(即:A-F, a-f, 0-9),函数返回非零值,否则返回零值。

	system("pause");
	return 0;
}
  1. C++的头文件中不建议使用含有.h的头文件
  2. 关于这些string的函数也可以去查阅API等等,代码列出的很全了。

cin等常用详解

本节包括cin,cin.get,cin.getline,getline等常用的用法
cin详解.cpp

#include<iostream>
#include<string>
using namespace std;
void clean() {
	while (getchar()!='\n')
	{
		continue;
	}	//清理STDIN,这个方法很棒
}
int main() {
	char ch;
	char ab[20];
	int a, b;
	cin >> a >> b;
	cout << a+b<<endl;
	cin >> noskipws;//设置cin读取空白符

	while(cin >> ch)

		cout << ch;

	cin >> skipws;//将cin恢复到默认状态,从而丢弃空白符*/
	clean();
	cin >> ab;
	cout << "遇到空格结束:"<<ab << endl;//遇到空格就结束了
	clean();
	char ch2[100];
	ch = cin.get();
	cout << "输出ch"<<ch << endl;//单个字符可以这样写
	cin.get(ch2,20);
	cout <<"输出ch2"<< ch2 << endl;//只会输出19个字符加上一个结尾\0
	//cin.getline用法
	//cin.getline有三个参数
	char m[100];
	cin.getline(m,20,'a');//最后一个默认为\0,即遇到什么字符开始截断
	cout << "输出m"<<m << endl;
	string cc;
	getline(cin,cc);
	cout << "输出的cc为" << cc << endl;
	//和cin.getline()类似,但是cin.getline()属于istream流,
	//而getline()属于string流,是不一样的两个函数
	system("pause");
	return 0;
}
  1. cin的>> 是会过滤掉不可见字符(如 空格 回车,TAB 等)
  2. 若想不过滤掉的话可以使用noskipws,然后再用skipws关闭
  3. cin.get();有两个参数,第一个是要输入到的字符组,第二个是输入的长度
  4. cin.getline();有三个参数,前两个与cin.get();相同,最后一个为设置截至符,默认为\0。
  5. getline();cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数

技巧讲解之清空标准输入流(STDIN)

void clean() {
	while (getchar()!='\n')
	{
		continue;
	}	//清理STDIN,这个方法很棒
}
  • 用getchar()重复读取输入流中的值来浪费他们去做判断,从而将这些不想要的值给"舍弃"掉

C++标准库bitset

C++标准库bitset.cpp

#include<iostream>
#include<bitset>
#include<string>
using namespace std;
int main(){
	bitset<32> a;//a的大小为32位2进制,全部都是0
	cout<<a<<endl;
	bitset<16> b(0xffff);
	cout<<b<<endl;
	string str("1101");
	bitset<32> e(str,str.size()-4);
	cout<<e<<endl;
		bitset<32> f(156);
	cout<<f<<endl;
	bool g=f.any();//any()函数返回真如果有位被设置为1,否则返回假。
	bool h=f.none();//none()返回真如果没有位被设为1,否则返回假。
	int i=f.count();//count()函数bitset中被设置成1的位的个数。
	//***************************
	bitset<32> j;
	j[5]=1;
	cout<<j<<endl;//从后往前数
	for(int index=0;index!=9;index++){
		j.set(index);//set就是将某一位变成1
		//而set()是将每一位都设置成1
		j.reset(index);//reset是将其变成0
		j.flip(index);//翻转,将其0变成1,1变成0

	}
	unsigned long long bb=j.to_ullong();//to_ulong()返回bitset的无符号长整数形式。就是将其转换成10进制数
	bitset<8> gg;
	cin>>gg;
	bitset<8> n(gg);//用其他的bitset初始化新的bitset
	bitset<8> nn(14);
	cout<<(gg & nn)<<endl;//位与,这些操作优先级比较低,要用括号括起来
	cout<<(gg|nn)<<endl;//位或
	system("pause");
	return 0;
}
  1. 注意头文件#include<bitset>这个可不能忘
  2. 来看看bitset的语法格式
    语法:
    bitset();
    bitset( unsigned long val );

C++ Bitsets能以无参的形式创建,或者提供一个长无符号整数,它将被转化为二进制,然后插入到bitset中。当创建bitset时,模板中提供的数字决定bitset有多长。

例如,以下代码创建两个bitsets,然后显示它们:

// 创建一个8位长的bitset

 bitset<8> bs;

  // 显示这个bitset
  for( int i = (int) bs.size(); i >= 0; i-- ) {
    cout << bs[i] << " ";
  }
  cout << endl;

  // 创建另一个bitset
  bitset<8> bs2( (long) 131 );

  // 显示
  for( int i = (int) bs2.size(); i >= 0; i-- ) {
    cout << bs2[i] << " ";
      cout << endl;
  }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值