C++ primer plus(第六版)学习笔记、习题答案(3)

第四章:复合类型


第一部分:学习笔记

1.数组

1)

typeName arrayName[araySize]

arraySize指定元素的个数,且必须是常数,即所有的值在编译时都是已知的,arraySize不能是变量,变量的值在程序运行时设置的。

2)编译器不会检查使用的下标是否有效

3)sizeof用于数组得到的是整个数组的字节数。

4)只有定义数组时才能进行初始化,此后就不可以了,也不能将一个数组赋给另一个

int cards[4];
card[4] = {};//not allowed

int hand[4] = {};

hand = card;/not allowed

但是可以使用输入流给数组复制,有因为它相当于一个一个的赋值。

const int count = 6;
int card[count];

cin >> card;
这是允许的。

5)C++11的新特性

int card[4]{1,2,3,5}

可省略等号

但列表初始化禁止缩窄转化,什么是缩窄转化呢?比如: 

long p[] = {25,92,1.0};
char q[4]{'g',111111111};

第一条语句不能通过编译,因为浮点转化为整形就是缩窄转化,第二条11111111超出char的范围。记住列表初始化不能缩窄转化。


2.字符串

1)‘\0’作为字符串的结尾

2)cout打印字符时知道遇到空串才停止。

3)字符创显示的不包括空串,但把它读入char字符数组时将自动加入。

4) 

char c = 'c';
char c = "c";//illegal type mismatch

"c"包括字符c 和\0

5)拼接字符常量

cout << "i ksafjlaskj" "jfakjflak fjl"

cout << 'jdkaflakjf"
"jfalkfjalfkja;lf"

拼接字符串之间不会加入空格,第一个字符串结尾的‘\0’被后面的取代。

6)sizeof(arry)计算的是数组的长度,但strlen()只计算可见的字符,不包括空字符。

7)一个容易的错误

// instr1.cpp -- reading more than one string
#include <iostream>
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";
    // cin.get();
	// cin.get();
    return 0; 
}

根本得不到你想要对结果,是这样的:cin使用空白(空格,制表符,换行符)来确定字符串的结束位置,当我们输入:wu jun qi 的时候,以为着只获取到了wu,读取完成后,cin将其他的字符串放入输入队列中。

3.cin.get()和cin.getline()

1)

cin.getline(name, size);

2)cin.get()读取单个字符,包括换行符。

3)一个问题程序:

// numstr.cpp -- following number input with line input
#include <iostream>
int main()
{
    using namespace std;
    cout << "What year was your house built?\n";
    int year;
    cin >> year;
    // cin.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";
    // cin.get();
    return 0; 
}

当cin读取年份后,回车键留在了输入队列中,后面的cin.getline()看到换行符后,将其认为是一个空行,赋给address数组。解决方法;

(cin >> year).get();


4)空行问题

当getline()或者get()读取空行时,det()读取空行后将设置失效位(failbit),只意味着接下来的输入将被阻断,用cin.clear()可解除,比如:

// 2014/12/7
#include <iostream>
int main()
{
	using namespace std;
	char c1[4];
	char c2[4];
	cin.getline(c1,4);
	cin.getline(c2,4);
	cout << c2;
	 cin.get();
	 cin.get();
	return 0; 
}
这样输入空行是可行的,

// instr1.cpp -- reading more than one string
#include <iostream>
int main()
{
	using namespace std;
	char c1[4];
	char c2[4];
	cin.get(c1,4);
	//cin.clear();
	cin.get();
	cin.getline(c2,4);
	cout << c2 << "jkalfjlakfj";
	 cin.get();
	
	return 0; 
}

没有cin.clear(),输入空行后将不可行。


4.String 类和结构,共用体,枚举

1)不能将一个数组赋给另一个数组,但可以将一个string对象赋给另一个string对象。

2)结构定义:

<pre class="cpp" name="code">struct perk
{
   int ...
   double ...
   
} my_struct;
初始化:
{
   6;
   7.0;
}

 

