第三章:
1,sozeof(int); int n_int=INT_MAX; sizeof n_int;(对变量括号可选)
2,#include<climits>包含一些类型的最大值
3,count 默认显示十进制, cout<<dec(默认) count<<hex count<<oct
4,bool, char, short, int, long, longlong, float, double, long double
5,count.setf(ios_base::fixed,ios_base::floatfield)//防止大的数切换到E表示法,显示小数点后6位小数(保留0)
6,C++风格 typeName(value)
7,变量初始化 int wren(23); int wren=23;
8,C++ const和#define区别:
(1)const 编译阶段使用,define是在预处理阶段展开;
(2)const可以指定类型,做安全检查,而define没有
(3)const可以在限定在指定区域
(4)const用于更复杂的类型,数组,结构体(大对象要分配内存,或extern声明或对其取地址时也要分配内存)
(5)const常量定义基本类型时放在符号表中(堆或栈),而define仅仅是展开,不分配内存
9常量的类型:L,l; U,u; ul,UL;
10 类型转换 float运算不提升为double,int型整数被赋给float时截取小数
***常量折叠:#define和const,const定义常量,你不能尝试通过更改变量的值去改变它,但是可以通过引用它的地址来改变,即通过指针。常量折叠说的是,在编译阶段,对该变量进行值替换,同时,该常量记录在符号表中,和define还不一样,有三种情况下,会为const分配内存。
实例:#include<iostream>
int main()
{
using namespace std;
const int i=20;
int *p=(int *) &i;//改变i内存地址上的值
*p=10;
cout<<(int *)&i<<":"<<i<<endl;//这个i在编译阶段已经被20给替换了
cout<<p<<":"<<*p<<endl;
return 0;
}
结果显示0012FF44:20
0012FF44:10
第四章:
1,数组只能定义时初始化,int hand[500]={0},此后只能单个单个元素赋值; 不能数组间赋值
初始化数组为{1}时,只有第一个元素是1,其它置0
a=int[10];sizeof a 数组字节数10*4; sizeof a[0] int类型字节数4
2,字符串数组 char cat[5]="C+owby"或 char cat[]="....."; count<<cat打印字符串,而非地址;
3,字符串输入:cin通过空白(space,,
)来定界,不能读空格;
cin.getline(name,20),遇到
,
停止,丢弃换行符,最多读19个char;
cin.get(name,20).get()或name=cin.get();cin.get();cin.clear()
* 用cin>> 连续读入时,注意每次读入字符或数字时,cin,get()或者(cin>>value).get()处理掉字符流中的回车生成的
4,读数字 cin>>year;cin.get()处理空行,防止阻断输入
5,#include<string> string类在名称空间std中 使用前必须声明useing namespace std;
和字符串数组不同,相互赋值:str1=str2; 拼接:str1+=str2;读入:getline(cin,str1)(这是个函数,不是cin的类方法)
6,对比#include<cstring>,
void strcat(char *t,char *s){ while(*t++=*s++);}字符串拼接
strcpy(char *t,char *s);
字符串长度:string类方法 len=str1.size()(不计' '), 字符串数组 len=strlen(charr1)(cstring 中的函数,不计 )
读入方法: 字符串数组 cin.getline(name,20), string:getline(cin,str1);
7,struct 可以相互赋值, 成员分隔定义时用;赋值时用,可以整体赋值,可以结构数组
8, union, enum spectum{oen,two=0,three=8,four};spectum myflag=one;
9,指针:使用前一定要有指向地址!cha c='a',*p=&c; (int*)强制转换为两个字节的地址类型,(double*)四个字节
10,new/delete 和malloc/free比较:
new/delete是操作符,而malloc/free是库函数,都是用于申请动态内存和释放动态内存的
对非内部数据类型的对象而言,malloc/free不能执行构造函数和析构函数,注定只能用于C
而new/delete可以胜任
11,new/delete条例:内存耗尽返回0(null pointer)可以被释放;不是new开辟的内存就不要用delete去释放;一个地址只能释放一次,无论多少指针指向它
12,指针和数组名:基本相同,根本区别:数组名是指向第一个元素的地址常量,不能被赋值!
指针或数组名加1是指向下一个地址块,即下个元素
13,cout的智能化:cout<<array;array是数组名,cout自动辨别是否为字符串数组(试了下,char数组就可以,比如字符数组char array[]=['a','b',' ','c']也可以)或string或char*,若是打印数组内容;其它则打印数组首元素地址
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 5 using namespace std; 6 int main() 7 { 8 string str1="hello"; 9 cout<<str1;//打印字符串内容 10 char array[]="hello word"; 11 12 cout<<endl<<array<<endl;//打印字符串数组内容 13 int mm[6]={0,1,2,3,4,5}; 14 cout<<mm<<endl;//打印整型数组地址 15 16 char c='a',nn[]={'a','b','c','d','e','f'}; 17 cout<<"nn is:"<<nn<<endl;//打印字符型数组内容,但是由于n[4]后面的没有初始化,乱码 18 char *p1=new char[strlen(nn)+1]; 19 cout<<"strlen:"<<strlen(nn)<<endl;//strlen只是针对字符串数组有用!!12是怎么来的? 20 strcpy(p1,nn); 21 cout<<p1<<endl;//同打印nn一样,后面未初始化的依然乱码 22 cout<<*p1<<endl;//首个元素内容 23 24 char vv[20]="hello word!!!"; 25 cout<<vv<<endl; 26 cout<<"strlen:"<<strlen(vv)<<endl; 27 char *p2=new char[strlen(vv)+1];//这次可以了 13 28 strcpy(p2,vv); 29 cout<<p2<<endl;//打印出hello word 30 delete [] p1; 31 delete [] p2; 32 return 0; 33 34 }
第五章:
1,前缀后缀++,对自己定义的对象来说,前缀效率更高;++p优先级同*,p++比*优先级高,从右到左计算,这样:
double arr[]={21,32,23,45,37};
double *p=arr;
++p; // 32 arr[1]
*++p; //23 arr[2]
++*p;//24 arr[2]
(*p)++;//25 arr[2] p这里就是arr的别名,arr是个地址常量,指向同一块内存
*p++; //后缀,当前命令行不加1,25,arr[3]
2,逗号表达式,右边的值为主
3,string字符串比较, 直接string word=“....”; if (word=="...."){....} C 风格 <string.h> strcpm()函数相同返回0否则回>0,<0
4,for(;;) while() do{} while();注意这里有分号
5, <ctime> clock_t 时间类型 clock()返回当前的clock_t类,就是long别名;CLOCKS_PER_SEC常量,代表每秒包含系统时间的 数量,可用来计算算法elapse time或者做延时函数
6,类型别名 #define Byte char // 宏 typedef Byte char;
7, cin不读空格,按下enter结束 多余的输入缓冲,下次读
8,cin.get()函数重载,三种读取方式,遇到换行符结束,不丢弃:cin.get(ch),cin.get(charr,10),cin.get()用来读回车产生的 换行符
9,EOF cin.eof() cin.fail() cin.clear()
10,int ch=cin.get()返回一个int型,cin.put()
11 二维数组
第六章:
1,&& and, || or, not !
2(**),#include<cctype> cctype函数库:(函数)
*isalnum(ch) 字母或数字,返回true
*isalpha() 字母,返回true
isblank() 空格或制表符 true
iscntrl() 控制字符 true
*isdigit() 数字(0~9) true
isgraph() 空格之外的打印字符 true
*islower() 小写字母 true
isprint() 打印字母(包括空格)
*ispunct() 标点
*isspace() 标准空白字符
*isupper() 大写字母
isxidigit() 十六进制数字 0~9, a~f, A~F
*tolower() 大写变小写
*toupper() 小写变大写
python中(类方法):
s.isalnum()
s.isalpha()
s.isdigit()
s.uslower()
s.isupper()
s.istile()
s.isspace()
3, switch语句的case标签必须是整数(char,int,long,longlong),enum做标签提升为int
第七章 函数
1,函数原型的必要性:告诉编译器函数的返回值和参数类型,以便编译器进行正确读取,可能的话进行转换(都是算术类型且可以 转换)
2, int a=0; const int *p = &a; *p的值不能通过指针改变,但可以由a改变(前提是 a没有const声明),p指向的地址可以变, 比如 p = &b;
int a=0; int * const p = &a; p和&a绑定死了,不能指向别人了,意味着这种指针必须声明时初始化,和引用效果一样。 但可以通过*p=1来 改变a,前提是a不是const
3,const int a=0; int *p = &a; 报错,但可以通过(int *) 强制地址转换,有涉及到常量折叠了
4,**二级指针**p和二维数组对照的理解, int arr[100][4]; int **p=arr; p//指向arr[0]; p+r//指向arr[r]; *p//指向arr[0] [0]地址; *(p+r)//指向arr[r][0]; *(p+r)+c//arr[r][c]的地址; *(*(p+r))+c//arr[r][c]的值也就是p[r][c]
5,函数指针 double (*pf)(int), *pf或pf就像是函数名的别名
第八章:函数2
1,内联 inline 不同于#define宏定义,宏定义是文本替换,没有参数传递,而inline有
2,引用创建时初始化,相当于int* const pt 引用参数和临时变量那块要仔细理解!形参用const声明,会根据需要产生临时变量 ,如果试图修改,会警告,只会修改临时变量的值
3,引用参数及返回值,啥时候加const啥时候不加~返回值加了const,比如const syone& func(); 不可以直接对func()进行写; 需要先创建一个同类型的变量,然后赋值进行写操作。
4,返回引用时, 不能返回不存在的内存单元~返回值的话,系统会先拷贝到临时区域,返回引用就不会拷贝
5,string类型自动转换: char *或char c[](实参)——>string(形参),返过来会报错:
1 1 using namespace std; 2 2 void change(string s); 3 3 int main() 4 4 { 5 5 char * s="hello"; 6 6 cout<<s<<endl; 7 7 change(s); 8 8 cout<<s<<endl; 9 9 return 0; 10 10 } 11 11 12 12 void change( string s) 13 13 { 14 14 s="nihao"; 15 15 cout<<s<<endl; 16 16 } 17 17 //valid 传的是值 18 18 19 19 void change(char *); 20 20 int main() 21 21 { 22 22 string s="hello"; 23 23 cout<<s<<endl; 24 24 change(s); 25 25 cout<<s<<endl; 26 26 return 0; 27 27 } 28 28 29 29 void change(char *s) 30 30 { 31 31 s="nihao"; 32 32 cout<<s<<endl; 33 33 } 34 34 //unvalid 返过来不可以 35 35 36 36 void change(string &); 37 37 int main() 38 38 { 39 39 string s="hello"; 40 40 cout<<s<<endl; 41 41 change(s); 42 42 cout<<s<<endl; 43 43 return 0; 44 44 } 45 45 46 46 void change(string &s) 47 47 { 48 48 s="nihao"; 49 49 cout<<s<<endl; 50 50 } 51 51 //valid 改变了s的值 52 52 53 53 void change(string &); 54 54 int main() 55 55 { 56 56 char* s="hello"; 57 57 cout<<s<<endl; 58 58 change(s); 59 59 cout<<s<<endl; 60 60 return 0; 61 61 } 62 62 63 63 void change(string &s) 64 64 { 65 65 s="nihao"; 66 66 cout<<s<<endl; 67 67 } 68 68 //unvalid 可以把char类型转换为string,但是不能转换为string & 引用 69 69 70 70 void change(const string &); 71 71 int main() 72 72 { 73 73 char* s="hello"; 74 74 cout<<s<<endl; 75 75 change(s); 76 76 cout<<s<<endl; 77 77 return 0; 78 78 } 79 79 80 80 void change(const string &s) 81 81 { 82 82 cout<<s<<endl; 83 83 } 84 84 //valid 加上const就可以,但是有了const,传的其实是值,和第一种情况一样,不能对其改变
补充:
A、数组名不是指针。
B、数组名 是 不是指针的指针。
数组名本质:
(1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组;
(2)数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量;
(3)指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址!
解析:
A
char str[10];
char *pStr = str;
sizeof(str);//值为10。对数组结构求长度。
sizeof(pStr);//值为4。指针变量的长度。
首先对sizeof,是操作符不是函数,siziof(char)是合法的,而如果是函数,函数输入的必须是实参。
B
char str1[10] = "I Love U";
char str2[10];
strcpy(str2,str1);
函数原形中能接纳的两个参数都为char型指针,而我们在调用中传给它的却是两个数组名!
其原因是数组名可以作为指针常量使用,即指针是常量。符合指向数组结构地址的特性。
本质:
1、数组名指代一种数据结构:数组
所以数组名是指向数据结构的指针,且是指针常量,所以不能作为累加来用,不能等同于指针,例如求长度sizeof。
2、数组名可作为指针常量
int intArray[10];
intArray++; //编译器会报错此条。数组名不能作为指针变量一样累加。数组名是指针常量。
3、数组名可能失去其数据结构内涵
数组名因为可以作为指针常量,所以可以作为实参进行传递指针,但是当传递进函数的时候,作为函数的形参,其自动换成了指针。 数组名作为指针常量,可以作实参, 传递到函数的形参中,自动转换成指针变量。
void arrayTest(char str[])
{
cout << sizeof(str) << endl;//长度为4
}
int main(int argc, char* argv[])
{
char str1[10] = "I Love U";
arrayTest(str1);
return 0;
}
(1)数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;
(2)很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。
所以,数据名作为函数形参时,其全面沦落为一个普通指针!它的贵族身份被剥夺,成了一个地地道道的只拥有4个字节的平民。
结构体和指针
数组定义好了数组的类型。例如int a[10];
而结构体的类型是结构体本身,