c++数组

所有C++11的都没看

数组:

1、数组声明(就是create):类型+数组名+元素个数(整形常数或const或常量表达式,就是不能是变量,编译的时候数组长度应该是已知的,也就是说要是常量表达式)short months[20];
在声明语句中初始化数组元素int yamcosts[3] = {20, 30, 5};,如果没有初始化数组,元素的值是不确定的,那么元素的值就是分配的位置上以前元素的值,默认初始化
数组的元素为对象,所以没有引用的数组,定义数组是也必须指定数组类型,不能用auto
初始化时也可以float hotel[5] = {5.0, 2.5};提供的值可以少于数组元素的数目,这样是给前两个元素赋值,如果只对数组部分元素初始化,其他元素默认初始化为0,初始化时[]可以为空,编译器会自动计算元素个数int things[] = {1, 5, 3}
sizeof如果用于数组名,返回的是整个数组的字节数
数组之间不允许拷贝和赋值,只有声明数组的时候才能初始化,之后就不可以,因为数组名是一个常量指针,也不能将一个数组赋值给另一个数组
复杂数组声明:int *p[10];是指针数组 int (*p)[10] = &arr; int (&p)[10] = arr;是数组指针和数组引用 在默认情况下,类型修饰符从右到左依次绑定,有括号先读括号

C风格字符串:

可以将字符串存储在char数组中 C-风格字符串的特殊性质:以空字符'\0',空字符\0就是0,结尾char cat[8] = {'r', 'i', '\0'},这是区分数组和字符串的关键,但打印的话到空字符(只要是空字符就截止,无论是哪里的空字符name[3] = '\0'这样第5个以及后面的元素打不出来)就截止了,它不会被打印出来
字符串常量就不用用一个个字符取初始化char bird[11] = "Mr.Cheeps"; char fish[] = "Bubbles";将字符串读到char数组中会自动加上空字符,如果字符串没有数组元素多(一定要记得把空字符算进去),拿出了自动加的空字符其余全是空字符。如果放不下会报错,而不会把前面的放进去
拼接字符串常量cout<<"abc" "def";第一个字符串的空字符会被第二个字符串的第一个元素取代,strcpy(char1, char2) strcat(char1, char2)分别是拷贝字符数组和拼接字符数组的函数
strlen()返回到数存储在数组中字符串的长度而不是数组本身的长度是不计算空字符的
字符串输入:cin是通过空格换行符来确定字符串结束的位置,它只会读取一个单词然后把他放在数组中并在结尾添加空字符
cin.getline(要存储到的数组的名字,要读取的字符数(如果是20,则只能读到19))是读取整行,通过回车确定结尾,他会读取换行符但会把它丢掉
cin.get(name, size)他也是读取一行,它不再读取并丢掉换行符,换行符会被留在输入队列中,因此连用两次该函数的话会出问题,要加cin.get()这是读取一个字符的 还可以把两个函数拼接在一起 cin.get(name, size).get() cin.getline(name, size).getline(name, size)
疑问:cin在读取的时候会把空格和换行符留在输入中吗? 解答:当cin>>从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理。

c++string类:

这样就使用string类变量而不是字符串数组来存储字符串 string可以用数组表示法访问存储在string对象中的字符
我们可以用c类型字符串给string赋值
string对象的优点是长度可以自动调节string a = "p"; a = "ppppppppppppp";,(未被初始化string对象长度为0)而不是像数组长度是固定的可以将char数组是为用于存储一个字符串的char的存储单元,而string类变量是表示字符串的实体
我们不能将一个数组赋值给另一个数组,但可以将一个string对象赋值给另一个string对象 可以使用+对字符串进行拼接
str.size()确定长度,strlen()是一个函数(返回的长度不包括空字符,空字符不是空白字符)size()是一个类方法,这里需要#include <cstring>
字符串输入:getline(cin, str1);这个不是类方法,cin当作参数指出去哪查找输入,也可以直接用cin cout输入输出string类对象
不能用char *c = s;可以char *c = s.c_str();这个函数返回的是c类型字符串也就是一个指针
疑问:char chars[20]; strlen(chars)为27书第87页

结构:

结构是一种新的数据类型。数组只能存储一种数据类型,而结构可以存储多种。我们也可以使用结构数组
创建结构变量:结构类型+名字 可以用名字.成员来进行访问 初始化inflatable duck = {"Daohne", 0.12, 9.98};如果成员是字符数组的话可以初始化为字符串
结构之间可以进行赋值,会让每个成员值都相等,即便成员是数组也可以
结构类型+名字的时候都已经开辟了一块内存了,就是创建,数组,整型都是
结构如果放在函数里就只能这个函数用?——在确认一下
可以将结构的描述和创建合在一起,只要将变量名放在}的后面,;的前面就行, 还可以描述、创建和初始化放在一起,还可以省略名称但要创建一个变量(这样没啥意义,不好)
结构数组(以结构为元素)它本身是一个数组,而不是结构。初始化结构数组inflatable gueets[2] = { {"Bambi", 0.5}, {"Godz", 2000} };
结构中的位字段不想看了~

