C++的学习之旅——复合类型(上)

目录

一、数组

二、字符串

1、在数组中使用字符串

2、字符串输入

 (1)getline函数

 (2)get函数

3、混合输入字符串和数字

 三、string类简介

1、使用string进行字符串初始化

2、赋值,拼接,附加

(1)赋值

(2)拼接、附加

3、string类的其他操作

4、string类I/O

 四、结构简介

1、结构初始化

2、将string类作为成员

3、 成员赋值

4、 结构数组

五、共用体

六、枚举

1、设置枚举的值

 2、枚举的取值范围


一、数组

数组的声明与C语言相同,一般格式如下:

typeName array[arraySize];

如:short months[12];//定义一个months数组,包含12个short类型的元素

 另外,还可以使用如下方式进行初始化:

int cards[4]={3,6,8,10};
int hand[4];
double earning[4] {1.2e4,1.6e4,1.1e4,1.7e4};
unsigned int counts[10]={};
float balances[100] {};

不过,以下方式则禁止 

//只有在定义数组时才可以使用{}进行初始化
int hand[4];
hand[4]={5,6,7,8};
//不能将一个数组赋给另外一个数组
hand=cards;
//不能进行缩窄转换
long plifs[]={25,92,3.0}//浮点型转换为整型是缩窄操作
char slifs[4] {'j','i',1122011,'\0'};//1122011超出char变量的取值范围
char tlifs[4] {'h','i',112,'\0'};//可以,112在char类型范围内

二、字符串

C++处理字符串的方式有两种,一种是来自C语言,一种是基于string类库的方法,我们先来了解一下C语言的格式

1、在数组中使用字符串

与C语言一样,可以将数组初始化为字符串常量。

#include <iostream>
#include <cstring>//strlen()函数头文件,用于确定字符串长度 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	using namespace std;
	
	const int Size=15;
	
	char name1[Size];
	char name2[Size]="C++owboy";//初始化字符串常量
	
	cout<<"Howdy!I'm"<<name2;
	cout<<"!what's you name?\n";
	cin>>name1;
	cout<<"Well,"<<name1<<",your name has ";
	cout<<strlen(name1)<<" letters and is stored\n";
	cout<<"in an array of "<<sizeof(name1)<<" bytes.\n";
	cout<<"Your initial is"<<name1[0]<<".\n";
	name2[3]='\0';
	cout<<"here are the first 3 characters of my name:";
	cout<<name2<<endl;
	
	return 0;
}

2、字符串输入

可以使用cin进行字符串的输入,但是存在一些缺陷,通过以下一个例子来说明

#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	using namespace std;
	
	const int ArSize=20;
	char name[ArSize] ;
	char dessert[ArSize];
	
	cout<<"Enter you name:\n";
	cin>>name;
	cout<<"Enter you favorite dessert:\n";
	cin>>dessert;
	cout<<"I have some delicious "<<dessert;
	cout<<" for you."<<name<<".\n";
	
	return 0;
}

         我们甚至还没有对“输入甜点的提示”作出反应,程序便把它显示出来了,然后立即显示最后一行。cin 是如何确定已完成字符串输入呢?由于不能通过键盘输入空字符,因此 cin需要用别的方法来确定字符串的结尾位置。cin 使用空白(空格、制表符和换行符)来确定字符的结束位置,这意味着 cin在获取字符数组输入时只读取一个单词。读取该单词后,cin 将该字符串放到数组中,并自动在结尾添加空字符。这个例子的实际结果是,cin 把 Alistair 作为第一个字符,并将它放到 name 数组中。这把 Dreeb 留在输入队列中。当 cin 在输入队列中搜索用户喜欢的甜点时,它发现了 Dreeb,因此 cin 读取 Dreeb,并将它放到 dessert 数组中

不过istream中的类(如cin)提供了一些面向行的类成员函数:getline()函数和get()函数,这两个函数都读取一行的输入,直到读取到换行符。随后getline将丢弃换行符get()将换行符保存在输入序列中

 (1)getline函数

调用这种方法,可以使用cin.getline(),这个函数有两个参数,第一个参数是用来存储输入行的数组名称,第二个参数是要读取的字符数。如果这个参数为20,则最多读取19个,剩下一个字符数用于存储空字符。调用格式为:

cin.getline(name,20);

 (2)get函数

get函数调用格式和getline函数相同,也是有两个参数,不过由于get()将换行符保存在输入序列中,所以需要在后面添加上cin.get();重新将换行符读取进来。

cin.get(name,20);
cin.get();

3、混合输入字符串和数字

混合输入数字和面向行的字符串会导致问题

#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	using namespace std;
	
	cout<<"What's year was your house built?\n";
	int year;
	cin>>year;
	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;
}

用户根本没有输入地址的机会。问题在于,当 ci 读取年份,将回车键生成的换行符留在了输入队列中。后面的 cin.getline()看到换行符后,将认为是一个空行,并将一个空字符串赋给 address 数组。解决之道是,在读取地址之前先读取并丢弃换行符。这可以通过几种方法来完成,其中包括使用没有参数的 get()和使用接受一个 char 参数的 get(),如前面的例子所示。可以单独进行调用:

cin>>year;

cin.get(); 

也可以使用表达式cin>>year返回cin对象,将调用拼接起来: 

(cin>>year).get();

 三、string类简介

string类使用起来比数组简单,它需要在程序中包含头文件string。string类位于名称空间std中,则需要提供一条using编译指令

1、使用string进行字符串初始化

