在前面学习了基本数据类型,在编程中我们要使用到复合数据类型,最复杂的数据类型是类。下面介绍一些简单的复合数据类型:
1.数组:可以存储多个相同数据类型的数据。
创建数组的方式:
1.int months[12] ; //创建一个int数组months,含有12个元素,默认值是0
2.int months[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} ; //创建数组并赋值
3.int months[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} ; //创建数组,由系统确定数组长度
4.int months[12] = {1} ; //指定第一个元素的值,其他默认值
可以使用下标来访问数组元素,下标从0开始。
months[0] = 23 ;
2.字符串:是存储在内存连续字节的系列字符。有两种方式:c语言风格的字符串,string类字符串
c语言风格字符串:char数组,以空字符(\0)结尾(记住).
char name[] = {'x','u','s','h','u','a','n','g','z','h','i'} ; 不是字符串,只是char数组
char name[] = {'x','u','s','h','u','a','n','g','z','h','i','\0'} ; 是字符串,可以使用 char name[] = "xushuangzhi" ; 更方便
字符串拼接,用空白(空格、制表符、换行符)隔开的两个字符串 会自动组合成一个字符串。
cout << "xu" "shuangzhi" << endl ;
cout << "xu"
"shuangzhi" <<endl ;
cstring头文件提供了一系列该格式字符串操作的函数。如:strlen(char *) ; 字符串长度
char name[20] = "xu" ; //数组长度为20 ,字符串长度为3 sizeof name/sizeof(char)为20 strlen(name)为3 字符串以\0结束。
cin 以空白来确定字符串的结束。如: cin >> name ; 我们输入xu shuang zhi 则name = "xu" ; 遇到u和s之间的空格就结束字符串输入。
有点需要注意:cin >> city ; cin >> address ; 当我们输入city数据:zheng zhou ,则city为zheng,准备输入address,发现输入缓存中有zhou数据,就输入给address,则city为zheng,address为zhou。这只是每次读取一个单词。我们可以每次读取一行:getline() 和 cin.get(),这两个函数都是读取一行,直到遇到换行符,只是getline()将丢弃换行符,get()将换行符保留在输入序列中。
getline(): cin.getline(name ,20) ;将输入到name数组,长度为20,即只能存储19个字符,第20为空字符。
cin.getline(name,20,'#') ; 第三个参数是指定结束符,默认是换行符,该处为'#',遇到'#'字符就结束。
get():cin.get(name,20) ; cin.get(name , 20 ,'#'); 就是将结束符保留在输入缓冲区中。
char name[30] ; char address[30] ; cin.get(name ,30 , '#') ; cin.get(address,30,'#') ;
name输入时:xushuangzhi # 3ee,则name:xushuangzhi,address:# 就是get()将结束符保留在输入序列中。
string类:
string类是c++提供的另一种字符串,在<string>头文件中定义,使用起来比c各式风格要简单。使用时要引用<string>头文件。
初始化:
char str[20] = "xushuangzhi"; string str2 = string(str) ; string str3 = string(str2) ; string str4 = "zhangguangming" ;
赋值:使用数组方式字符串时,不能将数组赋值给另一个数组,但可以将string对象赋值给另一个string对象。
char cchar1[20] ; char cchar2[20] = "xushuangzhi" ; string str1 ; string str2 = "ni hao" ; cchar1 = cchar2 ; //error str1 = str2 ;
拼接和附加:可以使用+操作符将string对象和字符串或string对象连接,生成一个新的string对象;使用+=将string对象或字符串附加在字符串的后面。如:
string str1 = "hello" ; string str2 = " world!!!" ; string str3 = str1 + str2 ; str1 += str2 ; cout << str3 << endl ; cout << str1 ;
c格式字符串要完成上述操作,就需要使用cstring头文件中定义的函数,strcat(charr1 , charr2) 将charr2的内容添加在charr1的后面,strcpy(charr1, charr2)将charr2的内容复制到charr1字符串中,操作时要保证charr1数组长度足够,也可以使用strncat(charr1,charr2,n)、strncpy(charr1,charr2,n)使用第三个参数控制操作的长度。
输入:输入一个单词方式时,使用方式和c风格一样使用<<,但输入一行数据时,就不一样了,string头文件中提供了getline(cin,string)函数。如:
#include<iostream> #include<string> using namespace std ; int main(){ char charr1[20] ; string str ; cout << "请输入str值:" ; getline(cin , str) ; cout << str << endl ; cout << "请输入charr1值:" ; cin.getline(charr1,20) ; cout << charr1 << endl ; return 0 ; }
结构体:数组可以存储多个相同元素的类型,要是存储运动员信息(名字、性别、地址),可以使用结构体。定义结构体格式:
struct person { char name[20] ; int age ; char address[100] ; } ;
初始化:person p = {"xushuangzhi" ,25 ,"河南省虞城县大候乡"} ;
访问元素:cout << p.name << endl ; 使用.取成员运算符
结构可以作为参数传递给函数,也可以从函数返回结构,可以将结构体赋值给结构,
#include<iostream> #include<string> using namespace std ; int main(){ struct person { char name[20] ; # int ane ; string address ; } ; person p = {"xushuangzhi", 25 ,"address"} ; person per = p ; cout <<"p.name : " << p.name << endl ; cout <<"per.name : " << per.name << endl ; return 0 ; }
结构体的定义可以放在函数中,也可以放在函数外面,区别是访问空间不一样,当然也可以在其他结构体或类中定义。
共用体(union) : 结构体可以存储多种不同类型的数据信息,共用体也是不同类型数据的集合,但只能存储一种类型数据,节省空间。如:
#include<iostream> using namespace std ; struct widget{ char brand[20] ; int type ; union id { long id_num ; char id_char[20] ; } id_val ; } ; int main(){ widget prize ; prize.brand = "baoma" ; prize.type = 1 ; if (prize.type == 1 ){ cin >> prize.id_val.id_num ; }else { cin >> prize.id_val.id_char ; } return 0 ; }
枚举:是一种定义常量的方式,使用enum关键字,可以替代const。
enum spectrum {red ,orange ,yellow ,green ,blue ,violet ,indigo ,ultraviolet } ;
上述定义了枚举spectrum类型,大括号中的值称为枚举量,常量对应的整数值0~7。可以将整数值赋值给枚举量,默认是从0开始,依次加一,也可以显式指定整数值。如:
enum bits {one = 1 ,two = 2 ,three = 3} ;
定义变量:spectrum band ; band = blue ; band的值只能取大括号中的值。
枚举只有赋值运算符,当进行运算时,会将枚举变量转换为对应的整数值来运算。
要将整数值赋值给枚举变量,则要进行强制转换。
bits b = (bits) 1 ; 则 b的值为one 。
指针:指针变量存储的是数据的地址,而不是数据的内容。我们可以使用地址运算符(&)来获取常规变量的地址。
我们可以使用(*)解除引用运算符来取得指针对应的值。如:
#include<iostream> using namespace std ; int main(){ int i = 3 ; int *p_i = &i ; cout << "i = " << i << endl ; cout << "*p_i = " << *p_i << endl ; *p_i = 35 ; cout << "i = " << i << endl ; cout << "*p_i = " <<*p_i << endl ; return 0 ; }
p_i指向i的地址,可以通过*p_i来修改i的值
int *p_i , i ; 这里定义的变量p_i是指针,i是int类型的变量。
注意:要调用*解引用操作之前,要将指针指向确定的、适当的地址。如:
int *p_int ; //*p_int = 2345 ; //cout << *p_int << endl ; int i = 23 ; p_int = &i ; cout << *p_int << endl ;
若*p_int = 2345 ; 则在调用的时候会出错,应该先将p_int指向&i的地址。
我们可以同new关键字来在运行阶段来分配内存地址。
int *p_int = new int ; int *p_age = new int(234) ;
使用new关键字分配的内存只能使用指针来访问数据。 这些分配的内存要使用delete关键字来进行释放。
delete p_int ; 释放内存 ,不能使用delete释放已经释放过的内存。
使用new创建动态数组:
#include<iostream> using namespace std ; int main(){ const int size = 20 ; int *p_arr = new int[size] ; for(int i = 0 ; i <size ; i++ ){ p_arr[i] = i ; } for(int i = 0 ; i < size ; i++ ){ cout << "p_arr[" << i << "] = " << p_arr[i] << endl ; } delete [] p_arr ; return 0 ; }
使用int *p_arr = new int[20] ; 创建动态数组,p_arr指向数组的第一个元素的地址。
释放数组的内存,应使用delete [] p_arr来释放。
*p_arr 是第一个元素的值,要访问其他元素,可以将指针作为数组的名字,使用下标来访问:P_arr[2]是第三个元素,也可以使用*(p_arr+2)来访问第三个元素。
int iArray[] = {1, 2, 3, 4} ; int *p_array = iArray ; int *p_i = &iArray[0] ; for(int i = 0 ; i< 4 ; i++ ){ cout << "iArray[" << i << "] = " << iArray[i] << endl ; cout << "p_array[" << i << "] = " << p_array[i] << endl ; cout << "p_i[" << i << "] = " << p_i[i] << endl ; cout << "*(iArray + " <<i << ") = " << *(iArray+i) << endl ; cout << "*(p_array + " << i << ") = " << *(p_array+i) << endl ; cout << "*(p_i + " << i << ") = " << *(p_i + i) << endl ; }