1.3 c++数据的复合类型及其使用(一)

1 数组

格式:typeName arrayName[arraySize];   arraySize表示元素数目,必须是整型常数或const值,也可以是常量表达式。arraySize在编译时已知,不能是变量。如int a[10];,c++强调a数组是使用int类型创建的。当数组下标超过9时,编译器编译时不会报错,但会破坏数据。如果是没有初始化的组数,其元素值是不确定的,由驻留在内存单元中的值决定。1)处:如果sizeof运算符作用于数组名,将得到整个数组的字节数。如果只对数组一部分进行初始化,则编译器把其他元素设置为0。如果[ ]内为空,编译器将计算元素的个数。注意:只有在定义数组时才能使用初始化,此后不能使用。不能将一个数组赋给另一个数组。

short thing[] = {1,3,5,7};
int num = sizeof thing /sizeof(short); //1)
        int b[4] = {'a',12,true}; 
	float c[4] = {'a',101,21.1,true};
	cout<<c[0]<<" "<<c[3]<<endl;

 代码结果:97  1  

c++11可省略“=”,列表初始化禁止缩窄转换(大存储空间缩减为小存储空间),如int a[2] = {12.1,2};不被允许,浮点型转换整型不会通过编译。

2 字符串

c风格字符串(以空字符\0结尾)和基于String字符串 c风格字符串:char me[10]={'w','a,'n','g'},char me[] ={'w','a,'n','g','\0'}或char me[]="wang"(隐式地包括空字符)。将字符串存储到数组的方法:1)将数组初始化为字符串常量;2)键盘输入读入数组中 。要注意字符数组和字符串的区别:字符串必须以'\0'结尾(不管是隐式还是显式的包含),而字符数组未必以'\0'结尾,如char dog[5]={'a','b',' ','c','d'}不是字符串,但是字符数组,切勿用cout输出dog,其结果显示ab cd五个字符后,会按内存中随后的各个字节解释要打印的字符,直到空字符,但由于空字符在内存中很常见,所以很快结束。字符串常量实际上表示的是字符串所在的内存地址

C语言库函数strlen(字符串地址):返回存储在数组中字符串的长度,即可见字符的长度,不含末尾的空字符,包含在cstring或string.h文件中。其他关于c语言字符串的库函数的方法:

  • 输入 -----gets(字符数组名)遇到换行符返回、scanf("%s",字符数组变量名)忽略前导空白(空格、制表符、换行符),遇到空白结束【注意%c的时候,会将空白按字符输入,其他情况跟%s一样。】

  • 输出------puts(字符串的地址);  printf("%s",字符串地址);遇到'\0'结束 (注意‘\0'空字符和' '空格字符的区别)

         【注意double类型的变量,其printf输出格式为%f,在scanf输入格式是%lf 】

  • 复制-----strcpy(字符数组名,字符串地址)strncpy(字符数组变量,字符串,长度n)包含在string.h文件

  • 比较-----strcmp(字符串1地址,字符串2地址)stricmp(字符串1地址,字符串2地址)strncmp(字符串1地址,字符串2地址,长度n),包含在string.h文件

  • 拼接-----strcat(字符数组名,字符串地址),包含在string.h文件

C++字符串常量的拼接:任何两个由空白分隔的字符串常量都将自动拼接成一个。下面cout语句都是等效的。

cout<<"We are Chinese from a large family.\n";
cout<<"We are Chinese" "from a large family.\n";
cout<<"We are Chinese"
"from a large family.\n";
  • 输入-----cin>>字符串地址;忽略前导空白(空格、制表符、换行符),遇到空白结束,并自动在结尾添加空字符。

读行输入 cin.getline(数组地址,要读取的字符数n)遇到换行符停止读取,丢弃换行符,在字符串尾加入空字符,最多读取n-1个字符,返回cin对象。

读行输入cin.get(数组地址,要读取的字符数n),返回cin对象。它遇到换行符停止读取(认为到达行尾),将其留在输入队列中,若下一句代码仍是cin.get(数组地址,要读取的字符数n),将会遇到留在输入队列中的换行符,那么它认为已经达到行尾,get()语句将无法跨过换行符。所以用cin.get()读取下一个字符,可以用它来读取换行符,函数返回输入中的下一个字符。以下有三种方法分别读取两行入数组name1和name2中。

//第一种
cin.getline(name1,size).getline(name2,size);
//第二种
cin.get(name1,size)
cin.get();
cin.get(name2,size);
//第三种
cin.get(name1,size).get();
cin.get(name2,size).get();
//提倡使用第三种,因为get(,)将一行读入数组中,可以用一种方式检查get(,)是因为读取整行而停止,而不是
// 由于数组而填满,该方式是可以查看下一个字符,如果是换行符,说明已读取整行,所以get(,)使输入更仔细

混合输入数字和面向行的字符串导致的问题,如下代码

int year;
char address[20];
cin>>year;
cin.getline(adreess,20);
cout<<year<<" "<<address<<endl;

cin会将空白留在输入队列,如果空白是换行符,则getline看到换行符后,认为是个空行,并将空字符串赋给address数组。解决之法有4种:

// 第一种
cin>>year;
cin.get();
cin.getline(adress,20);

// 第二种,cin>>year会返回cin对象
(cin>>year).get();
cin.getline(adress,20);

// 第三种
char ch;
cin>>year;
cin.get(ch);  // 接受一个char参数的get()方法
cin.getline(adress,20);

// 第四种
char ch;
(cin>>year).get(ch);
cin.getline(adress,20);

3 string类

c++另一种处理字符串的方式:使用string对象储存字符串,而不是之前的字符数组存储字符串,同时提供了将字符串作为一种数据类型的方法。要使用string类,程序必须包含头文件string。string类位于名称空间std中,所以要用using编译指令或者使用std::string来引用它。

string str1;
string str2 = "wer";
cin>>str1;

string str ;
getline(cin,str);  // 将一行读入string对象中
cout << str ;

string对象和字符数组的区别:将string对象声明为简单变量,而不是数组,且能自动处理string的大小,即初始长度为0,输入时自动调整。可以说char数组是一种存储一个字符串的char存储单元,而string类变量是一种表示字符串的实体。

string完成字符数组不能做的事:赋值、拼接和附加。1)将一个string对象赋给另一个string对象,而数组不可以;2)用运算符+将两个string对象(c-风格字符串和string对象)合并,用+=运算符将字符串附加到string对象的末尾。c++使这些操作简单(c使用函数),更安全(string类具有自动调整大小的功能)。

