0%

C++之数据类型

C++之数据类型……

信息在计算机中的表示

  • 二进制数:0、1,称为一个bit(b)
  • 八个二进制位称为一个byte(B)

$$
2^{10}B=1KB,,2^{10}KB=1MB,,2^{10}MB=1GB,,2^{10}GB=1TB
$$


整型

  • short至少16位

  • int至少与short一样长

  • long至少32位,且至少与int一样长

  • long long至少64位,且至少与long一样长

  • 若不加usigned,默认为有符号整数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include<iostream>
    #include<climits>

    using namespace std;

    int main(void)
    {
    //使用sizeof查看变量所占字节数
    cout<<"int is "<<sizeof(int)<<" bytes"<<endl;
    cout<<"short is "<<sizeof(short)<<" bytes"<<endl;
    cout<<"long is "<<sizeof(long)<<" bytes"<<endl;
    cout<<"long long is "<<sizeof(long long)<<" bytes"<<endl;

    //通过climits库中的变量查看数据类型的最值
    int n_int=INT_MAX;
    short n_short=SHRT_MAX;
    long n_long=LONG_MAX;
    long long n_llong=LLONG_MAX;

    cout<<"int max is:"<<n_int<<endl;
    cout<<"short max is:"<<n_short<<endl;
    cout<<"long max is:"<<n_long<<endl;
    cout<<"long long max is:"<<n_llong<<endl;

    return 0;
    }

    结果如下:

    image-20221104202738975

  • char与cout.put()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include<iostream>

    using namespace std;

    int main(void)
    {
    //char字符的使用
    char ch='M';
    int i=ch;
    cout<<"The char is:"<<ch<<endl;//cin和cout的行为都是由变量类型引导的
    cout<<"The ASCII code is:"<<i<<endl;

    //使用cout对象中的.put()方法显示单个字符
    cout.put('!');
    return 0;
    }

    结果如下:

    image-20221106155936150

  • 溢出问题:

    image-20221104200504476

进制的表示与显示

  • 十六进制:0x开头
  • 八进制:0开头
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>

using namespace std;

int main(void)
{
//进制表示
int D10=42;
int D16=0x42;
int D8=042;
//进制显示
cout<<"D10 is:"<<D10<<endl;
cout<<hex;
cout<<"D16 is:"<<D16<<endl;
cout<<oct;
cout<<"D8 is:"<<D8<<endl;

return 0;
}

结果如下:

image-20221104202636559

转义字符

image-20221106155734492


浮点数

1.书写浮点数

  • 使用常用的标准小数点表示

    image-20221106182523410
  • 使用E/e表示法

    image-20221106182623534

2.浮点数的有效位数

  • C++有3种浮点类型:float、double、long double

  • float至少32位,double至少48位,且不少于float、long double至少和double一样多

  • float的精度(6~7位,其中6位一定是准的)比double低,尽量用double类型表示浮点数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include<iostream>

    using namespace std;

    int main(void)
    {
    //浮点数的精度问题
    cout.setf(ios_base::fixed,ios_base::floatfield);//强制cout显示小数点后6位

    float tub=10.0/3.0;
    const float million=1.0E6;

    cout<<"tub= "<<tub<<endl;
    cout<<"A million tubs= "<<million*tub<<endl;
    cout<<"Ten million tubs= "<<10*million*tub<<endl;

    double mints=10.0/3.0;

    cout<<"tub= "<<mints<<endl;
    cout<<"A million mints= "<<million*mints<<endl;
    cout<<"Ten million mints= "<<10*million*mints<<endl;

    return 0;
    }

    结果如下:

    image-20221106184428062

3.浮点数的优缺点

  • 优点:首先,它可以表示整数之间的值,其次,由于有缩放因子,它可以表示的范围大很多

  • 缺点:浮点运算的速度通常比整数运算慢,且精度将降低

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include<iostream>

    using namespace std;

    int main(void)
    {
    //浮点数的缺点
    float a=2.34E22;
    float b=a+1.0;
    cout<<"a="<<a<<endl;
    cout<<"b="<<b<<endl;
    cout<<b-a<<endl;

    return 0;
    }

    结果如下:

    image-20221106185926389


强制类型转换

  • (typeName) value
  • typeName (value)

实例1:对输入的整数,求其对应的天数小时分钟秒数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
using namespace std;