char first_date[]={"Le Chapon Dodu"};
char second_date[] {"The Bread Bowl"};
string third_date={"The Bread Bowl"};
string fourth_date {"Hank's Fine Eats"};

2、赋值,拼接,附加

(1)赋值

char charr1[20];
char charr2[20]="hulij";
string str1;
string str2="ponint";
	
charr1=charr2;//不合法,不能将数组赋给另外一个数组 
str1=str2;//合法 ,可以将一个string对象赋给另外一个string对象 

(2)拼接、附加

string str3;
str3=str1+str2;//将str1和str2拼接起来赋给str3 
str1+=str2;//将str2附加到str1后面 

3、string类的其他操作

通过一个例子来对比C语言处理字符串使用的函数与string类处理字符串的对比

#include <iostream>
#include <string>
#include <cstring>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	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.\n";
	cout<<"The string "<<charr1<<"contains "<<len2<<" characters.\n";
	
	return 0;
}

4、string类I/O

可以使用cin和运算符>>来将输入存储到string对象中,使用cout和运算符<<来显示string对象。其句法与处理C-风格字符串相同,但是每次读取一行而不是一个单词时,使用的句法不同 

cin.getline(charr,20);//C-风格字符串读取一行
getline(cin str); //string读取一行

 四、结构简介

1、结构初始化

与数组一样,C++11也支持将列表初始化用于结构,且等号(=)是可选的。若大括号未包含任何东西,则各个成员将被设置为0。注意,这里也不允许缩窄转换。

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

inflatable duck {"white",0.12,9.98};

2、将string类作为成员

可以将string类作为成员,不过需要注意添加using编译指令,或者声明为:

std::string name;

3、 成员赋值

通过结构体变量名.成员名可以给对应的结构成员赋值,同类的结构体变量可以相互赋值,方式与C语言相同

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

inflatable duck1 {"white",0.12,9.98};
duck1.price=10.28;//给成员赋值
inflatable duck2;
duck2=duck1;//将一个成员赋给另外一个成员

4、 结构数组

可以创建元素为结构的数组,方法和创建基本类型的数组完全相同。

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

inflatable gifts[100];//定义包含100个inflatable结构的数组

cin>>gifts[0].volume;//对数组中第0个结构的volume成员进行赋值
cout<<gifts[99].price<<endl;//输出数组中第99个结构的price成员

inflatable guests[2]=
{
    {"huji",0.5,21.99};
    {"huksdk",200,56.66};
};//定义一个包含两个inflatable 结构的数组,并对他们初始化

五、共用体

共用体类型指的是同一段内存单元可以存放不同类型的变量。存储的变量虽然字节可能不同,但起始地址均相同,因而后一个数据会覆盖前面数据。

定义共用体类型变量的一般形式为:

union 共用体名

{

        成员表列

}变量表列

union one4all
{
    int int_val;
    long long_val;
    double double_val;
};

one4all pail;
pail.int_val=15;//此时pail只存储int_val=15;
pail.long_val=1.38;//此时pail只存储long_val=1.38;

 匿名共用体:指共用体但是没有名称,成员也是位于相同地址的变量。

struct widget
{
	char brand[22];
	union 
	{
		long id_num;
		char id_char[20];
	}
}

widget prize;
cin>>prize.id_num;

 由于共用体是匿名的,因此id_num和id_char被视为prize,两个成员,这两个的地址相同。

六、枚举

若一个变量只有几种可能存在的值,则可定义为枚举类型,所谓枚举,就是指把所有可能存在的值均列出来,变量的值只能在这范围中。

声明枚举类型的一般形式为:

enum [枚举名]{枚举元素列表} 

1、设置枚举的值

enum bigstep{sun,mon,tue,wed,thu,fri,sat};
enum bigstepworkday,weekend; 

 每一个枚举元素均代表一个整数,C语言编译时按定义时的顺序默认它们的值为0,1,2,3,,,当然,也可以在定义枚举类型时显示地指定数值

enum bigstep{sun=0,mon=7,tue,wed,thu,fri=100,sat};

如之后顺序加1,sat为101。 

 2、枚举的取值范围

最初,对于枚举来说,只有声明中指出的那些值是有效的。然而,C++现在通过强制类型转换,增加了可赋给枚举变量的合法值。每个枚举都有取值范围(range),通过强制类型转换,可以将取值范围中的任何整数值赋给枚举变量,即使这个值不是枚举值。例如,假设 bits 和 myflag 的定义如下:

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

 则下面的代码将是合法的:

myflag = bits(6);

其中6不是枚举值,但它位于枚举定义的取值范围内。

取值范围的定义如下。首先,要找出上限,需要知道枚举量的最大值。找到大于这个最大值的、最小的2的幂,将它减去 1,得到的便是取值范围的上限。例如,前面定义的 bigstep 的最大值枚举值是 101。在2的幂中,比这个数大的最小值为 128,因此取值范围的上限为 127。要计算下限,需要知道枚举量的最小值。如果它不小于 0,则取值范围的下限为 0: 否则,采用与寻找上限方式相同的方式,但加上负号。例如,如果最小的枚举量为-6,而比它小的、最大的 2 的幂是-8(加上负号),因此下限为-7。选择用多少空间来存储枚举由编译器决定。对于取值范围较小的枚举,使用一个字节或更少的空间;而对于包含long类型值的枚举,则使用4 个字节。


C++的学习笔记持续更新中~

要是文章有帮助的话,就点赞收藏关注一下啦!

感谢大家的观看

欢迎大家提出问题并指正~

猜你喜欢

转载自blog.csdn.net/qq_47134270/article/details/128592125