1.如何通过字节来计算数组长度
short things[]={1,6,4,7}
int num_elements = sizeof things/sizeof(short);
2.初始化数组可以省略等号=
float earning[4] {1.2e4,1.6e4,1.1e4,1.7e4};
3.可以不在大括号内包含任何东西,这将把所有元素
float balances[100] {}; //将balances中所有的值设为0
4.列表初始化禁止缩窄转化
long plifs[] = {25,52,33.0}; //浮点数转化为整数要缩窄操作,即使小数点后为0 我的编译器可以!!!!
char slifs[] = {'h','i',1111111,'\0'}; //111111超出char的取值范围
char slifs[] = {'h','i',33}; //可以通过编译
5.将字符数组初始化字符串
char bird[11]="Mr.Cheeps";
char fish[]="Bubbles";
6."S"和’s’的区别
char shirt = 'S'; //可以通过编译
char shirt = "S"; //无法通过编译 这里"S"表示'S'和'\0'
7.拼接字符串:
以下三句话输出效果完全相同
cout << "i'd give you my heart";
cout << "i'd give" "you my heart";
cout << "i'd give you"
"my heart";
注:
1.c++将两个用引号括起来的字符串合并为1个
2.任何两个有空白(空格,制表符,换行符)分隔的字符串常量都自动拼接为1个
3.拼接时,第一个字符串常量中的\0将被第二个字符串的第一个字符取代
8.字符串strlen只返回有效字符的个数,不是字符数组的长度,比数组长度少1,是最后一个\0
9.见代码
name[6]="abcde";
name[2]='\0';
cout << name; //则此时输出的是ab
10.cin使用空白(空格,制表符,换行符)来确定字符串的结束位置
#include<iostream>
#include<cstring>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin >> name;
cout << "Enter your favorite dessert:\n";
cin >> dessert;
cout << "I have some delicious " << dessert;
cout << "for you, " << name << ".\n";
return 0;
}
如果输入Alistair Dreeb
首先遇到中间的空格,c++将Alistair存储到name数组中并且自动在字符串末尾添加空字符\0,Dreeb则保存到队列中,再下一次遇到cin时则直接将Dreeb存储到dessert数组中。
11.面向行的输入:getline()和get()
- getline()
1.通过回车键输入的换行符来确定输入结尾,即把换行符改为空字符\0
2.通过函数cin.getline()具体实现
3.cin.getline(用来存储行的数组的名称,读取的字符数);
4.函数最多读取参数2(读取的字符数)减1,剩余一个空间留个空字符
5.getline()函数在读取指定数目的字符或遇到换行符时停止读取
2.get()
1.get()不会读取并丢弃换行符,而是将其留在队列里
cin.get(name,ArSize);
cin.get(dessert,ArSize); //这里只能读取一个字符并结束函数,因为在第一次输入完后敲下回车,换行符被保留在队里中,下一次遇到cin.get函数一开始就看到换行符,故,结束循环
//********可以使用下面语句*********
cin.get(name,ArSize);
cin.get(); //在调用一次cin.get()函数来接受第一个输入完后留在队列中的换行符
cin.get(dessert,ArSize);
// ********可以使用下面语句(get拼接的方式)*********
cin.get(name,ArSize).get();
// ********可以使用下面语句(getline拼接的方式)*********
cin.getline(name,ArSize).getline(dessert,ArSize);
2.get也可以这样使用
#include<iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name,ArSize).get(); //get写法:cin.get(name,ArSize)
cout << "Enter your dessert:\n";
cin.get(dessert,ArSize).get(); //get写法:cin.get(dessert,ArSize)
cout << "I have some delicious " << dessert;
cout << "for you, " << name << ".\n";
return 0;
}
这两个的区别在与cin.get(name,ArSize)让编译器知道将一个字符串放到数组中,如果使用cin.get()则编译器知道是要读取一个字符。
12.混合输入数字和字符串
有两种解决办法
#include<iostream>
int main()
{
using namespace std;
cout << "What year was your house built?\n";
int year;
cin >> year; //在这句话之后加上一条代码:cin.get();
//或者直接将这句代码改为(cin >> year).get();
cout << "What is its street address?\n";
char address[80];
cin.getline(address,80);
cout << "Year built: " << year << endl;
cout << "Address: " << address << endl;
cout << "Done !\n";
return 0;
}
结果就是只能输入数字但不能输入后面的地址
13.string类
1.使用string类必须包含头文件string,string类位于名称空间std中,string类根据用户输入的字符串度自动决定大小
2.可以用cout,cin,数组表示法来使用string
3.string对象与数组的区别在于string对象声明为简单变量,而不是数组
4.使用string来声明变量必须在前面有using namespace std;
或 std::string a;
#include<iostream>
#include<string>
int main()
{
using namespace std;
char charr1[20];
char charr2[20]="jaguar";
string str1;
string str2="panther";
cout << "Enter a kind of feline: ";
cin >> charr1;
cout << "Enter another kind of feline: ";
cin >> str1;
cout << "Here are some felines:\n";
cout << charr1 << " " << charr2 << " " << str1 << " " << str2 << endl;
cout << "The third letter in " << charr2 << " is " << charr2[2] << endl;
cout << "The third letter in " << str2 << " is " << str2[2] << endl;
return 0;
}
14.字符串string的初始化,赋值,拼接,附加
#include<iostream>
#include<string>
int main()
{
using namespace std;
string s1 = "penguin"; //字符串的初始化
string s2,s3;
cout << "You can assign one string object to another to another: s2 = s1\n";
s2=s1; //字符串的赋值
cout << "s1: " << s1 << ", s2: " << s2 << endl;
cout << "You can assign a C-style string to a string object.\n";
cout << "s2 = \"buzzard\"\n";
s2 = "buzzard";
cout << "s2: " << s2 << endl;
cout << "You can concatenate string: s3 = s1+s2\n";
s3=s1+s2; //字符串拼接
cout << "s3: " << s3 << endl;
cout << "s1 += s2 yields s1 = " << s1 << endl;
s2+=" for a day"; //字符串的附加
cout << "s2 += \" for a day\" yields s2 = " << s2 << endl;
return 0;
}
15.计算字符长度
string a;
char b[10];
a.size(); //表示计算字符串的有效长度
strlen(b); //表示计算字符串的有效长度
a是一个对象,而size()是一个类方法。方法是一个函数,只能通过其所属类的对象进行调用。在这里,a是一个string对象,而size()是string类的一个方法。in a word C函数使用参数来指出要使用哪个字符串,而C++ string类对象使用对象名和句点运算符来指出要使用哪个字符串
16.对string类读取一行字符串
#include<iostream>
#include<string>
#include<cstring>
int main()
{
using namespace std;
char charr[20];
string str;
cout << "Length of string in charr before input: "
<< strlen(charr) << endl;
cout << "Length of string in str before input: "
<< str.size() << endl;
cout << "Enter a line of text:\n";
cin.getline(charr,20);
cout << "You entered: " << charr << endl;
cout << "Enter another line of text:\n";
getline(cin,str); //LOOK HERE!!!!!! cin作为参数,没有指出字符串的长度,自动计算
cout << "Length of string in charr after input: "
<< strlen(charr) << endl;
cout << "Length of string in str after input: "
<< str.size() << endl;
return 0;
}
17.如果在字符串中显示\n,如码
#include<iostream>
#include<string>
#include<cstring>
int main()
{
using namespace std;
cout << " \\n\ ";
return 0;
}
18.外部声明和内部声明
#include<iostream>
using namespace std;
struct parts //this struct is uesd by all fomulates
{
unsigned long part_number;
float part_cost;
};
void mail();
int main()
{
struct perks //however this struct is only used by this function
{
int key_number;
char char[12];
};
}
19.now you must notice struct 初始化
inflatable guest = //注意等号
{
"Glorious Gloria", //注意逗号
1.8, //注意逗号
29.99 //注意无符号
};
inflatable duck {}; //注意这里直接将结构duck设为空结构,各个成员为0
//*******同样可以将string类作为成员******
#include<string>
struct inflatable
{
std::string name; //如果使用using namespace std的话不用输入std:: 直接string name
float volume;
double price;
}
20.初始化结构数组(其实guests[2]说是用结构数组表示,其实也就是表示对应的一个结构,因此结构也是用此方法来赋初值)
inflatable gifts[100]; //gifts[100]是长度为100的数组,数组的每个成员值都是结构体
inflatable guests[2] =
{
{"Bambi", 0.5, 21.99},
{"Godzilla", 2000, 545.22}
};
21.共用体:(https://blog.youkuaiyun.com/qq_37653144/article/details/70992347)
22.枚举类型:
enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};
此代码完成两条任务:
1.让spectrum成为枚举类型
2.将red,orange,yellow等作为符号常量,对应整数值0—7。这些常量叫枚举量
3.可以使用枚举名来声明这种类型的变量:
spectrum band;
23.在不进行强制类型转换的情况下,只能将枚举给枚举
band = blue; //wrong
band = 200; //wrong
24.枚举是整型,可被提升为int类型,但int类型不能自动转换为枚举类型:
int color = blue; //正确,因为blue是枚举类型,可以被提升为int
band = 3; //错误,3是整型,不能自动转化为枚举类型
color = 3 + red; //red是枚举类型,可以被转化为int类型与3相加
25.强制转化枚举类型
band = spectrum(3);
band = spectrum(3241534532); //可能会出错,有枚举的取值范围约束
26.设置枚举量的值
1.使用赋值运算符类显式设置枚举量的值(指定 的值必须是整数)
enum bits{one = 1 , two = 2 , four = 4, eight = 8};
2.第一个没有被设置的值默认为0,向后依次增大
enum bigstep{first, second = 100, third}; //其中first是0 third是101
3.可以创建多个值相同的枚举量
enum {zero, null=0, o1ne, numero_uno = 1}; //其中zero值为0, o1ne值为1
27.枚举的取值范围
首先,如下例子
enum bits{one=1, two=2, four=4, eight=8};
bits myflag;
myflag = bits(6); //其中6不是枚举值,但它位于枚举定义的取值范围
取值范围的定义:
找到大于枚举中的最大值,最小值的2的幂,将它减1,得到便是上界;如果枚举的最小值不小于0,则下界是0;如果枚举的最小值为负数,则用求上界的方法最后添上负号
for instance:
如,最大枚举值是101,则上界为127(128-1)
如,最小枚举值是-6,则下界为-7 (8-1完了再加负号)
28.指针的声明和初始化
int * p_updates; //*p_updates 是int类型,而p_updates是指针(地址)(是指向int类型的指针)
p_updates = &updates;
int *ptr; //cstyle , *两侧的空格是任意的
int* ptr; //c++style , int*是一种类型--指向int的指针
double* tax_ptr; //tax_ptr这个是指向double类型的指针
char* str; //str是指向char类型的指针
//这两个指针是不用类型的,但两个指针本身的长度是相同的
int higgens = 5;
int * pt= &higgens; //这里是将pt(不是*pt)初始化为higgens的地址
29.the dangerous of pointer
a statement : 计算机分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存
long* fellow; //fellow没有初始化,计算机随机分配一个地址 给 fellow ,比如 fellow的值为0x40d4eb
*fellow = 223323; //计算机认为这句话:存储223323的地址(就是将数据223323给fellow)
//此操作的目的救是,向对指针给定一个我想给定的地址,正确做法如下30
cout << fellow; //结果是没有任何输入输出,因为计算机不会分配用来存储指针所指向的数据的内存
long a;
a=100;
*fellow = a;
cout << fellow; //是可以的,显示地址的,切记a要赋值
以上是对书的理解,需要记住的是用指针*fellow不要去接受一数据(类似223323这样)
30.指针和数字
1.指针和整数是不同类型,不能将指针和整数进行加,减,乘,除,更不能将整数赋给地址
如:
int *pt;
pt = 0xB8000000; //wrong,会报错
//however the right operation this is :
int *pt;
pt = (int *) 0xB8000000; //需要注意pt是int值的类型并不意味着pt本身的类型是int,int类型是2字节值,地址是4字节值
31.使用new来分配内存
格式: typeName* pointer = new typeName;
实例:
int* pn = new int; /在计算机内存中找到一个int长度的空间,将该空间的地址返回给pn
同类:
int caonima;
int* pn = &caonima;
31.我发现在c++中还可以这样用 sizeof pa; 不用给pa加括号,前提是pa是指针
32.使用delete释放内存
使用实例:
int* ps = new int;
...
deleter ps;
注意:
1.释放ps所指向的内存,但不会删除ps指针本身,就是在后面的代码中,仍能使用指针ps,让其指向另一个新分配的内存
2.一定要配对使用new和delete
3.不要释放已经释放的内存块,只能用delete来释放new分配的内存,whereas for null pointer is right
for example:
int* ps = new int;
delete ps; //ok
delete ps; //wrong
int a =5;
int *pi = &a;
delete pi; //not allowed
4.使用delete可以释放new分配地址的地址
如:
int* ps = new int;
int* pq = ps;
delete pq;
33.使用new来创建动态数组
实例:int* psome = new int [10];
(只要将数组的元素类型和元素数目告诉new即可)
同样使用delete来释放
delete [] psome;
(方块告诉数组,释放整个数组)
注意:
int* pt = new int;
short* ps = new short [4000];
delete [] pt; //wrong
delete [] ps; //wrong
in a word,use new and delete,you should observe follow rules
- don’t use delete to release 不是new分配的内存
- don’t use delete to release the same 内存 twice
- 如果new有[]则delete有[] , 反之,无
34.使用动态数组
psome[0]表示数组的第一个元素,依次类推
35.数组指针指向数组元素的第一个,在移动了数组指针后记住要最后将数组指针放到初始位置,一遍方便给delete返回正确的地址
36.将指针变量+1后,其增加 值等于指向的类型所占用的字节数,short是两个字节,double是8个字节
37.使用数组名和指针来表示数组元素
int* pointer stacks;
stacks[2] = *(stacks+2);
stacks[3] = * (pointer +3 );
对于数组名使用sizeof是表示整个数组的长度(就是每个单元的字节数*数组元素个数)
对于指针使用sizeof表示指针对应类型的字节数
38.数组的地址
1.数组名是一个元素的地址
2.对数组名使用地址运算符时,得到的是整个数组的地址
e.g.
short tell[10];
cout << tell << endl; //数组名
cout << &tell << endl;
&tell[0](就是tell)是一个2字节的内存地址
&tell 是一个20字节的地址
对于tell+1表示+2
对于&tell+1表示+20
可以如下声明和初始化如下指针
short (*pas)[20] = &tell;
39.指针总结:
1.int* pa; 其中pa是指向int的指针, 而 *pa指向存储在对应存储单元的数值
40.指针和字符串:flower表示第一个元素的地址,代码不会将整个字符串给数组,而是发送该字符串的首地址
char flower[10] = "rose";
cout << flower << "s are red";
41.使用const表示字符串字面值
表示:bird是char类型的指针,指向“wren”字符串的第一个字符地址,并且使用const,则以后使用bird表示"wren",caution:because bird指针被声明为const,因此编译器将禁止改变bird指向的位置中的内容
const char* bird = "wren";
cout << "A concerned " << bird << " speaks\n"
//这条语句显示 A concerned wren speaks
42.使用强制转化来表示指针地址
使用 (int *)来表示地址
使用(char * )来表示该存储单元所存放的字符串
ps = animal; //此语句只是将animal的地址给ps,也就是ps和animal两个指针指向同一个单元地址
cout << anima << " at " << (int *) anime << endl;
cout << ps << " at " << (int *) ps <<endl;
43.使用new来根据字符串的长度配置字符数组
ps = new char[strlen(animal)+1];
44.使用strcpy和strncpy给数组分配字符串:
1.strcpy:
字符串赋值函数:strcpy(参数1,参数2) 参数1:目标地址 参数2:要复制的地址
2.strncpy:
此函数相比于strcpy多一个参数—要复制的最大字符数
strncpy(food,"a picnic basket filled with many goodies:", 19);
food[19]='\0';
表示最多赋值19个字符,数组中第19为结束符
45.使用new来创建动态结构和表示结构中的成员(3种方法)
两步走:
1.创建结构:
例如,创建一个未命名的inflatable类型,并将其地址赋给一个指针ps:
struct inflatable
{
char name[20];
float volume;
double pricre;
};
inflatable* ps = new inflatable;
2.访问成员值:
如果是结构名使用. 如,inflatable.name;
如果是指针使用->: 如,ps->name
如果是()指针使用. 如,()ps.name
46.BOOM!!! 这里将介绍一个储存多条字符串的方法
#include<iostream>
#include<cstring>
using namespace std;
char* getname(void);
int main()
{
char* name;
name = getname();
cout << name << " at " << (int *) name << "\n";
delete [] name; //name和返回的pn都是指向数组的地址,其中通过new将字符串放到数组中
name = getname();
cout << name << " at " << (int *) name << "\n";
delete [] name;
return 0;
}
char* getname(void)
{
char temp[80];
cout << "Enter last name:";
cin >> temp;
char* pn = new char[strlen(temp)+1];
strcpy(pn,temp);
return pn;
}
47.C++三大存储
1.自动存储:就是函数中所使用的变量,函数调用时使用该内存,函数结束时,程序收回该内存,而自动变量就是局部变量,其作用域为包含他的代码开块
2.静态存储:在整个程序执行期间都存在的存储方式,there are two ways to create static变量:
1.在函数外部定义变量, 2.use 关键字:static
3.动态存储:使用new和delete这俩个货,他们管理一个内存池,就是堆,将静态变量和动态变量的内存分开,可以在一个函数中new一个内存,同时,也可以在另一个函数中delete一个内存
48.结构数组:
strut fuck
{
int man;
int woman;
};
fuck a[3];
a[1].man=222;
也可 (a+1)->man=222;
49.指针数组:其中arp[1]就是一个指针,arp是一个指针数组
const fuck* arp[3] = {&s01,&s02,&s03};
访问其成员值:
std:: cout << arp[1]->man << std::endl;
指向数组的指针: ppa,ppb都是数组指针
const antarctica_years_end ** ppa = arp;
或者可以这样:
auto ppb = arp;
如何使用这两个数组指针:
std::cout << (ppa)->year << std::endl;
std::cout << ((ppb+1))->year << std:endl;
49.vector模板类:
1.它是一个动态数组,位于std名称空间
2.使用语法:
vector<typeName> vt(n_elem);
vt是vector的一个对象,它可以存储n_elem个类型为typename的元素,其中n_elem可以为整型常量,也可以是整型变量
3.vector对象在您插入或添加值时自动调整长度,因此可以将vt的初始长度设置为0
50.array模板类:
1.arry也是数组,array的对象长度是固定的,但它存储在栈中,不是自由存储区
2.使用如下:
#inclue<array>
...
using namespace std;
array<int ,5> ai;
array<double,4> ad= {1.2, 2.1, 3.43, 4.3};
声明创建一个名为arr的array对象,它包含n_elelm个类型为typename的元素
array<typeName,n_elem> arr;
注意n_elem不能是变量
50.对于数组来说:a[-2] 表示从第一个地址开始,向前移两个存储单元,等价于*(a-2) c++不检查这种错误操作,可以使用vetor和array的对象成员函数at():a.at(2)=3.3可以捕获非法索引,在程序中默认中断
51.声明一个vector对象和一个array对象,他们都包含10个string对象,指出使用头文件,不要使用using。使用const来指定要包含的string对象数
#include<string>
#include<vector>
#include<array>
int main()
{
using namespace std; //不要忘记namaspace std
const int string a {10};
vector<string> vstr(a);
array<string,a> astr;
}