//问题:输出一个整数,计算其对应多少天多少小时多少分钟多少秒
const int Day_to_hour=24;
const int Hour_to_minute=60;
const int Minute_to_second=60;

int main(void)
{
long long seconds=31600000;
cout<<"Please enter the number of seconds: ";
cin>>seconds;
cout<<seconds;

int days,hours,minutes;
days=seconds/(Day_to_hour*Hour_to_minute*Minute_to_second);
seconds=seconds%(Day_to_hour*Hour_to_minute*Minute_to_second);
hours=seconds/(Hour_to_minute*Minute_to_second);
seconds=seconds%(Hour_to_minute*Minute_to_second);
minutes=seconds/Minute_to_second;
seconds=seconds%Minute_to_second;


cout<<" seconds= "<<days<<"days, "<<hours<<" hours, "<<minutes<<" minutes, "<<seconds<<" seconds"<<endl;

return 0;
}

结果如下:

image-20221108181917206


数组

  • 数组中每个元素必须是相同的数据类型
  • 计算机在内存中依次存储数组的各个元素

1.数组的声明

  • typeName arrayName[arraySize];
  • arraySize必须是整数常量或const值或常量表达式

2.数组的初始化

  • int cards[4]={3,6,8,10}
  • 如果只对数组的一部分进行初始化,则编译器将把其他元素设置为0
  • short things[]={1,5,3,8}//编译器将使things数组包含4个元素
  • unsigned int couts[10]={}//若不在大括号内包含任何东西,编译器将把所有元素都设置为零

3.矩阵乘法的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include<iostream>

using namespace std;

const int ROWS=8;
const int COLS=8;

int a[ROWS][COLS];
int b[ROWS][COLS];
int c[ROWS][COLS];

int main()
{
//读入a、b矩阵
int m,n,p,q;
cin>>m>>n;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
cin>>a[i][j];
}
}
cin>>p>>q;
for(int i=0;i<p;i++)
{
for(int j=0;j<q;j++)
{
cin>>b[i][j];
}
}

//计算矩阵乘积
for(int i=0;i<m;i++)
{
for(int j=0;j<q;j++)
{
c[i][j]=0;
for(int k=0;k<n;k++)
{
c[i][j]+=a[i][k]*b[k][j];
}
}
}

//打印计算结果
for(int i=0;i<m;i++)
{
for(int j=0;j<q;j++)
{
cout<<c[i][j]<<' ';
}
cout<<endl;
}

return 0;
}

结果如下:

1
2
3
4
5
6
7
8
9
10
11
输入:
2 3
2 4 5
2 1 3
3 3
1 1 1
2 3 2
0 1 4
输出:
10 19 30
4 8 16

字符串

1.字符串的创建

  • C-风格字符串:以‘\0作为字符数组的结尾

    • char dog[8]={'f', 'a', 't', 'e', 's', 's', 'a', '\0'}
    • char fish[]="Bubbles"
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include<iostream>
    #include<cstring>
    using namespace std;

    int main(void)
    {
    const int size =15;
    char name1[size];
    char name2[size]="C++owBoy";

    cout<<"Howdy! I am "<<name2<<". What your name?"<<endl;
    cin>>name1;
    //strlen()只计算字符串的长度,不包括空字符
    cout<<"Your name has "<<strlen(name1)<<" letters"<<endl;
    //sizeof()计算的是字符串数组所占据的字节数,共有15个char类型,每个char占一个byte
    cout<<"Your name take up "<<sizeof(name1)<<" bytes"<<endl;

    return 0;
    }

    结果如下:

    image-20221108194822412

  • 使用string类创建字符串

    1
    string name="ssyttmsl";

