C++ Primer Plus Chapter 4

本文介绍了C++中数组的使用,强调了数组大小必须是常量或常量表达式。还探讨了字符串处理,包括C风格字符串和string类的特性。接着,文章讨论了指针、内存分配(new运算符)以及释放内存(delete)。此外,提到了结构体、共用体、枚举和动态数组的创建与使用。最后,简述了vector和array模板类作为更安全的数组替代方案。
摘要由CSDN通过智能技术生成

数组 Typename arrrayname [arraysize] arraysize可以是常量或者常量表达式,但不能是变量。

#include <iostream>

int main(void)
{
	using namespace std;

	int yams[3];

	yams[0] = 7;
	yams[1] = 8;
	yams[2] = 6;

	int yamscosts[3] = { 20,30,5 };

	cout << "The total yams = " << yams[0] + yams[1] + yams[2] << endl;
	cout << "The package with " << yams[1] << " yams costs " << yamscosts[1] << " cents per yam." << endl;
	cout << "The total yams cost: " << yams[0] * yamscosts[0] + yams[1]*yamscosts[1] + yams[2] * yamscosts[2] << " cents." << endl;

	cout << "Size of yams array = " << sizeof yams << " bytes." << endl;
	cout << "Size of one element = " << sizeof yams[0] << " bytes." << endl;

	return 0;
}

字符串

 

 

 

 一个有缺陷的程序

#include <iostream>
#include<cstring>

int main(void)
{
	using namespace std;

	const int Size = 15;

	char name1[Size];
	char name2[Size] = "C++owboy";

	cout << "Howdy! I'm " << name2 << " What is you name?" << endl;
	cin >> name1;
	cout << "Well, " << name1 << " ,your name has " << strlen(name1) << " letters." << endl;
	cout << "And your name is stored in an array of " << sizeof name1 << " bytes." << endl;

	return 0;
}

揭露这个缺陷

#include <iostream>
#include<cstring>

int main(void)
{
	using namespace std;

	const int Arsize = 20;

	char name[Arsize];
	char dessert[Arsize];

	cout << "Enter your name: " << endl;
	cin >> name;
	cout << "Enter your favourate dessert: " << endl;
	cin >> dessert;

	cout << "I have some delicious " << dessert << " for you, " << name << " ." << endl;
	
	return 0;
}

 cin以空白确定字符串的结束,当读取到第一个空白时cin将结束读取(不读取空白字符,所以空白字符依旧留在缓冲区)。当第二次读取时接着从输入缓冲区中读取剩下的字符串。

#include <iostream>

int main(void)
{
	using namespace std;

	char name[20];
	char age[20];

	cout << "Enter your name: " << endl;
	cin >> name;
	cout << "Enter your age: " << endl;
	cin>>age;

	cout << "name: " << name << "age: " << age << endl;

	return 0;
}
但是cin读取到字符才会以空白字符为结束标志,否则即使上一次留下空白字符也会等待输入


 

 

 

 string类

#include <iostream>
#include <string>

int main(void)
{
	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;
}

 string类的赋值、拼接与附加

#include <iostream>
#include <string>

int main(void)
{
	using namespace std;

	string s1 = "penguin";
	string s2, s3;

	cout << "You can assign one string object to another: s2 = s1" << endl;
	s2 = s1;
	cout << "s1: " << s1 << ", s2: " << s2 << endl;
	cout << "You can assign a C-Style string to a string object." << endl;
	s2 = "buzzard";
	cout << "s2: " << s2 << endl;
	cout << "You can concatenate strings: s3 = s1 + s2" << endl;
	s3 = s1 + s2;
	cout << "s3: " << s3 << endl;
	s1 += s2;
	cout << "s1 += s2 yields s1 = " << s1 << endl;
	s2 += " for a day";
	cout << "s2: " << s2 << endl;

	return 0;
}

string类与传统方法的对比

#include <iostream>
#include <string>
#include <cstring>