指针

要找到一个变量的地址,只要取地址就行了,用的是16进制表示的
面向对象编程强调是在运行阶段进行决策,比如传统情况要创建一个数组必须要指定数组的长度,这在编译阶段就设定好了,而C++将他推迟到运行阶段,这一次可以需要20个,下一次可以需要204个
我们用指针存储值的地址,指针名表示的就是它的地址 *表示的是地址指向的值,地址只是对象存储地址的开始,因此要指出指针的类型
指针的创建:指针指向类型+ * +名字 但不同类型的指针的长度是相同的 但要注意指针并不是整数(虽然计算机经常把地址当作整数处理,但两者并不是同一种类型),因此不能简单地将整数赋值给指针,要将他转化为指针类型才可以
注意:我们在*pointer之前,一定要给指针一个确定的地址,否则就是野指针了,会发生错误

动态分配内存

使用new来分配内存:指针真正厉害的地方是用在运行阶段分配未命名的内存来存储值,这时只能用指针来访问内存,大小必须要是整数 new右边是指针要存储的值的类型,new找到一个合适的内存,并返回地址,这样就将地址赋值给指针了,动态分配的对象一般是默认初始化的 int* p = new int;new完了之后一定要记得deletedelete p;,delete表达式接受一个指针,指针必须指向动态分配的对象或者空指针,只能删一次,删完就不能再删了
动态对象在被显式删除之前都是存在的,有可能指针离开了作用域,但动态对象还是没有被删除 指针被delete之后会变成空悬指针,原本指向数据对象但现在已经无效了,我们可以给他赋值nullptr保护她
对于空指针也可以使用delete,不一定非要是p这个指针,也可以是别的指针,其实是作用于new之后分配的地址,delete也只能删除new的
使用new创建动态数组:就是可以根据程序的运行动态的创建合适大小的数组 int* psome = new int[10];[]中必须是整形,但不一定是常量
要注意我们所说的动态数组其实并不是得到了数组类型的对象,而是得到了一个数组元素类型的指针,所以sizeof,begin,end不能用
我们不能声明char[0],但可以new char[0],只是不能解引用,这个指针有点像尾后指针
(new运算符返回到是第一个元素的地址,数组指针是指向第一个元素的,他是指向int的,因此是int*类型) delete [] psome;带[]的意思是要删除整个数组而不仅仅是指针指向的元素,如果我们忘了方括号,那么行为是未定义的,不是删除第一个元素
动态数组不能用sizeof()来确定字节数
使用动态数组:第一个元素是p[0],第二个是p[1]…直接把指针当作数组名来使用,指针加1的时候就会指向下一个元素,增加了了4个字节(int的话)
地址就是指针

使用动态内存的目的:1、不知道自己要使用多少对象(如容器初始化) 2、程序不知道所需对象准确类型 3】程序在多个对象间共享数据
如果两个对象共享的底层数据是同一个东西,那某个对象被销毁时,我们不能单方面销毁底层元素(只有动态内存能做到。。这是要自己设计的)

指针、数组和指针算术