2.字符串的输入

  • cin.getline(variable,size)

    • 读取一行输入,直到到达换行符,然后将换行符丢弃

    • 相比于直接cin,可以读取空格,否则cin遇到空格则会停止读取

    • 其中的第二个参数为size,最多存放size-1个字符

    • 对于string类型的字符串,输入为getline(cin,str)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include<iostream>
    #include<cstring>
    using namespace std;

    int main(void)
    {
    /*使用getline()读取一行数据*/
    const int size =15;
    char name1[size];
    char name2[size]="C++owBoy";

    cout<<"Howdy! I am "<<name2<<". What your name?"<<endl;
    cin.getline(name1,size);
    //strlen()只计算字符串的长度,不包括空字符
    cout<<"Your name has "<<strlen(name1)<<" letters"<<endl;
    //sizeof()计算的是字符串数组所占据的字节数,共有15个char类型,每个char占一个byte
    cout<<"Your name take up "<<sizeof(name1)<<" bytes"<<endl;
    return 0;
    }

    结果如下:

    image-20221109205139096

  • cin.get(variable,size)

    • 读取一行输入,将换行符保留在输入序列中
    • 直接使用cin也会读取换行符
    • 使用不带任何参数的cin.get(),可读取下一行的字符(即使是换行符)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include<iostream>
    #include<cstring>
    using namespace std;

    int main(void)
    {
    /*使用get()读取一行数据*/
    const int size =15;
    char name[size];
    char play[size];
    cout<<"Please enter your name:";
    cin.get(name,size);
    cout<<"Please enter the sport you love:";
    cin.get();//读取换行符
    cin.get(play,size);
    cout<<name<<" loves "<<play<<endl;
    return 0;
    }

    结果如下:

    image-20221109211059425

3.字符串的赋值、拼接和附加

  • 对于string类型的字符串:

    • 赋值:一个string对象可以赋给另一个string对象,但char数组却不行
    • 拼接:使用运算符+将两个string对象合并起来
    • 附加:使用运算符+=将字符串附加到string对象的末尾
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include<iostream>
    #include<cstring>
    using namespace std;

    int main(void)
    {
    /*string的赋值、拼接、附加*/
    string str1="ssy";
    string str2;
    //赋值
    str2=str1;
    cout<<"The str2 is:"<<str2<<",which is equal to str1:"<<str1<<endl;
    //拼接
    str2=" tql";
    cout<<"The str1+str2 is:"<<str1+str2<<endl;
    //附加
    str1+=" is a excellent person.";
    cout<<str1<<endl;
    return 0;
    }

    结果如下:

    image-20221109235315552

  • 对于C风格的字符串

    • 赋值:strcpy(charr1,charr2)//将字符串数组charr2赋给charr1
    • 附加:strcat(charr1,charr2)//将字符串数组charr2添加到charr1的末尾

4.计算字符串的大小

  • 对于C风格的字符串,使用strlen()
  • 对于string类型的字符串,使用str.size()

结构体

1.结构体的创建及其初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#include<cstring>
using namespace std;

//结构体的定义
struct student{
string name;
int age;
double grates;
};

int main(void)
{
//定义结构体对象及初始化
student ssy={"ssy",21,99.98};
ssy.age=22;
cout<<"The age of student1 is:"<<ssy.age<<endl;
student wcf={"wcf",21,98.99};
//结构体的调用
cout<<"The student1 is:"<<ssy.name<<" and grates is:"<<ssy.grates<<endl;
cout<<"The student2 is:"<<wcf.name<<" and grates is:"<<wcf.grates<<endl;
//结构体可以直接赋值给另一个结构体
student cyr;
cyr=wcf;
cout<<"The cyr is:"<<cyr.name<<endl;
return 0;
}

结果如下:

image-20221120223038507

2.结构体数组

  • 数组中的每一个元素都是结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<cstring>
using namespace std;

//结构体的定义
struct student{
string name;
int age;
double grates;
};

int main(void)
{
//结构数组的定义与初始化
student Stu_array[2]=
{
{"ssy",21,99.98},
{"wcf",21,98.99}
};
//结构数组的调用
cout<<Stu_array[0].name<<" and "<<Stu_array[1].name<<" are good frends"<<endl;
return 0;
}

结果如下:

image-20221120223703994


共用体

  • 共用体每次只能存储一个值,因此它必须有足够的空间来存储最大的成员,故共用体的长度为其最大成员的长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
using namespace std;

//共用体的定义
union one2all
{
char ch;
int n;
};


int main(void)
{
//定义共用体对象
one2all demo;
//因为int占四个字节,故取int所占的大小作为union所在存储的空间
cout<<"The size of union is:"<<sizeof(demo)<<endl;
demo.ch='A';
//以char类型去访问存储的变量
cout<<"The char of demo is:"<<demo.ch<<endl;
//以int类型去访问存储的变量
cout<<"The int of demo is:"<<demo.n<<endl;
return 0;
}

结果如下:

image-20221120225842812


