06.复合数据类型

字符

字符类型、字符文字与量

定义格式:char ch; const char cch = 'C';

字符文字使用单引号对

实际存储时字符类型量存储字符的对应ASCII值

可使用signed与unsigned修饰字符类型

单字符用8个字节存储,表达范围-128127,用unsigned修饰的话范围为0255

字符表示的等价性

char a = 'A';
char a = 65;    //ASCII值
char a = 0101;	//八进制
char a = 0x41;	//十六进制

ASCII码表

控制字符、通信专用字符、可打印字符

回车与换行

Windows: \n\r

Linux:\n

Mac: \r

ASCII使用示例:

判断某个字符是否为数字

bool isDigit(char c)
{
    if(c >= '0' && c <= '9')  //等价于if(c >= 48 && c <= 57)
        return true;
    else
        return false;
}

将字符转换为大写字符

char ToUpperCase(char c)
{
    if(c >= 'a' && c <= 'z')
        return c - 'a' + 'A';  //等价于return c + 32;
    else
        return c;
}

C标准字符特征库:ctype.h/cctype,标准字符特征库常用函数:bool isalnum(char c);bool isalpha(char c);bool isdigit(char c);bool islower(char c);bool isspace(char c);bool isupper(char c);char tolower(char c);char toupper(char c);

数组

数组的意义与性质

数组的定义

定义格式:元素类型 数组名称[常数表达式];

示例:int a[8]; //定义包含8个整数元素的数组

特别说明

常数表达式必须是常数和常量,不允许为变量

错误示例:int count = 8; int c[count];

数组元素编号从0开始计数,元素访问格式为a[0],a[1],a[2]...

不允许对数组进行整体赋值操作,只能使用循环逐一赋值元素

错误示例:int a[8], b[8]; a = b;

意义与性质

将相同性质的数据元素组织成整体,构成单一维度上的数据序列

数组的存储表示

数组元素一次连续存放,中间没有空闲空间

数组的地址

数组的基地址:数组开始存储的物理位置

数组首元素的基地址:数组首个元素开始存储的物理地址,数值上总是与数组基地址相同

“&”操作符:&a获得数组的基地址;&a[0]获得数组首元素的基地址

设数组基地址为p,并设每个元素的存储空间为m,则第i个元素的基地址为p+mi

数组元素的初始化

基本初始化格式

定义格式:元素类型 数组名称[元素个数] = {值1, 值2, 值3, ……};

示例:int a[8] = {1, 2, 3, 4, 5, 6, 7, 8};

初始化时忽略元素个数表达式

在全部元素均初始化时可以不写元素个数,使用sizeof操作符可以获得元素个数

示例:int a[] = {1, 2, 3, 4, 5, 6, 7, 8}; int num_of_elements = sizeof (a) / sizeof (a[0]);

sizeof获取数组存储空间大小(以字节为单位),sizeof(a[0])获取数组首元素的存储空间大小。

数组元素的访问

数组与函数

数组元素作为函数实际参数

int Add(int x, int y) {return (x + y);}
int a[2] = {1, 2}, sum;
sum = Add(a[0], a[1]);

数组整体作为函数形式参数

数组整体作为函数形式参数

基本格式:返回值类型 函数名称 (元素类型 数组名称怕[], 元素个数类型 元素个数)

示例:void GenerateIntegers(int a[], unsigned int n);

特别说明:作为函数形式参数时,数组名称后的中括号内不需列写元素个数,必须使用单独的参数传递元素个数信息

数组作为函数参数时有个巨大的优势,是能够将函数内部对数组元素的修改带出函数以外,能对数组产生实际改变。即数组作为函数参数时既是输入的一部分也是输出的一部分。

示例:

随机产生n个介于[lower,upper]之间的整数并保存在数组中

void GenerateIntegers(int a[],unsigned int n, int lower, int upper)
{
    unsigned int i;
    for(i = 0;i < n;i++)
        a[i] = GenerateRandomNumber(lower,upper);
}

