[C++]第三章 数据类型

第三章 数据类型(Data Types)


什么是数据类型?数据类型是指:
(1)一定的数据在计算机内部的表示方式;
(2)该数据所表示的值的集合;
(3)在该数据上的一系列操作;


C++中的数据类型,有语言既定的内部数据类型(inner types),也有程序员自定义的外部数据类型。


1、其中内部数据类型有:
整数类型(int)
字符类型(char)
布尔类型(bool)
单精度类型(float)
双精度类型(double)
还可以通过数组、指针、引用等来定义基于上面的数据类型以及其他外部数据类型的变异类型,例如:


整形数组(int [])
浮点引用(double &)
字符指针(char *)


即内部数据类型及其变异构成了C++的基本数据类型(base types)


2、程序员自定义的数据类型主要是指用class关键字构造的数据类型,除此之外,用enum、union、struct关键字也能定义单纯空间意义上的数据类型。
要解决具体问题,必须首先要学会用数据类型来描述问题中的具体事物,世界上的问题形形色色,仅用语言内部的数据类型来描述事物是远远不够的,还必须
借助于语言所提供的数据类型描述机制来自定义数据类型。


1.1整形(int types)
二进制补码(Binary Complement)
通常的计算机语言在计算机内部都是以二进制补码的形式表示整数,因为二进制补码用来表示整数具有高度的一致性,并且统一了加减法的意义,简化了乘除法的运算,甚至
直接简化了计算机的硬件结构。


类型 有符号形式 无符号形式 默认
8位 signed char unsigned char signed char
16位       signed short int unsigned short int   signed short int
32位 signed int unsigned int signed int
32位 signed long int unsigned long  int signed long int


char<=short int<=int<=long int


1.2编译器和整形长度
C++编译器在不同的计算机硬件上的表现是不同的。32位编译器是指它能将程序源代码编译成最高位32位的CPU指令系统代码,或者更加直接的说,int类型的长度是32位的。


1.3浮点数类型
//不想过多赘述……没错。


1.4C-串与string(C-strings&string)


1.4.1C-string
在C++中,有两种字符串,一种是从C沿袭过来的,称为C-字符串,简称C-串,C-串是以一个全0位(整数0)字节作为结束符的字符序列,该全0字节既是8位的整数0也是ASCII码的0。
C-串还称为ASCII串(即ASCII字符序列加上尾巴 Zero)


很显然,C-串的空间长度为字符串长度加1,如果要将C-串加入字符数组,则元素个数非比字符数多1不可。例如:
char buffer[7] ="Hello!";//若为char buffer[6]="Hello!";则为错误

我们知道字符字面值为char,那么C-串又是什么类型呢?
C-串的类型为char*,说得更准确一点,是const char*,事实上,所有的字面值类型都是const,Char*称为字符指针,它与字符数组虽然类型不同,但操作上是一样的,都表示C-串的起始地址。


1.4.2字符指针与字符数组(char Pointers& char Arrays)
指针式表示内存空间位置的类型!
字符指针就是所指向的空间位置上的值,当做字符来操作的类型,例如:
char *str="Hello";
cout<<*str<<endl;//显示H
cout<<str<<endl;//显示Hello


str是字符指针变量,*str是字符指针变量的间接引用。即若str指向"Hello"的首地址,则*str表示该地址代表的空间上的值-"H"
输出字符指针就是输出C-串。


为了比较C-串的字典序大小,在C库函数中,专门设计了C-串的比较函数strcmp。此外,还有C-串的复制问题:
char *str1="Hello";
char *str2=str1; //意味着str1与str2共享"Hello"空间。


数组复制直接告禁:
char a1[6]="Hello";
char a2[6]=a1;//错:数组是不能复制的。


因而C库函数为其设计了strcpy函数,总之,C库函数设计了一系列的C-串库函数,解决了C-串的赋值、复制、修改、比较、连接问题。


1)strcpy读作string copy,其函数声明:


char* strcpy(char* x1,char* x2);
//该函数将x2字串拷贝到x1所在位置,不论x1字串先前是什么内容,拷贝之后都将被所拷贝的内容所覆盖。且拷贝函数被调用之后,返回x1参数的首地址。
//同时,由于x2字串的长度可能比x1字串空间要长,所以strcpy的使用并不安全,需要编程时谨慎考虑。


2)strcmp读作string compare,其函数声明:


int strcmp(char *x1,char* x2);
//它表示x1与x2进行字典序比较,如果x1小则返回值为负数,如果x1大则返回非0正数,如果两者相等则返回0;


3)strcat读作string concat.其函数声明为:
char *strcat(char*x1,char*x2);
//它将x2字串的内容接在x1字串之后,或者说,将x2字串拷贝到x1字串结束处。所返回的x1字串让处理结果可以直接参加之后的操作。


4)strrev读作string reverse.其函数声明:
char * strrev(char *x);
//它将x字串倒过来,并改变原来的存储,同时直接将结果字串返回,以便于其后的操作。所以调用strrev(a)之后,将字串"Hello 123"变成"321 olleH"


5)strset读作string set其函数声明:
char* strset(char *x,char b);
//它将x整个字串的每个字符都用b字符替代,并将x作为结果返回。因此执行了strset(a,'c');,a串变成了'ccccccccc';