int main(void)
{
	using namespace std;

	char charr1[20];
	char charr2[20] = "jaguar";
	string str1;
	string str2 = "panther";

	str1 = str2;
	strcpy(charr1, charr2);

	str1 += " paste";
	strcat(charr1, " juice");

	int len1 = str1.size();
	int len2 = strlen(charr1);

	cout << "The string " << str1 << " contains " << len1 << " characters." << endl;
	cout << "The string " << charr1 << " contains " << len2 << " characters" << endl; 

	return 0;
}

string类IO

#include <iostream>
#include <string>
#include <cstring>

int main(void)
{
	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: " << endl;
	cin.getline(charr, 20);
	cout << "You entered: " << charr << endl;

	cout << "Enter another line of text: " << endl;
	getline(cin, str);
	cout << "You entered: " << str << endl;

	cout << "Length of string in charr after input: " << strlen(charr) << endl;
	cout << "Length of string in str after input: " << str.size() << endl;

	return 0;
}

结构简介

#include <iostream>

struct inflatable
{
	char name[20];
	float volume;
	double price;
};

int main(void)
{
	using namespace std;

	inflatable guest = 
	{
		"Glorious Gloria",//注意与类型声明时的区别
		1.88,
		29.99
	};

	inflatable pal = 
	{
		"Audacious Arthur",
		3.12,
		32.99
	};

	cout << "Expand your guest list with " << guest.name << " and " << pal.name << endl;
	cout << "You can hanve both for $" << guest.price + pal.price << endl;

	return 0;
}

 推荐使用外部声明而使用局部变量

 相同类型的结构体支持对拷

#include <iostream>

using namespace std;

struct inflatable
{
	char name[20];
	float volume;
	double price;
};

int main(void)
{
	inflatable bouquet = 
	{
		"sunflowers",
		0.20,
		12.49
	};

	inflatable choice;

	cout << "bouque: " << bouquet.name << " for $" << bouquet.price << endl;

	choice = bouquet;
	cout << "choice: " << choice.name << " for $" << choice.price << endl;

	return 0;
}

 结构体数组

#include <iostream>

struct inflatable
{
	char name[20];
	float volume;
	double price;
};

int main(void)
{
	using namespace std;

	inflatable guests[2] = 
	{
		{"Bambi", 0.5, 21.99},
		{"Godzilla", 2000, 565.99}
	};

	cout << "The guests " << guests[0].name << " and " << guests[1].name << " have a combined volume of "
	     << guests[0].volume + guests[1].volume << " cubic feet." << endl;

	return 0;
}

 共用体(联合体)

 

 

#include <iostream>

using namespace std;

union one2all
{
	char ch;
	int n;
};

int main(void)
{
	one2all num;

	cout << "sizeof(num) = " << sizeof(num) << endl;

	num.ch = 'A';

	cout << "num.ch = " << num.ch << endl;
	cout << "num.n = " << num.n << endl;
	
	return 0;
}

枚举

枚举一般用来定义多个符号常量

 

定义一个枚举 
spectrum jack;//只能将定义枚举时使用的枚举量赋值给这种枚举的变量;
也就是说jack在不进行强制类型转换的前提下只有八个可能的取值;
枚举变量可以看作一个整型 可以提升为int类型 但是int类型不能变为枚举类型,因此枚举变量可以赋值给int类型变量,反之则不成立
枚举变量只有赋值操作没有加减乘除操作
如果int的值是在枚举的取值范围内的则可以通过强制类型转换将值赋给枚举变量
band = spectrum(3);

 指针和自由存储空间

#include <iostream>

int main(void)
{
	using namespace std;

	int updates = 6;
	int *p_updates;
	p_updates = &updates;

	cout << "Value: updates =  " << updates << endl;
	cout << "p_updates = " << p_updates << endl;

	cout << "Address : &updates = " << &updates << endl;

	cout << "*p_updates = " << *p_updates << endl;
	
	*p_updates = *p_updates + 1;
	cout << " Now value: updates =  " << updates << endl;	

	return 0;
}

声明和初始化指针

 正确做法是: int* p1,*p2;

创建指针时计算机将分配存储地址的内存,但不会分配该地址指向的数据的内存。未初始化的指针可能指向任何地址,随意修改该地址的值是不明智的,故在对指针使用解引用运算符之前一定要确定指针指向的地址可用。