枚举

  • 枚举类型只有赋值运算,没有其他算数运算
  • 只能对枚举类型赋予枚举中的值
  • 枚举量是整形
  • 默认枚举中的第一个数为0,后面的数依次+1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
using namespace std;

//枚举类型的定义
enum week{one=1,two,three,four,five,six,seven};

int main(void)
{
//定义枚举对象
week demo;
//对枚举对象赋值
demo=seven;
cout<<"Today is week:"<<demo;;
return 0;
}

结果如下:

image-20221120231905948


指针

1.指针的定义与使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;

int main(void)
{
int data=100;
//指针的定义
int *p;
//指针的初始化
p=&data;//或者在定义时直接初始化int *p=&data;

cout<<"The address of data is:"<<&data<<" ,which is same as p:"<<p<<endl;
//*p是指针的解引用,表示指针指向的那个变量
cout<<"The number of data is:"<<data<<" ,which is same as *p:"<<*p<<endl;
*p=*p+5;
cout<<"Now the number of data is:"<<*p<<endl;
return 0;
}

结果如下:

image-20221121220631570

形象解释取地址&与*p:

image-20221121221749902

2.内存分配:new与delete

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;

int main(void)
{
//动态内存的分配
double *p=new double;
*p=100.11;
cout<<"The content of P is:"<<p<<",and the data of *p is:"<<*p<<endl;
//可以看出p中地址每+1,是+了指向的数据类型所占的字节数
cout<<"The P+1 is:"<<p+1<<endl;
cout<<"The P+2 is:"<<p+2<<endl;
cout<<"The P+3 is:"<<p+3<<endl;
cout<<"The address of P is:"<<&p<<endl;
//使用delete释放内存
delete p;
return 0;
}

结果如下:

image-20221121223750515

3.使用new来创建动态数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
using namespace std;

int main(void)
{
//使用new来创建动态数组
double *p=new double [3];//p最初会指向分配地址的首地址
//可以对指针使用数组的方式对其赋值
p[0]=0.1;
p[1]=0.2;
p[2]=0.3;
for(int i=0;i<3;i++)
{
cout<<"Array "<<i<<" is:"<<p[i]<<endl;
}
p=p+1;
for(int i=0;i<3;i++)
{
cout<<"Array "<<i<<" is:"<<p[i]<<endl;
}
p=p-1;
//释放动态数组
delete [] p;
return 0;
}

结果如下:

image-20221121225638392

形象解释:

image-20221121230342656
  • 动态获取输入字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<cstring>
using namespace std;

char *getname(void);

int main(void)
{
//调用getname从而分配动态数组
char *name;
for(int i=0;i<3;i++)
{
name=getname();
cout<<name<<" at address "<<(int *)name<<endl;
}
delete [] name;
return 0;
}

char *getname(void)
{
char array_name[80];
cout<<"Please enter your name:";
cin>>array_name;

char *p=new char [strlen(array_name)+1];
strcpy(p,array_name);
return p;
}

结果如下:

image-20221123150810181

4.指针与数组

  • 数组名通常代表数组中第一个元素的起始地址
  • &数组名代表整个数组的起始地址
  • 其二者的区别在于它们+1时,前者加的是元素所占的字节数,后者加的是整个数组所占的字节数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
using namespace std;

int main(void)
{
int array1[3]={1,2,3};
int *p=array1;//数组名代表数组第一个元素的起始地址
for(int i=0;i<3;i++)
{
cout<<"The address of array "<<i<<" is:"<<(p+i)<<endl;
cout<<"Array "<<i<<" is:"<<*(p+i)<<endl;
cout<<"-----------------------------------"<<endl;
}
cout<<"array1 is:"<<array1<<endl;
cout<<"&array1[0] is:"<<&array1[0]<<endl;
//注意对存地址的变量加1,加的都是那个变量所代表的整个地址
cout<<"array1 + 1 is:"<<array1+1<<endl;
cout<<"&array1 is:"<<&array1<<endl;//&array1代表整个数组的起始地址
cout<<"&array1 + 1 is:"<<&array1+1<<endl;
cout<<"sizeof(array1) is:"<<sizeof(array1)<<endl;
cout<<"sizeof(*p) is:"<<sizeof(*p)<<endl;
return 0;
}

结果如下:

image-20221122215306985

5.指针与字符串

  • C-type类型的字符串的数组名虽代表第一个字符的首地址,但打印时却会打印出地址对应的整个字符串
  • 可通过(int *)将数组名强制转化成整数指针输出,从而打印地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