6)strstr读作string substring,其函数声明为:
int strstr(char *x,char* s);
//该函数在x字串中查找s字串,若找到,则返回整数1,否则返回整数0;


7)strchr读作string char,其函数声明为:
int strchr(char* x,char b);
//该函数在x字串中查找b字符,若找到,则返回整数1,否则返回整数0;


1.4.3 string
string是C++的STL提供的一种自定义的类型,它可以方便地执行C-串所不能直接执行的一切操作。它处理空间占用问题是自动的,需要多少,用多少,不像字符指针那样,
提心吊胆与指针脱钩时的空间游离。它可以从C-串转换得到,还可以从内部“提炼”出C-串……。string本身就是针对方便字符串操作来设计的。


/*在C++的STL标准中说明,iostream资源是不包含string资源说明的,而BCB编译器为表示友好,默认包含了string资源。
需要注意的是string资源和string.h不是一回事,string资源是指string字串类,string.h头文件是指诸多字符空间操作的库函数的集合。包含资源与包含头文件。


定义string实体的原始形式与定义整形变量一样,例如:
int a=35,b;
string s="Hello",t;


string还可以有参数化的定义方式。例如:
 int a(35);//35初始化
 string s("Hello");//"Hello"初始化
 string t(15,'H');//15个'H'组成一个字串
 string u(15);//15个空格组成一个字串
 
 字符指针在操作字串时,是无法进行字串内容的比较的,而string型字串可以直接进行字串内容的。例如:
 cout<<(a==s1?"":"not ")<<"equal\n";能得到"equal"的效果。
 
 string实体还能用+进行字串的拼接操作,用+=进行修改式字串拼接操作,例如代码中的a+=s2便是赋值表达式。
 
 string类型自身是没有逆反操作的,但是通过STL库中的reverse函数,便可以实现字串的逆反。reverse函数包含在资源algorithm中,它的两个参数以一头一尾的形式描述一个容器的区间,
 其功能是该容器中一头一尾区间内的所有元素颠倒位置。string实体也是一种容器,其一头一尾的标准表示就是对其实体作begin()和end()操作。
 
 string中有replace操作,它可以将由下标规定的字串区间用重复一定个数的字符来替换。a.replace(0,9,9,'c');是表示a字串从下标0开始,长度为9的字串用9个'c'字符代替。
 
 string中也有find操作,如各种搜索操作、插入操作、取长度、删除字符、删除字串、判断空串等,它与C-串具有很好的亲和性,C-串可以直接赋值给创建中的和已经存在的string实体。
 string长度可以伸缩,比较灵活。唯一的缺点是:在大量的字符处理中,性能上略逊于字符指针。
 
 1.4.4 string与C-串的输入输出(string & C-string I/O)
 
下面这行文字的输入,可以来自文件,也可以来自键盘,总之是带有回车的有若干空格的字符序列:


Hello, How are you?
则可通过循环读入单词操作将内容输送到变量中,直到读不到数据(缓冲区读完,并且没有数据可读,则流状态变成false)


for(string s;cin>>s;)
cout<,s<<" ";
cout<<endl;
或者:
for(char a[10];cin>>a;)
cout<<a<<" ";
cout<<endl;
//cin的读入方式总是将前导的空格(所谓空格,即包括空格、回车、水平或垂直制表符)滤掉,将单词读入,当遇到空格时结束本次输入。


也可以用getline将其一次性地输入:


string s;
getline(cin,s);//cin为标准输入流 s必须为string 类型 //cin和getline为友缘函数
cout<<s<<endl;
或者
char a[40];
cin.getline(a,40);//成员函数,形式参数一定要是字符数组或字符指针
cout<<a<<endl;


注意两者使用getline格式上的差异,getline总是将行末的回车符撤掉。


如果是逐个字符输入,那应该如何呢?
for(char ch;(ch=cin.get())!='\n';)
cout<<ch;
cout<<endl;


1.4.5 string流(string streams)
 如果一个文件aaa.txt,有若干行,不知道每行含有几个整数,要编程输出每行的整数和,该怎么实现?
 由于cin>>不能辨别空格与回车的差异,因此只能使用getline的方式逐行读入数据到string实体中,但在string实体中分离若干个整数还是显得有些吃力,一个好的方式是string流。
 
#include<iostream>
#include<sstream>
#include<fstream>


using namespace std;


int main()
{
ifstream in("aaa.txt");
for(string s;getline(in,s);)//in是文件输入流 一行一行的读取
{
int a,sum=0;
for(istringstream sin(s);sin>>a;sum+=a);
/*/
istringstream是输入string流,它在sstream资源中说明,该语句类似文件流操作,只不过创建sin流时,
其参数为string对象,它是将string的实体看作是一个输入流,因而sin>>a即是从string流中输入到整数a中,输啊输,一直
输到string中的最后一个整数!
string流很有用,有时候要将内容先逐个输出到string中,最后才根据计算结果来编排输出格式,这时候,用string流很管用。


*/
cout<<sum<<endl;
}


return 0;
}
由于string可以很方便的修改、复制、插入、删除、拼接、比较等,所以在输入/输出流中,还能够进一步编辑流的格式,对于程序处理的统一性、方便性带来了莫大的好处。


getline函数返回的是流状态,通过其可以判断文件是否还有数据行可读。









你可能感兴趣的:([C++]第三章 数据类型)