c++第四章 复合类型 总结

本文深入探讨C++中数组的长度计算、初始化、字符数组的字符串表示、字符串的拼接与长度计算、string类的使用及初始化、赋值、拼接、附加操作,以及动态数组和指针的应用。此外,还介绍了结构体、共用体、枚举类型的基本概念与使用方法,以及C++中的存储类别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()

  1. 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值