int* p1;
p1 = 0xB8000000;//不能将数值赋值给地址,这样是错误的并且没有意义

p1 = (int*)0xB8000000;//要将数字值赋值给地址来使用应该通过强制类型转换

使用new运算符来分配内存

声明的变量被分配到栈区 而new运算符开辟的内存在堆区

#include <iostream>

int main(void)
{
	using namespace std;

	int nights = 1001;
	int *pt = new int;
	*pt = 1001;

	cout << "nights value = " << nights << " : location = " << &nights << endl;
	cout << "int value = " << *pt << " : location = " << pt << endl;

	double *pd = new double;
	*pd = 10000001.0;

	cout << "double value = " << *pd << " : location = " << pd << endl;

	cout << "location of pointer pd = " << &pd << endl;

	cout << "size of pt = " << sizeof(pt) << endl;
	cout << "size of *pt = " << sizeof(*pt) << endl;

	cout << "size of pd = " << sizeof(pd) << endl;
	cout << "size of *pd = " << sizeof(*pd) << endl;

	return 0;
}

用delete释放内存时 在其后面加上要释放内存的指针即可;但是不会删除该指针,它还可以指向其他内存地址,并且delete不能释放已经释放的内存块这样结果时未知的,也不能使用delete释放声明变量所获得的内存;new和delete成对出现可以很好的避免这个问题;

 用nwe来创建动态数组

如果通过声明来创建数组,则在程序编译时就为它分配内存空间。不管是否使用都占用那么多内存;

而使用new可以在程序运行时来创建数组。

 

 

 数组名是数组首元素的地址,是常量,不可修改。指针是存储地址的变量其内容可以修改,且指针加一将指向下一个元素的首地址;

#include <iostream>

int main(void)
{
	using namespace std;

	double *p3 = new double [3];
	p3[0] = 0.2;
	p3[1] = 0.5;
	p3[2] = 0.8;

	cout << "p3[1] is " << p3[1] << endl;
	p3 = p3 + 1;
	cout << "Now p3[0] is " << p3[0] << endl;
	cout << "p3[1] is " << p3[1] << endl;

	p3 = p3 - 1; 

	delete [] p3;

	return 0;
}

当使用sizeof运算符时数组名不会被解释为地址。而是整个数组;

#include <iostream>

int main(void)
{
	using namespace std;

	double wages[3] = {10000.0, 20000.0, 30000.0};
	short stacks[3] = {3, 2, 1};

	double *pw = wages;
	short *ps = &stacks[0];

	cout << "pw = " << pw << ", *pw = " << *pw << endl;
	pw = pw + 1;
	cout << "add 1 to the pw pointer." << endl;
	cout << "pw = " << pw << ", *pw = " << *pw << endl;
	
	cout << "ps = " << ps << ", *ps = " << *ps << endl;
	ps = ps + 1;
	cout << "add 1 to the ps pointer." << endl;
	cout << "ps = " << ps << ", *ps = " << *ps << endl;

	cout << "stacks[0] = " << stacks[0] << ", stacks[1] = " << stacks[1] << endl;
	cout << "*stacks = " << *stacks << ", *(stacks + 1) = " << *(stacks + 1) << endl;

	cout << "size of wages array = " << sizeof(wages) << endl;
	cout << "size of pw pointer = " << sizeof(pw) << endl;

	return 0;
}

#include <iostream>