上述代码中,对a[]数组的实际操作真正反映到了a[]中。同时需注意,C++中数组声明时数组元素个数必须为常数或常量(C中只能为常数),所以需额外传一个参数n表示数组元素个数,而不能将元素个数写死或直接声明a[n]。

上述问题的完整描述:使用单独数组名称作为函数实际参数,传递数组基地址而不是数组元素值;形式参数与实际参数使用相同存储区,对数组形式参数值的改变会自动反应到实际参数中

多维数组

多维数组的定义

定义格式:元素类型 数组名称[常数表达式1] [常数表达式2] ...;

示例一:int a[2][2]; //2*2的整型二维数组

示例二:int b[2] [3] [4] ; //2*3*4的整型三维数组

多维数组的初始化

与一维数组类似:int a[2][3] = {1, 2, 3, 4, 5, 6};

单独初始化每一维:int a[2][3] = {{1, 2, 3}, { 4, 5, 6} };

多维数组的存储布局

同一维数组,先行后列存储。

结构体

结构体的意义与性质

结构体的意义

与数组的最大差别:不同类型数据对象构成的集合

当然也可以为相同类型的但具体意义或解释不同的数据对象集合

结构体类型的定义:注意类型定义后面的分号

struct 结构体名称
{
    成员类型1 成员名称1;
    成员类型2 成员名称2;
    ......
    成员类型3 成员名称3;
};

示例

日期结构体

struct DATE
{
    int year;
    int month;
    int day;
};

复数结构体

struct COMPLEX
{
    double real;
    double imag;
};

结构体类型的声明

仅仅引入结构体类型的名称,而没有给出具体定义,其具体定义在其他头文件中或本文件后续位置

如何表示学生信息?

成员:整数类型的学号id、字符串类型的姓名name、性别(单独定义枚举类型)gender、年龄age、字符串类型的地址addr

enum GENDER{FEMALE,MALE};
struct STUDENT
{
    int id;
    STRING name;   //假设已有字符串类型的定义
    GENDER gender;
    int age;
    STRING addr;
};

结构体的存储表示

按照成员定义顺序存放

各成员的存储空间一般连续

特殊情况

因为不同硬件和编译器的原因,不同类型的成员可能会按照字(两个字节)或双字(四个字节)对齐后存放

使用sizeof获得结构体类型量占用空间大小(以字节为单位),下述两种方式均可:sizeof date; sizeof(date);

结构体数据对象的访问

结构体类型的变量与常量:按普通量格式定义

示例一:DATE date;

示例二:STUDENT zhang_san;

示例三:STUDENT students[8];

结构体量的初始化

示例四:DATE date = {2008, 8, 8};

结构体量的赋值

与数组不同,结构体量可直接赋值,拷贝过程为逐成员一一复制

示例五:DATE new_date; new_date = date;

结构体成员的访问

使用点号操作符(成员选择操作符)“."解析结构体量的某个特定成员

示例一:DATE date; date.year = 2008; date.month = 8; date.day = 8;

嵌套结构体成员的访问

可以连续使用点号逐层解析

示例二:

struct FRIEND{int id; STRING name; DATE birthday;};
FRIEND friend;
friend.birthday.year = 1988;

复杂结构体成员的访问

FRIEND friends[4];
friends[0].birthday.year = 1988;

结构体与函数

编写一函数,使用结构体类型存储日期,并返回该日在该年的第几天信息,具体天数从1开始计数,例如2016年1月20日返回20,2月1日返回32

unsigned int GetDateCount(DATE date)
{
    static unsigned int days_of_months[13]=
    {0,31,28,31,30,31,31,31,31,30,31,30,31};
    unsigned int i, date_id = 0;
    for(i = 1;i < date.month;i++)
        date_id += days_of_months[i];
    date_id += date.day;
    if(date,month > 2 && IsLeap(date.year))
        date_id++;
    return date_id;
}
posted @ 2020-09-11 19:32  bear-Zhao  阅读(230)  评论(0编辑  收藏  举报