3)共用体是一种数据结构,它能够存储不同的数据结构,但是只能同时存储其中的一种类型

<pre class="cpp" name="code">union one
{
  int a;
  long long b;
  double c;
};
one pail;

 
因此pail有时可以是int变量,有时可以使long long 变量
4)枚举enum spectrum{red,orange,yellow,green,blue,violet}

spectrum是一个新的类型,称为枚举,默认情况下,将整数赋给枚举量,第一个为0,第一个为1。。。它只定义了赋值运算符,它没有定义算术运算。枚举是整形,可以提升int但是不能int不能自动转化为枚举类型。看一个例子:

<pre class="cpp" name="code">spectrum band;
band = orange;
band = orange + red;//not valid, but a littele tricky

 

将orange + red将转化为1+0,这是一个合法的表达式,但类型为int,不能赋值给spectrum的变量band;

如果int值是有效的,可以这样:

band = spectrum(3);

5)枚举的取值范围

enum bits{one = 1, two = 2,four = 4,eight = 8};
bits myflag;
myflag = bits(6);

其中6是合法的,但它不是枚举值,但它在枚举定义的范围内。

取值范围定义如下:首先找到上限,找到大于这个最大值,最小值的2的幂,将它减去1,得到的便是取值的上限,就算下限,如果最小值不小于0,则它为0,否则和找上限一样,但要加上负号 
 

5.指针

1)*运算符称为解除引用

2)指针式基于其他数据类型的。

3)一定要在解除引用运算符(*)之间,将指针初始化为一个合适的,确定的地址

4)指针是int值得地址,但并不意味着他本身的类型是int


6. 使用new和delete

1)

<pre class="cpp" name="code">int *pn = new int;
typeName * pointer_name = new typeName;

 pn指向了int型的地址,它指向的是数据分配的内存块  

2)定义指针是需要知道指针指向的是什么类型的指针,以为cout打印*p的值时,需要知道读取多少 字节,以及如何解释他们。

3)使用new和delete遵循的规则:

①不要使用delete来释放不是new分配的内存

②不要使用delete释放同一块内存块两次

③使用new[]为数组分配内存,则应使用delete[]来释放

④如果使用new为一个实体分配内存,则应使用delete(没有【】)来释放

⑤对空指针运用delete是安全的

4)不能使用sizeof运算符来确定动态分配的数组包含的字节数。

5)

type_name * pointer_name = new type_name [num_elements]

为数组分配内存的通用格式。

6)

int s[5]

其实在计算机中,s也为指针,但此指针不能再指向其他的值,即数组名是指针常量,二普通的指针则可以。

7)c++编译器将s[1]看成*(s + 1),  

8)对数组使用sizeof得到的是数组的字节长度,而对指针得到的是指针的长度,即使指针指向的是一个数组。

9)一个例子:

short tell[10];
cout << tell << endl;
cout << &tell << endl;

&tell[0]是一个两个字节的内存块的地址,而&tell是一个20字节内存块的地址。因此tell + 1将地址值加2,而表达式&tell将加20

10)c++允许指针和整数值相加,加1的结果等于原来的指向的地址加上指向的对象占用的字节总数。

11)定于数组在编译时分配内存,所以长度需要指定,new在运行时才分配,因此不需要指定长度。

12)如果给cout提供一个字符的地址,则它将从该字符开始打印,知道遇到空字符开始

// mixtypes.cpp --some type combinations
#include <iostream>
#include<array>
using namespace std;

int main()
{
	char p = 'N';
	char* q = &p;
	cout << q;
	cin.get();
	return 0;
}

打印的将不会是N,还会有他的字符。

13)

cout<<"wo ai ni ";

这条语句,是如何解释的呢?字符串常量,也是将其第一个地址传给cout ,cout将其输出知道遇到空字符。

14)在cout和c++表达式中,char数组名,char指针以及引号括起的字符串常量都被解释为字符串的第一个字符的地址。