c++会将数组名解释为第一个元素的指针(首元素的地址可以看作是与数组分开的,仅仅是首个元素的地址,是指向int的,和数组无关) stack[1]*(stack+1)是等价的,c++在编译的时候会把数组的形式转化为指针 在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针,编译器转换为&arr[0]
如果我们想得到数组尾元素的下一个地址 int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int *p = &arr[10];这样也是可以的,但不能对p解引用或递增,因为尾指针不知想具体的元素 解引用只有当指针指向了一个对象时才能使用,其他情况都不可以 指针最多只能指到对象的下一个位置,
指针运算:如果两个指针分别指向不相关的对象,那对他们相减货比较毫无意义,因此他们要指向同一个数组/尾后 指针加减某个数得到的新指针也要在数组中/尾后 如果是空指针也可以相减 *(ia + 4) 等价于 ia[4]编译器会将后者转换为前者
数组名是常量,不能修改 数组用sizeof()得到的是数组的长度,而对指针用sizeof()得到的是指针的长度,此时c++不会将数组名解释为地址
对数组名用取地址运算符时,得到的时整个数组的地址,此时数组名也不会被解释为地址(把&a当作一个整体就好了,不要想他们分开的含义) &tell[0]是一个4字节的内存块地址,而&tell是一个20字节内存块的地址,因此tell+1只会加4,而&tell+1会加20,换句话说tell是一个int指针,而&tell指向的是整个数组,可以看作是“数组指针”(自己起的名),要这样声明:short (*p) [30——元素个数] = &lalala,如果不加()的话就变成指针数组了 这里p和lalala等价,因此(*p)[0]是数组的第一个元素因为p = &lalala -> *p = *&lalala = lalala;
指针和字符串:
C风格字符串数组的首元素地址就是char元素的地址,而在打印时。如果给cout提供一个字符的地址,他将从该字符进行打印,直到遇到空字符为止,在c++中,用引号括起的字符串和数组名一样,也是第一个元素的地址 cout<<"flower, lalala";这里不会将整个字符串发送给cout,只会将第一个元素的首地址发送给他(所以这里也可以用指向字符串的指针来打印字符串) 因此在这里以及很多情况下char数组名,char指针以及"这是字符串"的处理方式是一样的,都被当作首元素地址
字符串的字面值被视为只读常量,是不能被修改的,因此const ps = "zifuchuan";,不能使用
ps,会发生错误
在使用cin>>数组名/指针时,是要将输入读入到地址所存储的值中(如果指针没有初始化的话这么做会引起错误)在将数组读入程序的时候,应该使用已分配的内存,如果我们要打印出字符串的地址,那么就需要将数组名或指针转化为(int*)类型(所以这里我觉得可以把数组名当作指针)
strcpy(目标地址, 要复制的字符串的地址)这样就可以获得一个字符串的副本,要注意我们不能使用赋值运算符将字符串赋值给数组。要用这两个函数。如果要赋值的字符串长度大于数组的长度,那就要使用strncpy()这个函数多了一个参数,代表要复制的最大字符数,要注意留好空字符的位置
使用new创建动态结构:inflatable * ps = new inflatable;因为new返回的是地址值,所以用的是指针。在使用动态结构的时候,不能使用 . 来访问成员变量,因为就没有结构的名称,只有地址,因此用指针->成员 或者是(*指针).成员来进行访问,结构名不是结构的地址,要使用&运算符
自动存储:局部变量是用的自动存储空间,作用域就是代码块,一般是存储在栈中 静态存储:整个程序执行期间都存在让变量成为静态有两种方法,一种是在函数外定义,一种是加static 动态存储:就是new的空间,是存在堆当中的,可以在一个函数new在另一个函数delete,一定要记住delete,否则可能内存泄漏
有关符合指针的问题一定要将思路搞明白?自己看看黑马的代码
数组的替代品:vector类,有点像ArrayList,#include <vector> using namespace std; vector<double> name(n)需要建立一个vector对象,如果不说长度就默认初始长度为0,可以插入、添加新数据等,也是用的动态数组,n可以是变量 array类:如果是长度固定的数组,用array比用vector效率更高,#include <array> using namespace std; array<double, 5> name;这里的长度只能是常量 vector对象和array对象都可以用标准数组的表示方法访问操作元素,要注意可以将array对象直接赋值给另一个array对象

多维数组:

所谓的多维数组就是数组的数组,就是数组的元素还是数组int ia[3][4];大小为3的数组,每个元素是大小为4的数组,第一个是行,第二个是列
涉及数组的声明由内向外读更好
初始化int ia[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}; int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};是一样的 int ia[3][4] = {{0}, {4}, {8}};只初始化每行首元素,其他默认初始化 int ia[3][4] = {0, 1, 2, 3, };只初始化第一行,剩下的默认初始化
如果数组用到的维数比声明的维数小,说明这是一个数组
要使用范围for语句处理多维数组,除了最内层的循环,其他循环的控制变量都要是引用类型
定义指向多维数组的指针时,别忘了多维数组是指向数组的数组 要注意ia[2]也是数组名,他是指向第三行第一个元素的地址
ia是第一个数组的地址,对应的指针是数组指针,*ia是ia[0]其实是第一个数组,也就是第一个数组的第一个元素的地址

共用体

共用体可以存储不同类型的变量,但只能存储一种,先存int,在存double那int就会消失
如果是结构体中有匿名共用体使用的时候直接用共用体中变量不用打共用体名字
sizrof是最大值长度

枚举

用枚举相当于把枚举的信息赋从0~n的值,也可以自己赋想要的值,如果前一个有值后一个没有,那后一个比前一个大一 枚举类相当于一个集合,声明枚举变量的时候如果要赋值的话需要把集合里的东西给他,而且不能给其他的东西,只能在集合里,不能用数字,枚举量可以转化为int(整形提升),但int不能变为枚举量 枚举变量没有定义算术运算符,只有等号,加号什么的不能出现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值