using namespace std;

int main(void)
{
//指针与字符串
char charray[4]="ssy";
char *p=charray;
//打印字符串的首地址,出来的会是对应的字符串
cout<<"The charray is:"<<charray<<endl;
cout<<"The p is:"<<p<<endl;
cout<<"The &p is:"<<&p<<endl;
//将地址强制转化为整数指针,因为指针里面存储的就是地址
cout<<"The address of charray is:"<<(int *)charray<<endl;
cout<<"The address of charray is:"<<(int *)p<<endl;
cout<<"The address of p+1 is:"<<(int *)(p+1)<<endl;
cout<<"The p+1 is:"<<(p+1)<<endl;
return 0;
}

结果如下:

image-20221122224702963

6.使用new创建动态结构

  • 使用p->变量访问结构体中的变量
  • 或者使用(*p).变量访问结构体中的变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
#include<cstring>
using namespace std;

//结构体的定义
struct student{
string name;
int age;
double grates;
};

int main(void)
{
//创建动态结构
student *p=new student;
//通过p->访问结构中的变量
p->name="ssy";
p->age=21;
p->grates=99.99;
cout<<"The p->name is:"<<p->name<<endl;
cout<<"The p->age is:"<<p->age<<endl;
cout<<"The p->grates is"<<p->grates<<endl;
cout<<"Also can use (*p).,like (*p).name is:"<<(*p).name<<endl;
delete p;
return 0;
}

结果如下:

image-20221123144807095

7.结构体数组与结构体类型的指针数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<iostream>
#include<cstring>
using namespace std;

struct simple{
int data;
};

int main(void)
{
//结构体数组
simple struct_array[3];
simple *p=struct_array;
for(int i=0;i<3;i++)
{
(p+i)->data=100+i;
cout<<"struct_array data "<<i<<" is:"<<struct_array[i].data<<endl;
}

simple s1,s2,s3;
s1.data=1;
s2.data=2;
s3.data=3;

//结构体类型的指针数组
simple *pointer_array[3]={&s1,&s2,&s3};
for(int i=0;i<3;i++)
{
cout<<"The data of pointer_array "<<i<<" is:"<<pointer_array[i]->data<<endl;
}

//指向指针的指针
simple **ptr=pointer_array;
for(int i=0;i<3;i++)
{
cout<<"(*(ptr+"<<i<<"))->data "<<"is:"<<(*(ptr+i))->data<<endl;
}
return 0;
}

结果如下:

image-20221123162248897

形象解释:

image-20221123163611564

8.指针与const

  • const int *pt;//不能通过指针去改变指针所指向变量的值,但能指针所指向的地址可以改变,即指针自身所存储的内容可以被改变

    image-20221216220850065
  • int *const pt;//能通过指针去改变指针所指向变量的值,但不能改变指针中存储的内容,也就是指针一旦指定,就不能被改变去指向别的地址

    image-20221216221039467
  • const int *const pt;//结合上述二者,即不能通过指针去改变指针所指向变量的值,也不能改变指针里的内容


模板类vector与array

  • 模板类vector的调用格式:vector<typeName> vt(n_elem);
  • 模板类array的调用格式:array<typeName,n_elem> arr;
  • 需要包含的头文件有<vector><array>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<vector>
#include<array>

using namespace std;

int main(void)
{
//用vector类定义数组
vector<int> vector_array(3);
vector_array[0]=1;
vector_array[1]=2;
vector_array[3]=3;
vector<int> vector_array2(3);
//vector类可以将一个数组赋值给另一个数组
vector_array2=vector_array;

//用array类定义数组
array<double,3> array1={1.1,2.1,3.1};
array<double,3> array2;
//array类可以将一个数组赋值给另一个数组
array2=array1;

cout<<"vector_array[0] is:"<<vector_array[0]<<" at "<<&vector_array[0]<<endl;
cout<<"vector_array2[1] is:"<<vector_array2[1]<<" at "<<&vector_array2[1]<<endl;
cout<<"array1[1] is:"<<array1[1]<<" at "<<&array1[1]<<endl;
cout<<"array2[2] is:"<<array2[2]<<" at "<<&array2[2]<<endl;
return 0;
}

结果如下:

image-20221124182904615

欢迎来到ssy的世界