C++还提供返回字符串长度的类方法-----size(),调用方式:str.size();(str是string对象)。c++11新增的原始字符串,默认将"(和)"作为定界符,并使用前缀R来标识原始字符串。也有自定义形式:在"和(之间添加其他字符,但空格、左右括号、斜杠和控制符除外,同样也要在)和"之间添加相同的字符,防止编译器在原始字符串中第一次遇到")就认为结束了。

cout<<R"(hello\nworld)";
// 结果显示hello\nworld

4 结构(体)

结构是用户定义的类型,而结构声明定义了这种类型的数据属性。创建结构,首先要定义结构描述,然后按描述创建结构变量。c++允许声明结构变量时省略关键字struct,c不可。用成员运算符.来访问各个成员,如p1.age。

struct person
{
    char name[20];
    int age;
};
person p1;

结构声明的位置:1)外部声明(在main()外)2)内部声明。结构变量可以是也可以在函数外部或内部定义。c++不提倡使用外部变量,但提倡使用外部结构声明。注意:可以将结构作为参数传递给函数,也可以让函数返回一个结构。还可以使用赋值运算符(=)将结构给另一个同类型的结构,这样结构中每个成员都将被设置为另一个结构中相应成员的值,即使是数组。也可以创建元素为结构的数组

// 同时完成定义结构和创建结构变量
struct person
{
    char name[20];
    int age;
}p1,p2;
// 还可以进一步完成初始化
struct person
{
    char name[20];
    int age;
}p1={"wang",18};
// 声明没有名称的结构类型,缺点是以后无法创建这种类型的变量
struct 
{
    char name[20];
    int age;
}p1;

c++给结构进行拓展——构造函数(其特点与类的构造函数类似)用于结构的初始化,本身有默认的无参构造函数,无返回类型(也没有void) ,函数名与结构名相同。和类中无初始化声明的对象调用构造函数问题一样,如果你提供了构造函数,就必须满足无初始化声明的对象创建。这都有两种方法解决,一是利用默认参数,二是利用重载默认构造函数,可参考类的构造函数https://blog.csdn.net/vinkuan/article/details/105441127

// 示例一:memset()方法在头文件<memory.h>或<cstring>中,参数一表示指针,参数二表示int类型,参数三表示从a开始的字节数,
//采用按字节拷贝,所以参数二只能是-1或者0
const int max = 10;
struct str{
	int a[max];
	int len;
	str(){                            // 构造函数
		memset(a,0,sizeof(a));
		len = 0;
	}
};


// 示例二:利用默认参数
struct str2{
	std::string id;
	int value;
	str2(std::string _id = "xxx", int _value = 0){        // 1)处
		id = _id;
		value = _value;
	}
//	str2(std::string _id = "xxx", int _value = 0) : id(_id), value(_value){}    // 第二种写法:成员初始化列表语法
	
};


str2 s1("ming",12);                // 利用1)处构造函数初始化,传递ming和12
std::cout << s1.id << " " << s1.value << std::endl;
str2 s2;                            // 利用1)处构造函数初始化,使用默认参数xxx和0
std::cout << s2.id << " " << s2.value;

5 共用体

共用体能够存储不同的数据类型,但只能同时存储其中的一种类型。所以共用体变量值会是最新成员的值,将导致共用体的长度为其最大成员的长度。优点:节省内存

union dog
{
    long id_num;
    char id[10];
}dg1;
dg1.id_num = 2020;
cin>>dg1.id; // id会覆盖id_num

struct person
{
    union
    {
        long id_num;
        char id[10];   
    };                // 匿名共用体
};

6 枚举

enum提供另一种创建符号常量的方式,可代替const。枚举只有赋值运算,没有算术运算。在不进行强制转换的情况下,只能将定义使用的枚举量赋给枚举变量。枚举量是整型,可被提升为int类型,但int类型不能自动转换为枚举类型。可以省略枚举类型的名称。

设置枚举量的值:第一个枚举量默认为0,后面没有初始化的枚举量的值比前面的枚举量大1。枚举的取值范围:对于枚举来说,只有声明的那些值才是有效的,但通过强制转换,给枚举变量增加了合法值。合法的最大值为 将大于最大的枚举量的最小2的幂 减一,最小值为 将小于最小的枚举量的最大2的幂 加1。

enum bits{one =1,two,three=5,four=5}; // one,two等作为符号常量,叫做枚举量
bits b1 = three;
cout<<b1;

// 输出结果
5

enum {
	num = 10
};
char arr[num] = {'a','b','c','d','\0'};    // 可代替const
cout << arr;
// 输出结果
abcd

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vinkuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值