15)

const char * bird = "wren";

记住,“wren”实际表示的是字符串的地址,这条语句将其首地址赋给了指针bird,

16)如何输出char  数组,指针的地址呢? 使用(int *)ps;

17)应该使用strcpy()或者strncpy(),而不是赋值运算符来将字符串赋值给数组。

char food[20] = "abcd";//初始化
strcpy(food,"flan");//使用赋值函数

strncpy(food, "abac", 19(个数))

18)一个动态输入字符的方法:

// delete.cpp -- using the delete operator
#include <iostream>
#include <cstring>      // or string.h
using namespace std;
char * getname(void);   // function prototype
int main()
{
    char * name;        // create pointer but no storage

    name = getname();   // assign address of string to name
    cout << name << " at " << (int *) name << "\n";
    delete [] name;     // memory freed

    name = getname();   // reuse freed memory
    cout << name << " at " << (int *) name << "\n";
    delete [] name;     // memory freed again
    // cin.get();
    // cin.get();
    return 0;
}

char * getname()        // return pointer to new string
{
    char temp[80];      // temporary storage
    cout << "Enter last name: ";
    cin >> temp;
    char * pn = new char[strlen(temp) + 1];
    strcpy(pn, temp);   // copy string into smaller space

    return pn;          // temp lost when function ends
}


 7.自动存储,静态存储,动态存储。

1)自动存储,在函数内部定义的常规变量,称为自动变量,函数结束时消亡。存储在栈中,符合(LIFO)

2)静态存储:在函数外定义,使用static;

3)动态存储:用new创建动态变量,他们管理了一个地址池,称为自由存储空间,或者堆。它不受函数的生存周期限制。


8 auto

1)自动识别你要传输的指针类型。

int *p = &q;
auto pr = p;


9.模板类

1)vector

vector<typeName> vt(n_elem)

n_elem可以使整形常量也可以使整形变量。

2)array

array<typeName,n_elem>arr;
它指定了固定的数组长度,n_elem 不能是 整形变量。 


第二部分:课后习题

4.1

// 2014/12/8
#include <iostream>
#include<string>

using namespace std;

int main()
{
	string firstName;
	string lastName;
	char grade;
	int age;

	cout << "what is your first name? ";
	//cin >> firstName;
	getline(cin,firstName);
	//cout << endl;
	
	cout <<"what is you last name?";
	getline(cin, lastName);

	cout << "what letter grade do you deserve? ";
	cin >> grade;
	grade = grade + 1;
	//cout << endl;

	cout << "what is your age?";
	cin >> age;
	//cout << endl;

	cout << "Name:" << lastName << firstName << endl << "Grade:" << grade << endl << "Age:" << age;
	

	cin.get();
	cin.get();
	cin.get();
	return 0;
}


4.2

// 
#include <iostream>
#include<string>

using namespace std;
int main()
{
	/*using namespace std;
	const int ArSize = 20;
	char name[ArSize];
	char dessert[ArSize];*/

	string name;
	string dessert;

	cout << "Enter your name:\n";
	getline(cin, name);  // reads through newline
	cout << "Enter your favorite dessert:\n";
	getline(cin,dessert);
	cout << "I have some delicious " << dessert;
	cout << " for you, " << name << ".\n";
	cin.get();
	return 0; 
}


4.3

// 
#include <iostream>
#include<cstring>

using namespace std;
int main()
{
	int const n = 10;
	char firstName[n];
	char LastName[n];

	cout << "Enter your first name:";
	cin.getline(firstName,n);
	
	cout << "Enter your last name:";
	cin.getline(LastName,n);

	cout << "Here is the information is a single string :" << firstName << "," << LastName;

	cin.get();
	cin.get();
	return 0; 
}


4.4

// 
#include <iostream>
#include<string>

