c++源代码风格1每行一条语句2每个函数的两个花括号各占一行3函数中的语句都对于花括号进行缩进4与函数名称相关的圆括号周围没有空白(空行将声明语句与程序的其他部分分开,或在变量前声明,c++的做法是尽可能在首次使用变量前声明)。
第二章 开始学习c++
变量名的约定:类型_名称 或者是 类型(int)名称(akjl)
c语言输入输出是printf,scanf,他们都包含在头文件stdio.h中
操作符重载:通过重载,同一个操作符将有不同的含义。&操作符表示地址操作符又表示and按位操作符
c++程序应当为程序中使用的每个函数提供原型,而库函数在头文件中有声明,而在库文件中有他的定义。标准c库中提供了140多个预定义函数,而main()函数不是关键字,由于它不是语法的组成
头文件stdlib.h中rand()函数不接受任何参数,并返回一个随机整数,其函数声明如下:int rand(void);
第三章 数据处理
3.1简单变量
内置c++类型有基本类型和复合类型
sizeof操作符能够打印类型或变量长度的单位字节数,如:sizeof(int);sizeof a;//a 为变量
头文件climits包含了整型限制信息
schar_max |
signed char最大值 |
char_bit |
char的位数 |
ing_min |
int最小值 |
uchar_max |
unsigned char最大值 |
schar_min |
signed char最小值 |
shrt_max |
short最大值 |
long_max |
long最大值 |
unit_max |
unsigned int最大值 |
char_max |
char的最大值 |
shrt_min |
short最小值 |
long_min |
long最小值 |
ulong_max |
unsigned long最大值 |
char_min |
char的最小值 |
int_max |
int最大值 |
|
|
ushrt_max |
unsigned short最大值 |
c++的变量的初始化有两种,第一种c语言的:int a=15;第二种是c++的:int a(15);如果不初始化那么变量的值是不确定的
C++添加了两种类型:long long和unsigned long long 两种类型都至少是64位的
cout<<hex;//告诉编译器以16进制的方式输出
cout<<bianliang<<oct;//输出完以后切换到8进制的方式输出
cout<<bianliang<<dec//输出完以后切换回10进制
cout<<1982ul;c++打印常量时候,常量后面加l或l表示1982被存为long型,若是ul或ul表示存为unsigned long型,若是u或u表示存为unsigned int,若无后缀表示存为int。
char ch=’a’;cout.put(ch);//成员变量put()可以打印char型变量,我们也可以写成cout.put(‘n’);
c++转义序列符 (括号里的为ascii符号)
换行符(nl或lf) |
\n |
退格(bs) |
\b |
回车(cr) |
\r |
反斜杠(\) |
\\ |
单引号(‘) |
\’ |
水平制表符(ht) |
\t |
垂直制表符(vt) |
\v |
振铃(bel) |
\a |
问号(?) |
\? |
双引号(“) |
\” |
cout<<endl<<’\n’<<”\n”;//三种方式等效且都表示换行
通用字符名:通用字符名以\u或\u开头,\u后面在跟8个十六进制位,而\u后面跟16个十六进制位,这些位表示的是iso10646编码(iso10646是一种正在制定中的国际标准,位大量的字符提供字符编码,他与unicode合作,确保标准同步,unicode可以表示96000多种符号和49个手写符号,而ascii码就是unicode的一个子集)
cout<<”ni g\u00e2teau.\n”;打印如下ni gâteau //â的iso10646编码是00e2
特殊类型:wcha_t 宽字符类型 bool类型,任何数字值或指针指都可以被隐式的转换为bool值。任何非零值都被转换为true,零被转换为false;反之 int aa=true;long bb=false;也成立。
3.2 const限定符
const long months=true;//const限定符用于定义常量
const限定符定义常量时①常量名一般全用大写,便于与变量区分;②要直接初始化,否则将无法初始化
3.3浮点数
浮点数的书写有两种方式:①常用的标注-942635;②-1.54e-4 5.6545e8 。浮点类型要添加头文件float.h,浮点型的类型有float(32位,其精度低,系统至少有6位有效数位或更低),double(64位,精度至少在13位有效位),long double(80,96,128位)。 浮点常量默认为double类型若希望常量位float,要用f或f后缀,对于long double类型。使用l或l(尽量用l,l像1) cout<<2.2l<<3.12f<<8.123;//8.123为double默认型
c++标准在默认输出时会删除小数点后末尾的零,如将23.450000显示成23.45。
cout.setf(ios_base::fixed,ios_base::flatfield);//可以覆盖默认设置,让打印末尾的0显示出来
3.4 c++算术操作符
求模操作符要求两个数必须为整数
潜在的数值转换问题①大浮点型→小浮点型:精度降低可能超出目标类型的取值范围,结果是不确定的。②浮点型→整型:小数丢失,原先的值可能超出目标类型的取值范围,结果不确定。③大整型→小整形:容易超出范围,通常只复制右边字节
强制类型转换:不会修改变量本身,而是创建一个新的指定类型的值。其格式有两种:
(long) bianliang;//c语言强制类型转换的方式
long (bianliang);//c++风格,其想法是让强制转换类型就想是函数调用
第四章 复合类型
复合类型:在c语言中叫派生类型,而c++中类使用了“派生”这个词,所以叫复合类型
4.1数组(array)
数组的三要素是:每个元素的类型,数组名,元素数, 如short mouths[12]
数组的下标总是从0开始到元素数减1结束;如果下标超界,编译器不会报错,但可能破坏数据或代码也可能异常终止。所以必须确保有效下标。
long kk[10]={10,12,6856,12}; //ok
long jj[10];//ok
jj[10]={1,2,3};//not allowed
long cc = jj;//not allowed
//数组初始化,有逗号隔开,大括号里元素可以少于元素总数,数组的这种初始化只能用与定义数组的时候。也不能把一个数组赋给另一个数组
cout<<sizeof kk;//输出kk这个数组的字节数,有40个字节
cout<<sizeof kk[1];//输出kk这个数组的第二个元素的位元组数他有4个字节
long kk[15]={0};//将没个元素都初始化为0的方法,为被定义的元素自动初始化为0。
long kk[]={0,523,54,3,4};//编译器计算出[]内的元素个数,这里为5个
long long_kk=sizeof kk/sizeof(short);//我们不知道数组的个数是多少,这样就知道了
4.2 字符串
c++处理字符串的方式有两种1:来自c语言,常被称为c-风格字符串;另一种基于string类库
定义两个char型数组:
char dog[5]={‘a’,’b’,’c’,’d’,’c’};//定义 了一个char型数组,储存的不是一个字符串
char cat[5]={‘a’,’b’,’c’,’d’,’\0’};//储存的是一个字符串,到空字符结束。
//在确定存储的字符串所需的最短数组时,别忘了将结尾的空字符计算在内
另一种初始化字符串的方法:char kk[]=”nihao!!”;
//编译器会在字符串最后加上”\0”字符;字符串用双引号,字符单引号
拼接字符串常量:下面的语句是等效的。
cout<<”我们可以将字符串分开””写,但双引号紧靠着,中间无符号”;//不建议采用这种方法
cout<<”我们也可以将字符串直接写在一对双引号内”;
cout<<”我们也可以将字符串分开写,”
”并像这样放在两行里,第一行末尾没有分号”;//这中方法是解决一行内字符串太多,分行写
strlen()函数是标准函数库cstring的函数 用来确定字符串的长度。
char kk[15]=”nihao!”;//strlen只计算可见字符,不把空字符计操作数在内
cout<<strlen(kk)<<” ” <<sizeof(kk);//sizeof是确定数组的长度
kk[3]=’\0’; //当cout读到’\0’时变停止
cout<<kk<<” ”<<kk[5];//后面的字符忽略(未被清空),’/0’有截取字符的功能
打印如下:6 15 nih !
读取一行字符串的输入:istream中的类(如cin)提供面向行的类成员函数:getline()和get().
getline()将丢去换行符,而get()将换行符保留在输入序列中。
getline()有两个参数,第一个是数组名第二个是读取字符数-1(如若是20,最多度19个)
在读取指定数目的字符或遇到换行符时停止读取。不保存换行符,最后用空字符代替。
get()有几个变体。其中一个与getline相似他们接受参数相同,解释参数也相同。
该函数并不是用空字符代替换行符,而是插入,并将换行符保留在输入列中,这样get()将无法跨行,因为下个get()一开始就读到了换行符,并有把他保存在输入队伍中.
cin.get(kk,20);
cin.get();//get()另一个变体cin.get()可读取一个字符,即使是换行符,这样就可以保留在输入列中
cin.get(mm,20);
我们可以将两个类成员函数合并:cin.get(array,200).get();//第一个get()返回一个cin对象,该对象随后被用来调用第二个get()函数。同样:cin.get(array,200). cin.get(array,200);也是可以的等效于调用两次getline()。而cin.get().get()则不行,以为第一个get()不返回对象.
混合输入字符串和数字:
int a; char kk[100];
cin<<a;//如果就这样将跳过下一行,有一个回车;取消回车的方法:(cin<<a).get();//加括号
cin.getline(kk,100);//如果就这样,我们将无法输入字符串就跳到下一行,因为上一行有回车
c++程序长使用指针(不是数组)来处理字符串
4.3 string类简介
string类包含在头文件string里,且位于名称空间std中。string对象的方式与使用字符数组相同:可以使用c-风格字符串来初始化string对象;可以使用cin来将键盘输入存储到string对象中;可以使用cout来显示string对象;可以用数组的表示法访问其中的字符
理论上,char数组是存储一个字符串的存储单元,string类变量是一个表示字符串实体
string str1=”kjlsamdl”,str2,str3;//string对象我们可以看做是一个变量,可以连续定义
str2=str1;//我们可以将以个string对象赋给另一个string对象
str2+=str1;//我们可一将string对象相加,+=是将以个字符串附加到另一个string对象的末尾
str2+=“nikan”;//我们也可以将一个string对象的末尾加上一个字符串
string类是c++新增的string库来处理输入的字符串,c语言中的字符串可使用头文件cstring提供的函数来完成
char c1[20]=”jjjj”,c2[20];//数组也可以连续定义,要注意不要超出数组的大小。
strcpy(c2,c1);//strcpy()能将c1中的字符串赋值到c2中,不能超出数组的大小,会破坏数据;发生错误。
strcat(c2,”kkkk”) ;//strcat()函数能将字符串”kkkk”附加到c2字符串的末尾处
cout<<c1<<’\t’<<c2<<’\t’<<strlen(c1);//strlen()也是cstring提供的函数,能读取数组中字符串的大小
打印结果:jjj jjjkkkk 4
string str=“123”;//如果没有初始化,str为0个字节,他能够随着输入字符串的大小自动调节
getline(cin,str);//string对象的引入比istream晚很多,所以getline并不是string类方法,只能创建一个string类的友元函数。因此只能这样调用。
int kk=str.size();//size()是string对象的方法,他能够读出str内的字符串个数为3(不带’\0’空字符)
4.4 结构(struct)简介
结构可以存储多种类型的数据。
定义结构描述:1它描述并标记了能够存储在结构中的各种数据类型;2按描述创建变量
每个列表项都是一条声明语句,每一个声明语句都是一个结构成员
struct inflatable goose;//定义结构变量 这种风格是c语言中的
inflatanle vincent; //c++可以省略struct关键字
goose.price就相当于一个double类型的变量,可以像常规使用double变量那样来使用它们,访问类成员函数就是从访问结构成员这里衍生来的,结构也是c++oop(类)堡垒的基石
struct inflatable
{ char name[20];
float aa;
double bb;
// inflatable是标签成为新的类型的名称;name、aa、bb是结构成员;最后的分号结束结构声明。当然我们可以不加结构名称inflatable而建立以个结构变量kk,用kk来调用其结构的成员,但因为没有结构名称,所以不能定义其他的结构变量,这样后续程序将不能使用该结构
}kk= //我们可以在定义结构时直接定义结构变量,我们也可以直接对其初始化。
{“leilei”, //初始化结构变量之间必须用逗号。
12.3, //要用逗号。c++不提倡使用外部变量,但提倡使用外部结构声明,还提倡外部声明符号常量
6.8}; //最后一个成员变量值后面不用加逗号,大括号的后面一定要加分号。
inflatable mm={“leilei”,12.3,6.8};//我们可以直接对结构变量进行初始化,成员间用逗号,末尾用分号
inflatable ll;ll=mm;//我们可以将结构赋给另一个同类型的结构
结构数组:
inflatable kk[2]= //结构数组是一个数组,而不是一个变量,这样数组中的每个值都是一个结构变量
{ {“shuzu0”,0.5,13.546}, //每个结构数组变量初始化,用{}扩起来,每组变量用逗号, 可放一行也可分开
{“shuzu1”,513.1,56.133}};//结构数组变量之间也用逗号进行分隔,也可以放在一行内
结构中的位字段
4.5 共用体(union)
是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。结构能够同时存储各种类型,而共用体只能存储一种类型,因此共用体的长度为其最大成员的长度。公用体的用途之一是当数据项使用两种或更多种格式(但不会同时使用)时,可以节省空间
union mingcheng{long long_aa;bouble bouble_aa;}bianliang;//语法与结构一样,但每次只调用一个成员,可直接定义变量
cout<<bianliang.long_aa;//输出成员变量的值
匿名共用体:没有名称,其成员将成为位于相同地址处的变量。显然每次只有一个成员是当前的成员
struct inflatable{char name[20];double hehe;union{long long_aa;double double_aa;};};
inflatable jiegou_bianliang;cout<<jiegou_bianliang.long_aa;//匿名共用体成员被视为结构的成员,可直接调用
4.6枚举类型(enum)
提供了另一种创建符号常量的方式,这种方式可以代替const。也可以定义新的类型
enum kk{a,b,c,d,e};//kk被称为枚举,a.b.c等被称为枚举量,第一个枚举量为0,往后依次类推
kk band = d;//枚举变量只能等于枚举量,不能等于其他非kk枚举的枚举量
band = kk(12);//我们可以通过枚举来给枚举变量赋值,通过这种方法给枚举变量赋值的范围为:
上限:比这个枚举量的最大值大的最小的2的幂的值减一,如:上式中最大枚举量是4,比4大的2的幂为2^3=8,那上限是2^3-1=7;下限:如果不小于零则下限是0;如果小于零,则为小于最小枚举量的最大2的幂加一,如最小为-6,则最小范围为-(2^3)+1=-7
选择用多少空间来存储枚举由编译器决定,对于范围小的枚举使用一个字节或更小的空间;
enum kk={a,b=0,c=100,d,f};//枚举量可以相同(a和b的枚举量都为0),当c=100,则d=101,f=102
4.7指针和自由存储空间
c++基本原理:面向对象编程与传统的过程性编程的区别在于,oop强调的是在运行阶段而不是编译阶段进行决策。指针用于存储值的地址,指针名表示的是地址。*操作符被称为间接值或解除引用操作符,如m表示的是一个地址,*m表示储存在该处的值。
int* p_kare=&kk;//被初始化的是指针本身,确定指针指向的变量,而不是确定它指向的变量的值。
操作符*两边的空格是可选的。c程序员使用这种格式:int *ptr;而c++使用这种格式:int* ptr;在c++中,int*是一种复合类型,是指向int的指针。
int* p1,p2;//这样将创建一个指针p1和一个常规int变量p2。对于每一个指针变量名,都需要使用一个*。
int*a;*a=23;//未初始化的指针的危险。应养成在定义指针时将指针初始化为一个确定的、适合的地址的习惯。
int* pt=0xb8000000;//错误。c++不允许将一个整型赋给指针,指针类型与整型是不一样的。
int* pt=(int*)0xb8000000;//我们可以通过强制类型转换将整型转换为适当的地址类型。
为一个数据对象(可以是结构,也可以是基本类型)获得并指定分配内存的通用格式如下:typename pointer_name =new typename;
int* ps=new int;//定义一块新的内存区域
int* pn=ps;//不要创建两个指针指向同一个内存块的指针,因为这将增加错误删除同一内存块两次的可能。
delete ps;//删除指针指向内存块而不是指针的值,释放ps的内存,但不会删除指针ps本身。可将其指向另一个新内存块
delete的使用①一定要配对使用,否则将发生内存泄露,被分配的内存将无法再使用了,如果泄露严重,程序将由于不断寻找更多内存而终止②不能释放已释放的内存块,否则结果将不确定,这意味着什么情况都可能发生③不能释放声明变量所获取的内存,不过,对空指针使用delete是安全的。
在编译时给数组分配内存被称为静态联编,意味着数组是在编译时加到程序中的,这种叫做静态数组;可以在程序运行时选择数组的长度被称为动态联编,意味着数组是在程序运行时创建的,这种叫做动态数组。
为数组分配内存的通用格式如下:type_name = new type_name [num_elements];如:long* p_kk = new long [100];
释放一个new[]数组要用delete [] zhizhenming;
动态数组的使用
int* a = new int [2];a[0]=0;a[1]=1;//初始化。可以将他看成int a[2]数组来处理,a存储的地址为数组第一个值的地址。
a+=1;//此时a[0]=1; a-=1;//此时a[0]=0
delete [] a;//将指针的值切换为数组的第一个值的地址,给delete[]提供正确的地址,便于释放。
4.8指针、数组和指针算术
指针和数组基本等价的原因在于指针算术和c++内部处理数组的方式
规范一下:*p不是指向类型的指针,而是完全等同于一个类型的变量;p才是指针。
将指针变量加一,就是增加的值等于指向的类型占用的字节数。如:long* a;a++;//a指针变量保存的地址加4
*(pointname+j)=pointname[j]或者arrayname[j]=*(arrayname+j)
//数组表示法与指针表示法之间区别区别:①可以修改指针值,而数组名是常量;②sizeof操作符对数组得到的是数组长度,而对指针得到的是指针的长度,即使指针指向的是一个数组。
指针和字符串:数组和指针的特殊关系可以扩展到c-风格字符串。
char flower[10]=”nihao”;//常规定义一个char型数组来存储字符串
cout<<flower<<”haizaima?\n”;//flower打印时并不是打印第一个字符,而是打印从该地址起往后的字符串,直到遇到‘\0’//后面”haizaima?\n”字符串打印,cout只知道第一个字符的地址,打印直到遇到’\0’结束
在cout和多数c++表达式中,char数组名、指向char的指针以及应用引号的字符串常量都被解释为字符串第一个字符的地址。
const char* pp=”nihao”;// ”nihao”表示是其第一个字符的地址,所以pp所保存的地址为字符串第一个字符的地址。形式与char型数组一样,但char型数组的数组名可以重新定义数组的字符串,但是常量字符串const不能被重新定义。
cout<<flower<<endl<<(int*)flower;//第一个打印的是字符数组中的字符串,第二个打印的是第一个字符的地址。
char型数组在初始化后重新定义时,初始化的字符串将被清空而重新定义
警告:在将字符串读入程序时,应使用已分配的内存地址,该地址可以是数组名也可以是new初始化过的指针。如果给cout提供一个指针,他将打印地址。但如果指针类型为char则cout将显示指向的字符串。如果要显示字符串的地址,则要用强制转换符转换成另一种指针类型,对其进行转换cout<<(int*)p<<endl;
strcpy()可以将一个字符串数组复制给另一个字符串数组:atrcpy(shuzu1,”zif”);//也以将字符串复制给数组
但当数组的空间不足时,会超出数组内存,超出部分将覆盖数组后面的其他内存;这样讲会影响程序运行,因此我们用strncpy这个函数来复制如:strncpy(shuzu,”nai znlls”,5);//它将字符串的前五个字符付给了数组,但它不能添加空字符‘\0’
所以要设置 shuzu[5]=’\0’;//我们要添加语句,确保字符数组的最后为空字符,要不然它存储的不是字符串了
使用new创建动态结构:在运行时创建数组优于在于编译时创建数组,对于结构也是如此。
struct inflatable{ char name[20];float volume ;double price;};//创建结构模板 ,定义其中的结构成员。
inflatable *ps = new inflotable;//定义一个指针指向在堆中创建的结构;ps表示指向结构的指针,*ps是表示结构变量
cin.get((*ps).name,20);//由于创建的结构变量没有名称,而只有指向他的指针,所以可以用*ps表示结构名称。
cout<<ps->name<<endl;//指针不是结构变量名称,不能用句点符,而要用->来访问结构成员。
记住:结构变量名来访问成员时用句点符(.),当用指向结构变量名的指针来访问成员时要用->操作符
第五章 循环和关系表达式
第五章的主要内容:
①for循环 ②表达式和语句 ③递增和递减操作符:++和-- ④组合赋值操作符 ⑤复合语句(语句块)⑥逗号操作符 ⑦关系操作符 ⑧while循环 ⑨typedef工具 ⑩get()字符输入方法 ⑾文件尾条件 ⑿嵌套循环和二维数组
for循环:其中的判断表达式都能转换成bool型,如判断表达式为i,若i=1为真,若i=0为假,而所有的表达式也都可以转化成bool类型的true或者false类型;c++表达式都是值与操作符的组合,每个c++表达式都有值。
maid=(cooks=4)+3;//在c++中可以这样做,但是不提倡这样做,这样只是为了让x=y=z=0;这样的语句存在
long a=100;cout<<a>1; //a>1这个表达式为真成数值1,他将显示一个数字1。要成为表达式就必须能确定其值。
cout.setf(ios.base::boolalpha); //将输出结果转化成bool类型,同时用true和false表示,而不是1和0
cout<<a<3; //设置以后就不显示数字0了,而是显示一个false
定义一个const值来表达数组中的元素个数是好的习惯。在声明数组和引用数组长度时,可以使用const值。
在string类的size()获得字符串中的字符数,如:string word ;cin>>word;int kk=word.size();
a++//表示先使用当前的,使用完后就加一。 ++a//表示先加一后,在使用其值。
组合赋值操作符:有+= -= *= /= %=
复合语句(也叫语句块):单独的一对大括号就是一个语句块,在一个语句块内定义的变量到语句块外面就释放了
逗号操作符:逗号操作符的优先级是最低的。如:i=20,j=i*2;//两个语句是有先后顺序,翻过来是不行的
for(long i=0,j=10;i<j;i++,j--)//逗号操作符一般用于for循环语句中。这个循环可以将字符串中的字符反过来。
关系表达式:< > <= >= == !=;
//for第二个关系表达式如果为赋值表达式则其表达式的值是true
c-风格字符串的比较:我们要用到cstring类库中strcmp()可以比较两个字符串的大小,是否相等。如果两个字符串相同则该函数返回的值为零;如果第一个字符串按字母顺序排在第二个字符串之前,则返回一个负数;如果第一个字符串按字母顺序排在第二个字符之后,则返回一个正数。char aa[20];if(aa==”nihao”)//错误,这是比较两个字符串地址。正确的比较是:if(strcmp(aa,“nihao”)==0)
string类字符串的比较:string类的比较字符串方法是比较简单的。
string str1;str1 == “nihao”;//这里比较的是两个字符串,并非比较的是内存地址。
5.3while循环
while(1);{…}//分号是一个结束语句,while是没有循环体,是一个死循环,编译时什么也不动
用whlie循环来计时:在ctime头文件中clock()可以解决计时问题。ctime提供了以个符号常量clocks_per_sec,该常量等于每秒钟包含的系统时间单位数。将系统时间除以这个值将得到秒数,将秒数除以这个变量可以得到以系统时间为单位的时间。clock_t是clock()函数返回类型的别名, 我们可以将变量声明为clock_t类型,他表示long、unsignde int或系统其他类型
类型别名:c风格的预处理命令#define 和 c++的typedef都可以来创建类型别名。
#define ch char*;//在编译时所有的ch都被替换成char*,这样ch kk;中的kk就是以个char型指针。这里用char*代替ch,但是如果定义 ch a,b;则会被解析成 char *a,b;但是typedef就不会出现这个问题,它能解决更复杂的情况。
typedef char* ch;//我们也可以这样,有时我们只能这样,这是c++风格 这里我们用char*来代替ch
do whlie循环:这种循环不如前两种,但他有他的特别用法,如让用户输入一 个数后在做判断,这个循环至少循环一次。