int main(void)
{
	using namespace std;

	short tell[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

	cout << "tell = " << tell << endl;
	cout << "tell + 1 = " << tell + 1 << endl;
	cout << "&tell + 1 = " << &tell + 1 << endl;
	cout << "&tell + 2 = " << &tell + 2 << endl;

	return 0;
}
//short (*pt) [20] = &tall;其中short (*pt) [20]表示一个指向由20个short类型元素组成的数组的指针。

int* pa;
int arr[3] = [1,2,3];
pa = arr;
则 pa[1]=arr[1]=*(pa+1)=*(arr+1) != (&arr+1)

 

 

 

关于常量指针与指针常量

常量指针 const int *Pt; 指针可以更改指向,但是不能通过指针来更改指向的内容;
指针常量 int * const pt;指针可以更改指向地址的内容,但是不能更改指向对象;
#include <iostream>
#include <cstring>

int main(void)
{
	using namespace std;

	char animal[20] = "bear";
//只有在数组初始化时才能就行字符串的拷贝,此后只能就行字符串的地址赋值
	const char *bird = "wren";
	char *ps;

	cout << animal << " and " << bird << endl;
	//cout << ps << endl;

	cout << "Enter a kind of animal: ";
	cin >> animal;
	cout << animal << endl;

	ps = animal;
	cout << ps << endl;

	cout << animal << " at " << (int *)animal << endl;
	cout << ps << " at " << (int *)ps << endl;

	cout << "After using strcpy\n";
	ps = new char[strlen(animal) + 1];
	strcpy(ps, animal);
	cout << animal << " at " << (int *)animal << endl;
	cout << ps << " at " << (int *)ps << endl;
	delete []ps;

	return 0;
}

动态创建结构体

#include <iostream>

struct inflatable
{
	char name[20];
	float volume;
	double price;
};

int main(void)
{
	using namespace std;

	inflatable *ps = new inflatable;
	cout << "Enter name of inflatalbe item: ";
	cin.get(ps->name, 20);
	cout << "Enter volume in cubic feet: ";
	cin >> (*ps).volume;
	cout << "Enter price $";
	cin >> ps->price;

	cout << "Nanme: " << (*ps).name << endl;
	cout << "Volume: " << ps->volume << endl;
	cout << "Price: $" << ps->price << endl;

	delete ps;

	return 0;
}
#include <iostream>
#include <cstring>

using namespace std;

char *getname(void);

int main(void)
{
	char *name;

	name = getname();
	cout << name << " at " << (int *)name << endl;
	delete [] name;

	name = getname();
	cout << name << " at " << (int *)name << endl;
	delete [] name;

	return 0;
}

char *getname(void)
{
	char tmp[80];

	cout << "Enter last name: ";
	cin >> tmp;

	char *pn = new char[strlen(tmp)+1];
	strcpy(pn, tmp);

	return pn;
}

 组合类型

指针与二级指针

#include <iostream>

using namespace std;

struct antarctica_years_end
{
	int year;
};

int main(void)
{
	antarctica_years_end s01, s02, s03;

	s01.year = 1998;

	antarctica_years_end *pa = &s02;
	pa->year = 1999;

	antarctica_years_end trio[3];
	trio[0].year = 2003;

	cout << trio->year << endl;

	const antarctica_years_end * arp[3] = {&s01, &s02, &s03};

	cout << arp[1]->year << endl;


	const antarctica_years_end **ppa = arp;
	cout << (*ppa)->year << endl;

	auto ppb = arp;
	cout << (*(ppb+1))->year << endl;     //(*(ppb+1))  == &s02

	return 0;
}

初识vector、array模板类 传统数组不安全是因为会产生访问越界而vector和array类中有防止越界的函数

#include <iostream>
#include <vector>
#include <array>

int main(void)
{
	using namespace std;

	double a1[4] = {1.2, 2.4, 3.6, 4.8};

	vector<double> a2(4);
	a2[0] = 1.0/3.0;
	a2[1] = 1.0/5.0;
	a2[2] = 1.0/7.0;
	a2[3] = 1.0/9.0;

	array<double, 4> a3 = {3.14, 2.72, 1.62, 1.41};
	array<double, 4> a4;

	a4 = a3;

	cout << "a1[2] = " << a1[2] << " at " << &a1[2] << endl;
	cout << "a2[2] = " << a2[2] << " at " << &a2[2] << endl;
	cout << "a3[2] = " << a3[2] << " at " << &a3[2] << endl;
	cout << "a4[2] = " << a4[2] << " at " << &a4[2] << endl;

	a1[-2] = 20.2;
	cout << "a1[-2] = " << a1[-2] << " at " << &a1[-2] << endl;
	cout << "a3[2] = " << a3[2] << " at " << &a3[2] << endl;
	cout << "a4[2] = " << a4[2] << " at " << &a4[2] << endl;

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值