using namespace std;
int main()
{
	string firstName;
	string lastName;


	cout << "Enter your first name:";
	getline(cin,firstName);
	
	cout << "Enter your last name:";
	getline(cin,lastName);

	cout << "Here is the information is a single string :" << firstName << "," << lastName;

	cin.get();
	cin.get();
	return 0; 
}


4.5

//
#include <iostream>
#include<string>


using namespace std;

struct CandyBar
{
	string s;
	double weight;
	int ka;
};
int main()
{
	CandyBar candy = {"Mocha Munch", 2.3, 350};

	cout << candy.s << "   " << candy.weight << "   " << candy.ka;
	cin.get();
	cin.get();
	return 0; 
}


4.6

// instr2.cpp -- reading more than one word with getline
#include <iostream>
#include<string>


using namespace std;

struct CandyBar
{
	string s;
	double weight;
	int ka;
};
int main()
{
	int i = 0;
	CandyBar candy[3] = {{"Mocha Munch1", 2.31, 3501},{"Mocha Munch2", 2.32, 3502},{"Mocha Munch3", 2.33, 3503}};

	for(i; i < 3; i++)
	{
		cout << candy[i].s << "   " << candy[i].weight << "   " << candy[i].ka;
		cout << endl;
	}
	
	cin.get();
	cin.get();
	return 0; 
}


4.7

#include<iostream>
#include<string>

using namespace std;

struct pizza
{
	string name;
	double diameter;
	double weight;
};
int main()
{
	pizza pi;
	cout <<"Enter name:";
	getline(cin,pi.name);

	cout << "Enter the diameter";
	cin >> pi.diameter;

	cout <<"Enter the weight:";
	cin >> pi.weight;

	cout << "the name is:" << pi.name << "the diameter is :" << pi.diameter << "the weight is :" << pi.weight;

	cin.get();
	cin.get();
	return 0; 
}


4.8

#include<iostream>
#include<string>

using namespace std;

struct pizza
{
	string name;
	double diameter;
	double weight;
};
int main()
{
	pizza* pi = new pizza;
	cout <<"Enter name:";
	getline(cin,pi->name);

	cout << "Enter the diameter";
	cin >> pi->diameter;

	cout <<"Enter the weight:";
	cin >> pi->weight;

	cout << "the name is:" << pi->name << "the diameter is :" << pi->diameter << "the weight is :" << pi->weight;
	delete pi;
	cin.get();
	cin.get();
	return 0; 
}


ps:顺序呢没有换,懒得了。得记住释放pi


4.9

//
#include <iostream>
#include<string>


using namespace std;

struct CandyBar
{
	string s;
	double weight;
	int ka;
};
int main()
{
	int i = 0;
	CandyBar* candy= new CandyBar[3];
	//CandyBar candy[3] = {{"Mocha Munch1", 2.31, 3501},{"Mocha Munch2", 2.32, 3502},{"Mocha Munch3", 2.33, 3503}};
	candy[0].s = "Mocha Munch1";
	candy[1].s = "Mocha Munch2";
	candy[2].s = "Mocha Munch3";

	candy[0].weight = 2.31;
	candy[1].weight = 2.31;
	candy[2].weight = 2.31;

	candy[0].ka = 3;
	candy[1].ka = 4;
	candy[2].ka = 5;

	for(i; i < 3; i++)
	{
		cout << candy[i].s << "   " << candy[i].weight << "   " << candy[i].ka;
		cout << endl;
	}

	delete[] candy;
	std::cin.get();
	return 0; 
}


4.10

//
#include <iostream>
#include<array>


using namespace std;


int main()
{
	const int n = 3;
	double sum = 0.0;
	array<double,n> score;

	cout <<"Enter you 3 times Score:";

	for(int i = 0; i < 3; i++)
	{
		cout << "enter your " <<i + 1 <<" times score:"<<endl;
		cin >> score[i];
		sum += score[i];
	}
	cout << "your average is :" << sum / score.size() << " ci shu shi :" << score.size();
	cin.get();
	cin.get();
	return 0; 
}

望指正。。。

 







































































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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值