语法的笔记。用到啥就复制点。仅供个人查阅~
基本
printf的格式化输出 :https://www.jianshu.com/p/fdb537c40a9d
(int)(3*1.5)` 默认向下取整得到4
char:字符型与整型相比只是更加节省内存。(在所有数据类型中,char类型占用的内存空间最少)所以可以用来代替int使用
计时
1
2
3
clock_t start = clock();
cout<<clock()-start;inline
内联函数,在函数被调用时就展开。比较快,开销小。
但会使代码膨胀,尤其是内联函数处理复杂,尽可能少用。
const
1
2
3const int* a = x;
int* const b = y;
const int* const c = z;a不能修改所指的内容。但是能指向其他地方。
b能修改所指的内容。但是禁止修改b本身(不能指向其他地方)。
c都不能。
1
2
3const int& a = x;
//这种写法可以禁止引用修改它所指向的变量
//注意,不可以利用这一点来达到“传入引用,并肆无忌惮地修改,最终不破坏原值”的目的。因为const引用,做了内容修改会导致,编译器报错。void指针
void的字面意思是“无类型”,void则为“无类型指针”,void可以指向任何类型的数据。
作用:
(1)对函数返回的限定;
(2)对函数参数的限定。使用:
在C语言中,可以给无参数的函数传送任意类型的参数,但是在C++编译器中编译同样的代码则会出错。在C++中,不能向无参数的函数传送任何参数,出错提示“’fun’:functiondoesnottake1parameters”。
所以,无论在C还是C++中,若函数不接受任何参数,一定要指明参数为void。
数组
局部数组:没有默认值,如果声明的时候不定义,则会出现随机数(undefined);如果声明的长度与赋值长度不相等,则有,声明的长度>赋值长度,后面用0补足,声明的长度>赋值长度,发生编译错误;
全局数组:声明时不赋值,默认值为0
指针new:动态获取的内存,默认值undefined
关于数组初始化,这里写的很详细!https://www.cnblogs.com/bluecagalli/p/9511126.html
函数参数传数组但不改变数组值
以下做法是否可行并未测试
1 | int sum(const int *a[]);/*形参为常量指针数组, 数组aa的每个元素都是常量指针, 不会改变实参的值*/ |
Char* 字符串数组
参考:https://www.cnblogs.com/kungfupanda/archive/2012/06/15/2456931.html
我就抄点我用到的 定义与初始化
1 | char str[ ]={"I am happy"}; //可以省略花括号,如下所示 |
注意:上述这种字符数组的整体赋值只能在字符数组初始化时使用,不能用于字符数组的赋值。但是字符串指针就可以这么赋值:
1 | char *a; |
输出方式
1 | char str[] = "http://c.biancheng.net"; |
Note!关于声明时赋值
c++ 里面 如果你写
1 | char *af ="bbbb"; |
会报错 Conversion from string literal to 'char *' is deprecated
这是什么原因呢,书上是这么写的:
c++从c语言继承下来的一种通用结构是c风格字符串,char 字符串字面值就是这中类型的实例,而字符串字面值的类型是const char 类型的数组,是以空字符null结束的字符数组。
char ca1[] = "hello";//正确 包换null
char ca2[] = {'h','e','l','l','o'};//不含null
char ca3[] = {'h','e','l','l','o','\0'};//包含null
代码可以看出,ca1和ca3是属于c风格字符串。
现在回到问题中,那么正确的写法是什么呢?
1 | char af[] = "hello"; |
以上两种方式都是正确的,而为什么要加上const,因为char字符串字面值是不允许修改的,原因如下:
1 | char const *ak ="ffff"; |
ok,编译正确,这里并木有修改 * ak的值,而是把ak重新指向了“hello”
1 | char const *ak ="ffff"; |
编译有错误“Read-only variable is not assignable”
String
string 转 char*:
1
2string a = "123";
int x = atoi(a.c_str());头文件string与string.h的区别https://www.cnblogs.com/curo0119/p/8304924.html
这篇文章后面对string基操介绍挺全https://www.luogu.org/blog/co2021/solution-p1032
string之间相比较,只有同长度才返回结果。(先判断一下谁长
string对象的操作
1
2
3
4
5istringstream os
os<<s //s写入到输出流os中。返回os
is>>s //从输入流is读取字符串赋给s,返回is。
s.empty()
s.size()//std::string的大小写转换 transform(strA.begin(), strA.end(), strA.begin(), ::toupper);
1
2
3
4
5
6
7
8
### sprintf
```c++
int a, b;
scanf("%d%d", &a, &b);
sprintf(buf, "%d", a + b);
puts(buf);
可以把数据输出到字符串中
c++11标准增加了全局函数std::to_string:
string s = to_string(123);
一.利用stringstream类
字符串到整数
1 | stringstream sstr(str); |
整数到字符串
1 | stringstream sstr; |
缺点:处理大量数据转换速度较慢。stringstream不会主动释放内存,如果要在程序中用同一个流,需要适时地清除一下缓存(用stream.str(“”)和stream.clear()).
npos
用法
1
2
3
4
5
6
7
8
9
10//find 函数 返回jk 在s 中的下标位置
position = s.find("jk");
if (position != s.npos) //如果没找到,返回一个特别的标志c++中用npos表示,npos取值是4294967295,
{
cout << "position is : " << position << endl;
}
else
{
cout << "Not found the flag" + flag;
}原理:
在MSDN中有如下说明:
basic_string::npos
static const size_type npos = -1;//定义
The constant is the largest representable value of type size_type. It is assuredly larger than max_size(); hence it serves as either a very large value or as a special code.
以上的意思是npos是一个常数,表示size_t的最大值(Maximum value for size_t)。许多容器都提供这个东西,用来表示不存在的位置,类型一般是std::container_type::size_type
。
1 |
|
执行结果为:
npos: 4294967295
size_t max: 4294967295
可见他们是相等的,也就是说npos表示size_t的最大值
stream
1 |
|
用这个可以实现各种转string。需要注意的是:
ss一直不会清空。ss一直不会清空。ss一直不会清空。要这么清空:
ss.str("")
就是把空字符串赋值给它
分割单词
1 |
|
类
禁止在栈中实例化的类:
栈空间有限。如果一个类中有大量数据。应尽可能在栈中实例化它,而只允许在堆上创建其实例。做法:
1
2
3
4
5class A{
private:
//大量的数据
~A();
};没错。就是把析构函数设为私有。这时候在main中声明一个A a,由于编译器会在main()末尾调用析构函数,而私有不可用。编译报错。
那怎么析构?
1
2
3
4
5
6
7
8
9class A{
...//略
public:
static void DestroyInstance(MonsterDB* pInstance){
delete pInstance;
}
}
A* a = new A();
A::DestroyInstance(a);与struct不同:
struct中成员默认为共有。class默认为私有。
除非指定了,否则struct以公有方式继承基struct。class为私有。
友元
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class A{
private:
//...data...
friend void DisplayAge(const A& a){
show(a.data);
};
friend class B;
};
class B{
public:
void func(const A& a){
show(a.data);
}
};
//友元函数和类都可以访问到private数据
关于继承
派生类重载了基类的一个方法后,若又想调用一下父亲的方法:
1 | B.A::func(); |
应避免写与基类同名但参数不同的func,以免隐藏基类func。
私有继承:
基类中的方法、成员全部不可访问。从继承层次结构来看,私有继承并非is-a关系。私有继承使得只有子类才能使用基类的属性和方法,因此也被成为has-a关系。
保护继承:
也表示has-a。在继承层次结构外,也不能通过派生类实例访问基类的成员。
虚继承:
1
2
3A;
B:public A; C:public A; D:public A;
E:public B,public C,public D;这时候构造一个E,够构造一个B\C\D和三个A!显然不科学,正确做法是采用虚继承:
如果派生类 可能被用作基类, 派生他最好使用关键字
virtual
1
2
3A;
B:public virtual A; C:public virtual A; D:public virtual A;
E:public B,public C,public D;
多态
基类A,派生类B。现在声明一个A* p,并指向B的object:b.
然后delete p. 会发现,仅仅析构了A,而没有析构B。发生内存泄漏。
如果将A的析构函数声明成virtual的,则delete p时,析构A完会自动析构B。
如果A中存在纯虚函数virtual void func()=0;
这个A是不能被实例化的。也叫抽象基类。
读写文件
https://www.cnblogs.com/liaocheng/p/4371796.html
1 | //写文件实例 |
STL
Vector
容器是连续的内存区。有1.5倍的容量大小。可以避免开数组设置大小的问题。
初始化
默认构造函数
1
2vector<int> vt(10); //10个0
vector<int> vt(10,1); //10个1数组地址初始化
1
2int a[3] = {1,2,3};
vector<int> vt(a,a+3);文档中看到的方法,编译过不了?
1
std::vector<int> v1{1, 2, 3};
二维初始化:
1
vector<vector<int>> vt(n,vector<int>(m,0));
遍历
迭代器
1
2
3
4
5
6ST tmp;
vector<ST>:: iterator iter;
for(iter = vt.begin();iter != vt.end();iter++){
tmp = *iter;
//取到了
}at()
括号里是下标。跟数组一样访问就行了。tmp=vt.at(5);
去重
1 | v.erase(unique(v.begin(), v.end()), v.end()); |
unique()函数将重复的元素放到vector的尾部 然后返回指向第一个重复元素的迭代器再用erase函数擦除从这个元素到最后元素的所有的元素
统计
1 | count(a.begin(),a.end(),value) |
Queue
优先队列priority_queue
默认排序方式是<,且注意q.top()
是最大值。如果想让q.top()
是最小值,比较函数应使用greater()
,和sort是反着的。
下面重点说一下队列里的元素是自定义结构体的情况(需要重载运算符)
1 | struct cmp1{ |
Map
遍历
1 | map<int, int>::iterator iter; |
查找:
1 | if(map.find('x')!= _map.end()) |
Set
1 | int numList[6]={1,2,2,3,3,3}; |
Algorithm.h
Sort()
注意:经测试,比较函数必须写在全局函数里
1 | struct stu{ |
1 |
|
然后如果是基本类型假如是int,第三个参数可以使用系统自带的less<int>()
或者greater<int>()
然后说说sort的前两个参数: 第一个是数组基地址,第二个是长度+1。
如对a[0..i]排序需要传入sort(a,a+i+1)才行。
unique
可以提出所有连续的数并缩减到一个.
1 |
|
最后输出:1 2 3 5 10
其他
void func(char * arr, int x)
你在定义的这个函数里 写x++
这种句子。会报错? x是个形参,怎么能 变来变去呢?但是我觉得应该可以变啊。我得去试试再。
cout<<oct<<x<<dec<<x<<hex<<x<<endl; //oct、dec、hex类似格式控制符,控制其后的变量
if里定义的变量不能在if外使用。
枚举类型成员都是整型变量。可以为负。不设初值就是上一个变量+1。
enum a {sum=9,mon=-1,tue};
打印tue的值就是0.cin
怎么结束输入Mac下是
ctrl + D
Win 下是ctrl + Z
#ifdef和#endif
选择性编译
1 |
|