处理数据<此章编程练习过几天附上>
- 1.变量
- 1.1变量名
- 1.2 整型
- 1.3 整型 short、int、long和long long
- 1.3.1 运算符sizeof和头文件limits
- 1.3.2 初始化
- 1.3.3 C++11初始化方式
- 1.4 无符号类型
- 1.5整型类型的选择
- 1.6 整型字面量
- 1.7 C++如何确定常量的类型
- 1.7.1 后缀,后缀是放在数字常量后面的字母,用于表示类型。
- 1.72 长度。在C++中,对十进制整数采用的规则,与十六进制和八进制采用的规则稍微有些不同。
- 1.8 char类型:字符和小整数
- 1.8.1 程序演示
- 1.8.2 成员函数
- 1.8.3 转义序列
- 1.8.4 wchar_t
- 1.8.5 C++11新增的类型:char16_t和char32_t
- 1.9 bool类型
- 2. const限定符
- 3. 浮点数
- 3.1浮点的书写
- 3.2 浮点类型
- 3.3 浮点常量
- 3.4 浮点数的优缺点
- 4. C++算术运算符
- 4.1 除法
- 4.2 求模运算符
- 4.3 类型转换
- 4.3.1 初始化和赋值进行的转换
- 4.3.2 以{}方式初始化时进行的转换(C++11)
- 4.3.3表达式中的转换
- 在同一个表达式中包含两种不同的算术类型时,C++将执行两种自动转换:
- 有些类型在与其他类型同时出现在表达式时,将被自动转化。
- 4.3.4 传递参数是的转换
- 4.3.5 强类型转换
- 4.3.6 C++11中的auto声明
- 总结
1.变量
程序都需要存储信息。为把信息存储在计算机中,程序必须记录3个基本属性:
- 信息将存储在哪里。
- 要存储什么值。
- 存储何种类型的信息。
例,int number = 100;中,程序将找到一块能存储整数的内存,将该内存单元标记为number,并将100复制到该内存单元中;然后,就可以在程序中使用number来访问该内存单元。
1.1变量名
C++变量名命名规则:
- 在名称中只能使用字母符号、数字和下划线(_)。
- 名称的第一个字符不能是数字。
- 区分大写字符与小写字符。
- 不能用C++关键字作为名称。
- 以两个下划线或下划线和大写字母大头的名称被保留给实现(编译器及其使用的资源)使用。以一个下划线开头的名称被保留给实现,用作全局标识符。
- C++对名称的长度没用限制,名称中所以的字符都有意义,但有些平台有长度限制。
1.2 整型
- 符号类型:可以表示正值和负值。
- 无符号类型:不能表示负值。
- 术语宽度:用于描述存储整数时使用的内存量。使用的内存越多,则越宽。
- C++的基本整形(按宽度梯增的顺序排列):分别时char,short,int,long和C++11新增的long long,其中每个类型都有符号版本和无符号版本因此共有10钟类型供选择。
1.3 整型 short、int、long和long long
术语宽度是用于描述存储整数时使用的内存量。使用的内存越多,则越宽。C++的基本整形按宽度递增的顺序排列为:char、short、int、long、和C++11新增的longlong。
- short至少16位;
- int至少与short一样长;
- long至少32位且至少与int一样长;
- longlong至少64位,且至少与long一样长;
计算机内存由一些叫做位(bit)的单位组成。
显示short、 int、 long、 longlong在系统中的最大长度。
#include<iostream>
#include<climits>
int main()
{
using namespace std;
int n_int = INT_MAX;
short n_short = SHRT_MAX;
long n_long = LONG_MAX;
long long n_llong = LLONG_MAX;
cout << "int is " << sizeof(int) << " bytes." << endl;
cout << "short is " << sizeof n_short << " bytes." << endl;
cout << "long is " << sizeof n_long << " bytes." << endl;
cout << "long long is " << sizeof n_llong << " bytes" << endl;
cout << endl;
cout << "Maximum values:" << endl;
cout << "int: " << n_int << endl;
cout << "short: " << n_short << endl;
cout << "long: " << n_long << endl;
cout << "long long: " << n_llong << endl << endl;
cout << "Minimum int value = " << INT_MIN << endl;
cout << "Bits per byte = " << CHAR_BIT << endl;
return 0;
}
1.3.1 运算符sizeof和头文件limits
sizeof运算符指出,在使用8位字节的系统中,int的长度为4字节。可对类型名或变量名使用sizeof运算符。对类型名(如int)使用sizeof运算符时,应将类型名称放在括号中;但对变量名(如n_short)使用该运算符,括号是可选的。
cout << “int is " << sizeof(int) << " bytes.” << endl;
cout << “short is " << sizeof n_short << " bytes.” << endl;
头文件climits定义了符号常量来表示类型的限制。如,INT_MAX表示类型int在当前系统能够存储的最大值。

1.3.2 初始化
初始化将赋值与声明合并在一起。
可以使用字面值常量来初始化
int n_int = 5;
可以将变量初始化成另一个变量,条件是后者已经定义过了的。
int aunts = n_int;
可以使用表达式来初始化变量,条件是当程序执行到该声明时,表达式中的所以值是已知的。
int chairs = aunts + n_int + 5;
警告:如果不对函数内部顶的变量进行初始化,该变量的值将是不确定的。这意味着该变量的值将是它被创建之 前,相应内存单元保存的值。
1.3.3 C++11初始化方式
使用大括号的方式:
(1)采用这种方式时,可以使用等号(=),也可以不使用:
int emus{7};
int rheas = {12};
(2)在大括号内可以不包含任何东西。在这种情况下,变量将被初始化为零:
int rocs = {};
int psychics{};
(3)这有助于更好的防范类型转换错误。
以前的C++使用不同的方式来初始化不同的类型,而C++11使得可将大括号({ })初始化器用于任何类型,这是一种通用的初始化语法。
1.4 无符号类型
short、int、long和long long 这四种整型都有一种不能存储负数值的无符号变体,其优点是可以增大变量能够存储的最大值。例:short表示范围位-32768到+32768(int、long、long long类型,依此类推),则无符号的版本的表示范围为0 – 65535。仅当数值不会为负时才应使用无符号类型,如人口,粒数等。
创建无符号版本的基本整型,需要unsigned关键字来修改声明:
unsigned short change;
unsigned int rovert;
unsigned quarterback;
unsigned long gone;
unsigned long long lang_lang;
注:unsigned本身是unsigned int的缩写。
程序:使用无符号类型,并说明程序试图超越整型的限制是将产生的后果。最后再看看预处理器#define。
#include<iostream>
#define ZERO 0//#define用来指定常量
#include<climits>
int main()
{
using namespace std;
short sam = SHRT_MAX;
unsigned short sue = sam;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl
<< "Add $1to each account." << endl << "Now";
sam = sam + 1;
sue = sue + 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited.\nPoor Sam!" << endl;
sam = ZERO;
sue = ZERO;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl;
cout << "Take $1 from each account." << endl << "Now";
sam = sam - 1;
sue = sue - 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars dposited." << endl << "Lucky Sue!" << endl;
return 0;
}
该程序将sam和sue分别设置为最大的short值,在系统上,是32767。然后将这些值都加1.对于sue来说没有问题,因为新值仍比无符号整数的最大值小得多;但sam的值从32767变成了-32768同样,对于sam,将其设置为0并减去1,也不会有问题;但对于无符号变量sue,将其设置为0并减去后,就变成了65535。可以看出,这些整型变量的行为就像里程表。如果超越了限制,其值将为范围另一端取值。C++确保了无符号整型的这种行为;但C++并不保证符号整型超越限制(上溢和下溢)时不出错,而这正是当前实现中最为常见的行为。
1.5整型类型的选择
通常,int被设置为对目标计算机而言最为“自然”的长度。自然长度指的是计算机处理起来效率最高的长度。如果没有非常有说服力的理由来选择其他类型,则应使用int。
可能使用其他类型的原因:
- 知道变量可能表示的整数值大于16位整数的最大可能值,则使用long。即使系统上int位32位,也应这样做。这样,将程序移植到16位系统时,就不会突然出现无法正常工作。
- 如果存储的值超过20亿,可使用long long。
- 如果short比int小,则使用short可以节省内存。通常,仅当有大型整数数组时,才有必要使用short。(数组是一种数据结构,在内存中连续存储同类型的多个值。)如果节省内存很重要,则使用short而不是使用int,即使它们的长度是一样的。例:假设程序从int位16位的系统移到int位32位的系统,则用于存储int数组的内存量将翻倍,但short数组不受影响。请记住,节省一点就是赢一点。
- 如果只需要一个字节,可以使用char。
1.6 整型字面量
整型字面量(常量),如212或1776。与C相同,C++能够以三种不同的技术方式来书写整数,分别是:基数为10,基数为8(老式的UNIX版本),基数为16(硬件黑客的最爱)。
C++表示法:C++使用前一两位来表示数字常量的基数。
- 第一位为1~9,则基数为10(10进制);因此93为10进制。
- 第一位为0,第二位为1~7,则为8(八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。);因此042的基数是8,相当于10进制数34。
- 如果前两位为0x或0X,则基数为16(16进制)英文字母A,B,C,D,E,F分别表示数字10~15计数到F后,再增加1个,就进位;因此0x42为16进制,相当于十进制数66。
程序:演示三种基数。
#include<iostream>
int main()
{
using namespace std;
int chest = 28; //十进制
int waist = 0x28; //十六进制
int inseam = 027; //八进制
cout << "Monsieur cuts a striking figure!\n";
cout << "chest = " << chest << " (28 in decimal)\n";
cout << "waist = " << waist << " (0x28 in octal)\n";
cout << "inseam = " << inseam << " (027 in octal)\n";
return 0;
}
如,在视频内存段为十六进制B000,则不必在程序中使用之前将它转换为十进制数45056,只需要使用0xB000即可。不管把值书写成十进制、八进制还是十六进制,都将以相同的方式存储在计算机中------被存储为二进制数(以2位基数)。
如果要以十六进制或八进制方式显示值,则可以使用cout的一些特殊性。头文件iostream提供了控制符endl,用于指示cout重起一行。它还提供了dec(十进制)、hex(十六进制)和oct(八进制),分别用于指示cout以十进制,十六进制,八进制格式显示整数。
程序:使用hex和oct以上述三种格式显示十进制42。
#include<iostream>
int main()
{
using namespace std;
int chest = 42;
int waist = 42;
int inseam = 42;
cout << "Monsieur cuts a striking figure!" << endl;
cout << "chest = " << chest << " (decimal for 42)" << endl;//10进制
cout << hex;//十六进制
cout << "waist = " << waist << " (hexadecimal for 42)" << endl;
cout << oct;//八进制
cout << "inseam = " << inseam << " (octakl for 42)" << endl;
return 0;
}
诸如cout << hex;等代码不会在屏幕上显示任何内容,而只是修改cout显示整数的方式。因此,控制符hex实际上是一条消息,告诉cout采取何种行为。另外,由于标识符hex位于名称空间std中,二而程序使用了该名称空间,因此不能将hex用作变量名。然而,如果省略编译命令using,二使用std::cout、std::endl、std::hex、std::oct,则可以将hex用作变量名。
1.7 C++如何确定常量的类型
程序的什么,声明将特定的整型变量的类型告诉了C++编译器,假设程序使用常量表示一个数字:
cout << "Year = " << 1492 << “\n”;
程序将八1492存储为int类型,原因是,除非有理由存储为其他类型(使用了特殊的后缀来表示特定的类型,或者值太大,不能存储为int),否则C++将整型常量存储为int类型。
1.7.1 后缀,后缀是放在数字常量后面的字母,用于表示类型。
- 整数后面的l(小写l)或L后缀表示该整数为long常量,u或U后缀表示unsigned int常量,ul(可以采用任何一种顺序大小写均可)表示unsigned long常量(由于小写l看上去像1,因此应使用大写L做后缀)。例如,在int为16位,long位32位的系统上,数字22022倍存储为int,占16位,数字22022L被存储为long,占32位。同样,22022LU和22022UL都被存储unsigned long。
- C++11提供了用于表示long long的后缀ll(小写)或LL,还提供了用于表示类型unsigned long long的后缀ull、Ull、uLL和ULL。
1.72 长度。在C++中,对十进制整数采用的规则,与十六进制和八进制采用的规则稍微有些不同。
- 对于不带后缀的十进制数,将使用下面几种类型中能够存储该值的最小类型来表示:int、long或long long。在int为16位、long位32位的计算机系统上,20000被表示为int类型,40000倍表示long类型,30,0000,0000被表示为long long类型。
- 对于不带后缀的十六进制或八进制整数,将使用下面几种类型中能够存储该值的最小类型来表示:int、unsigned int、long、unsigned long、long long或unsigned long long。在将40000表示为long类型的计算机系统中,十六进制数0x9C40(40000)将被表示为unsigned int。这是因为十六进制常用来表示内存地址,而内存地址是没有符号的,因此,unsigned int比long更适合用来表示16位的地址。
1.8 char类型:字符和小整数
最常用的符号集是ASCII字符集。字符集中的字符用数值编码表示。例,字符M的编码是77,字符X的编码是88。
char类型是专为存储字符(如字母和数字)而设计的。存储数字对于计算机没什么,但存储字母就是另一回事了。编程语言通过使用字母的数字编码解决了这个问题。因此,char类型是另一种类型。
- char类型是用来表示目标计算机系统中的所有基本符号-------所有的字母、数字、标点符号等。
- char虽然最常被用来处理字符,但也可以将它用做比short更小的类型。
- 只能表示一个符号,并且要用单引号(‘’)括起来。
C++的实现使用的是其主机系统的编码------例,IBM大型机使用EBCDIC编码,如国际Unicode字符集使用的值。
程序演示char类型:
#include<iostream>
int main()
{
using namespace std;
char ch;
cout << "Enter a character: " << endl;
cin >> ch;
cout << "Hola!";
cout << "Thank you for the " << ch << " charcater." << endl;
return 0;
}
假设,该程序运行后用户X输入X,为什么程序打印的是X,而不是字符编码88。通过查看内存可以知道,88是存储在变量ch中的值。这个不是因为char类型的特性导致的,而是cin和cout,这些工具为你完成了转换工作。输入是cin将键盘输入的X转换为XX;输出是,cout将88转换为所显示的字符X;cin和cout的行为都是由变量类型所引导的。如果将55存储在int变量中,则cout将把它显示为55(也就是显示两个字符5)。
1.8.1 程序演示
如何在C++中书写字符面值。
#include<iostream>
int main()
{
using namespace std;
char ch = 'X';//将X的ASCII码赋给ch
int i = ch;//将相同的代码存储在int类型中
cout << "The ASCII code for " << ch << " is " << i << endl;
cout << "Add one to the character code: " << endl;
ch = ch + 1;
i = ch;
cout << "The ASCII code for " << ch << " is " << i << endl;
cout << "Displaying char ch using cout.put(ch): ";
cout.put(ch);
cout.put('!');
cout << endl << "Done" << endl;
return 0;
}
- 将字符用单引号括起来。cout把ch显示为X,而把i显示为88。就如前所述,值得类型将引导cout选择如何显示值。
- C++将字符表示为整数提供了方便,使得操作字符值很容易。不必使用笨重的转换函数在字符和ASCII码之间来回转换。
- 即使通过键盘输入的数字也被视为字符。如下:
char cc;
cin >> cc; - cout.put()该函数显示一个字符。
1.8.2 成员函数
cout.put()就是一个成员函数,它中间有一个句点(.),句点被称之为成员运算符。函数cout.put()是一个重要的C++OOP概念----成员函数-----的一个例子。类定义了如何表示和控制数据。成员函数归类所有,描述了操纵类数据的方法。例如类ostream中有一个put()成员函数,用来输出字符。只能通过特定对象(例如cout对象)来使用成员函数。要通过对象(cout)使用成员函数,就必须用句点将对象名和函数名称(put())连接起来(cout.put())。
cout.put()的意思是,通过类对象cout来使用函数put()。
cout.put()成员函数,可以替换 << 运算符。
1.8.3 转义序列
C++提供了一种特殊的表示方法------转义序列。例,\a振铃字符,它可以使终端扬声器振铃。转义序列\n
表示换行符,\”将双引号作为常规字符,而不是字符串分隔符。
转移序列可以在字符串和字符常量中使用这些表示法。
注意,应该像处理常规字符(如Q)那样处理转义序列(如\n)。也就是说,将他们作为字符常量时,应用单引号括起来;将它们放在字符串中时,不要使用单引号。
现代系统并非都支持所有的转义序列。例如,出入振铃符时,有些系统保持沉默。
换行符可代替endl,用于输出中重起一行。可以以字符串常量表示法(‘\n’)或字符串方式(“\n”)适应换行符。下列三行代码效果一致。
cout << endl;
cout << '\n';
cout << "\n";
提示:在可以使用数字转移序列或符号转义序列时(如\0x8和\b),应使用符号转义序列。数字表示与特定的编码方 式相关(如ASCII码),而符号表示适用于任何编码方式,其可读性更强。
程序演示
转义序列的一些使用:
#include<iostream>
int main()
{
using namespace std;
cout << "\aPeration \"HyperHype\" is now activated!\n";
cout << "Enter your agent code:________\b\b\b\b\b\b\b\b";
long code;
cin >> code;
cout << "\aYou entered " << code << "...\n";
cout << "\aCode verified! Proceed with Plan Z3!\n";
return 0;
}
注意:有些基于ANSI C之前的编译器的C++系统不能识别\a。对于使用ASCII字符集的系统,可以用\007替换\a。有些系统的行为可能有所不同,例如可能将\b显示为一个小矩形,而不是退格,或者在退格时删除,还可能忽略\a。
signed char和unsigned char
与int不同的是,char在默认情况下即不是没有符号,也不是有符号。是否有符号由C++实现决定,这样编译器开发人员可以最大限度的将这种类型与硬件属性匹配起来。
- unsigned char类型的表示范围为0 ~ 255。
- signed char类型的表示范围为-128 ~ +127。
- 当使用一个char类型变量来存储200这样的大值时,有可能在某些系统上不可以,但使用unsigned char可以在任何系统上达到此目的。
- 如果使用char变量来存储标准ASCII字符,则char有没有符号都没有关系,在这种情况下可以使用char。
1.8.4 wchar_t
程序需要处理的字符可能无法用一个8位的字节表示,如汉子或日文系统。wchar_t类型就可以处理,它是一种整数类型,有足够的空间,可以表示系统使用使用的最大扩展字符集。这种类型与另一种类型(底层(underlying)类型)的长度和符号属性相同。
- cin和cout将输入和输出看做char流,因此不适合wchar_t类型。
- iostream因此提供了相识的工具wcin和wcout,可用于wchar_t流。
- 可以通过加上前缀L来指示宽字符常量和宽字符串。 例:wchar_t pop = L’p’; cout << L"tall\n";
1.8.5 C++11新增的类型:char16_t和char32_t
当wchar_t无法满足需求的时候,就可以使用无符号类型char16_t和char32_t。
- char16_t为16位无符号类型,char32_t为32位无符号类型。
- 使用前缀u表示char16_t的字符常量和字符串常量,如u’C’和u”be good”;使用前缀U表示char32_t的字符常量和字符串常量,如U’T’和U”dive a”。
- 类型char16_t与/u00F6形式的通用字符名匹配;类型char32_t与/U0000222B形式的通用字符名匹配。
#include<iostream>
int main()
{
using namespace std;
char16_t ch1 = u'q';
char32_t ch2 = U'\U0000222B';
cout << ch1 << '\n';
cout << ch2 << "\n";
}
1.9 bool类型
- 在计算中,bool变量的值是true和false。
- 任何字面值或指针值都可以被隐式转换(即不用显式强制转换)为bool值。例, int ans = true;//0 int piomise = false;//1
- 任何非零值都被转换为ture,而零被转换为false。例, bool ans = -100;//true bool promise = 0;//false
2. const限定符
常量的符号名称,符号名称指出了常量表示的内容。如果程序在多个地方使用同一个常量,则需要修改该常量时,只需要修改一个符号定义即可。这种方法就是使用const关键字来修改变量声明和初始化。
例,const int Months = 12;
- 常量被初始化后,其值不能再被修改。
- 关键字const叫做限定符,因为它限定了声明的含义(不能被修改的含义)。
- 创建常量的通用格式:const type name = value;
常见的常量名命名方式:
- 名称的首字母大写。
- 整个名称全部大写。
- 以字母k开头,如knumber。
const相比#define的优点:- 能够明确指定类型。
- 可以使用C++的作用域规则将定义限制在特定的函数或文件中(作用域描述了名称在各个模块中的可知程度)。
- 可以将const用于更复杂的类型。
注意:在C++中优先使用const创建常量而不是#define来创建。
3. 浮点数
浮点类型是C++的第二组基本类型。浮点数能够表示带小数部分的数、非常大和非常小的值,提供的范围也更大。计算机将这样的值分为两个部分存储。一部分表示值,另一部分用于对值进行放大或缩小。比如,对数字31.4125和31412.5,它们除了小数点的位置不同外,其他都是相同的。就把第一个数表示为0.314125(基准值)和100(缩放因子),而将第二个数表示为0.314125(基准值相同)和10000(缩放因子更大)。缩放因子的 作用是移动小数点的位置,术语浮点因此而得名。C++内部表示浮点的方法与此相同,只不过它基于的是二进制数,因此缩放因子是2的幂,不是10的幂。
3.1浮点的书写
书写方法分为两种:标准小数点表示法和E(不区分大小写)表示法。
-
标准小数点表示法:例,3.12、3.0、321.1234252
-
E表示法:例,3.45E6,这指的是3.45与1000000相乘的结果;E6指的是10的6次方,即1后面6个0。因此, 3.45E6表示的是3450000,6被称为指数,3.45被称为尾数。
- E表示法确保数字以浮点格式存储,即使没有小数点。
- 即可以使用E也可以使用e,指数可以是整数也可以是负数。
- 数字中不能有空格,因此7.2 E6是非法的。
- 指数为负数意味着除以10的乘方,而不是乘以10的乘方。因此,8.33E-4表示8.33/104,即0.000833。
- -8.33E4值得是-83300。前面的符号用于数值,而指数的符号用于缩放。
- 记住:d.dddE+n指的是将小数点右移n位,而d.dddE-n指的是将小数点左移n位。之所以称之为“浮点”,就是因为小数点可移动。
3.2 浮点类型
C++有3种浮点类型:float、double、和long double。这些类型数按它们可以表示的有效数位和允许的指数最小范围来描述的。
有效位
- 是指数字中有意义的位。即山的是高度位3124米,该数字有5个有效位,指出了最接近米数。
- 但数字14000,有效位为2。即,末尾为0的数字不算有效位。其余的三位为占位符。
- 有效位不依赖于小数点。即,3.1415的有效位为5,这是因为这个值精确到了第5位。
- 通常float为32位,double为64位,long double为80、96或126位。
- 这三种类型的有效位可以一样多。
- 这三种类型的有效范围至少是-37到37。
程序:演示float和double类型及它们表示数字时在精度方面的差异。
#include<iostream>
int main()
{
using namespace std;
/*
ostream方法setf()。这种调用迫使输出使用定点表示法,以便更好的了解精度,
它防止程序把较大的值切换为E表示法,并使程序显示到小数点后6位。
参数ios_base::fixed, ios_base::floatfield是通过包含iostream来提供的常量。
*/
cout.setf(ios_base::fixed, ios_base::floatfield);
float tub = 10.0 / 3.0;
double mint = 10.0 / 3.0;
const float million = 1.0e6;
cout << "tub = " << tub;
cout << ", a million tubs = " << million * tub;
cout << ",\nand ten million tubs = ";
cout << 10 * million * tub << endl;
cout << "mint = " << mint << " and a million mints = ";
cout << million * mint << endl;
return 0;
}
cout会删除结尾的0。例如,将3333333.250000显示为3333333.25。调用cout.setf()将覆盖这种行为,至少在新的实现中是这样。
3.3 浮点常量
如果希望常量为float类型,则使用f或F后缀。对于long double类型,可使用l或L后缀。
例:1.234F,1.234f,4.23L,3.24L
3.4 浮点数的优缺点
两大优点:
- 可以表示整数之间的值。
- 由于有缩放因子,可以表示的范围大得多。
缺点:
- 浮点运算的速度比整数运算的速度慢,且精度将降低。
类型分类
- 类型signed char、short、int和long、long long统称为符号类型;它们的无符号版本统称为无符号类型。
- bool、char、wchar_t、char16_t和char32_t符号整数和无符号整数统称为整型。
- float、double和long double统称为浮点型。整数和浮点型统称为算术类型。
4. C++算术运算符
程序:+、-、*、/。
#include<iostream>
int main()
{
using namespace std;
float hats, heads;
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << "Enter a number: ";
cin >> hats;
cout << "Enter another number: ";
cin >> heads;
cout << "hats = " << hats << "; heads = " << heads << endl;
cout << "hats + heads = " << hats + heads << endl;
cout << "hats - heads = " << hats - heads << endl;
cout << "hats * heads = " << hats * heads << endl;
cout << "hats / heads = " << hats / heads << endl;
return 0;
}
输入hats = 11.17、heads = 50.25相加应等于61.42,但输出中却是61.419998.这不是运算问题;而是由于float类型表示有效位数的能力有限。对于float,C++只保证6位有效位。如果将61.419998四舍五入成6位,将得到61.4200,这是保证精度下的正确值。如果需要更高的精度,请使用double或long double。
4.1 除法
如果两个操作数都是整数,则C++将执行整数除法。这意味着结果的小数点将被丢弃,使得最后的结果是一个整数。如果其中一个(或两个)操作数是浮点值,则小数部分将保留,结果为浮点数。
#include<iostream>
int main()
{
using namespace std;
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << "Integer division: 9/5 = " << 9 / 5 << endl;
cout << "Floating-point division: 9.0/5.0 = ";
cout << 9.0 / 5.0 << endl;
cout << "Mixed division : 9.0/5 = " << 9.0 / 5 << endl;
cout << "double constants: l.e7/9.0 = ";
cout << 1.e7 / 9.0 << endl;
cout << "float constants: 1.e7f/9.0f = ";
cout << 1.e7f / 9.0f << endl;
return 0;
}
注:如果编译器不接受ios_base就直接使用ios。
浮点常量的默认情况下是double类型。
4.2 求模运算符
求模运算符返回整数除法的余数。它与整数除法相结合,尤其适用于解决一些将一个量分成不同的整数单元的问题,如单位之间换算。
程序:用整数除法来计算合计多少石,再用求模运算符计算余下多少磅。
#include<iostream>
int main()
{
using namespace std;
const int Lbs_per_stn = 14;
int lbs;
cout << "Enter your weight in pounds: ";
cin >> lbs;
int stone = lbs / Lbs_per_stn;
int pounds = lbs % Lbs_per_stn;
cout << lbs << " pounds are " << stone
<< " stone, " << pounds << " pounds(s).\n";
return 0;
}
4.3 类型转换
由于有11种整型和3种浮点类型,处理量大,C++将自动执行很多类型转行:
- 将一种算术类型的值赋给另一种算术类型的变量时,C++将对值进行转换。
- 表达式中包含不同类型时,C++将对值进行转换。
- 将参数传递给函数时,C++将对值进行转换。
4.3.1 初始化和赋值进行的转换
C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换位接收变量的类型。
按类型取值范围,小转大自动转,大转小的话就会出现某些问题。例,将一个很大的long值(如2111222333)赋给float变量将降低精度。因为float只有6位有效数字,因此这个值将被四舍五入位2.11122E9。
潜在的数值装换问题:
- 较大浮点类型转换为较小浮点类型。精度(有效位)降低,值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的。
- 将浮点类型转换为整型。小数部分丢失,原来的值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的。
- 将较大的整型装换为较小的整型,如将long转换为short。原来的值可能超出目标类型的取值范围,通常只复制右边的字节。
传统初始化的行为与赋值相同,程序:初始化进行的转换。
#include<iostream>
int main()
{
using namespace std;
cout.setf(ios_base::fixed, ios_base::floatfield);
float tree = 3;
int guess(3.9832);
int debt = 7.2E12;
cout << "guess = " << guess << endl;
cout << "tree = " << tree << endl;
cout << "debt = " << debt << endl;
return 0;
}
程序说明:
- 浮点转换为整型时。舍弃小数点部分,而不是四舍五入。
- 当赋予的值大于类型范围时。则,取此类型在当前系统、编译器而定的值。
当整数变量初始化为浮点时,有些编译器将提出警告,指出这个可能丢掉数据。
4.3.2 以{}方式初始化时进行的转换(C++11)
C++11将使用大括号({})的初始化称为:列表初始化,这种初始化常用于给复杂的数据类型提供值列表。它对类型转换要求更加的严格。具体的讲:
- 列表初始化不允许“缩窄”,即变量的类型可能无法表示赋给它的值。例,浮点类型转换为整型。
- 在不同的整型之间转换或将整型转换为浮点型可能被允许,条件是编译器知道目标变量能够正确的存储给它的值。例,long变量初始化为int值,因为long总是至少与int一样长;相反的转换也可能被允许,只要int变量能够存储赋给它的long值。
4.3.3表达式中的转换
在同一个表达式中包含两种不同的算术类型时,C++将执行两种自动转换:
- 一些类型在出现时便会“自动转换”。
在计算表达式时,C++将bool、char、unsigned char、signed char、和short的值转换为int。具体地说,true 被转换为1,false被转换为0。这些转换被称之为:整型提升。
例:short st = 20;
short sh = 32;
short so = st + sh;
C++程序取得st和sh的值,并将它们转换为int类型。然后程序将结果转换为short类型,因为结果被赋予一个short变量。通常将int类型选择为计算机最自然的类型,这以为这计算机使用该类型时,运行速度可能最快。
其他的整型提升: - 如果short比int短,则unsigned short类型将转换为int。
- 如果两种类型的长度相同,则unsigned short类型转换为unsigned int。此规则确保了unsigned short在进行提升时不会损失数据。
- wchar_t被提升为下列类型中第一个宽度足够存储wchar_t取值范围的类型:int、unsigned int、long和unsigned long。
有些类型在与其他类型同时出现在表达式时,将被自动转化。
将不同类型进行算术运算时。例int与float相加,较小的类型将被转换为较大的类型。这是编译器通过效验表来确定在算术表达式中执行的转换。C++11对此效验表做出了修改,编译器将一次查阅该列表:
- 如果有一个操作数的类型是long double,则将另一种操作数转换为long double。
- 否则,如果有一个操作数的类型是double,则将另一个操作数转换为double。
- 否则,如果有一个操作数的类型是float,则将另一个操作数转换为float。
- 否则,说明操作数都是整型,因此执行整型提升。
- 在这种情况下,如果两个操作数都是有符号或无符号的,且其中一个操作数比另一个操作数的级别要低,则转换为级别高的类型。
- 如果一个操作数为有符号,另一个操作数为无符号,且无符号操作数的级别比有符号操作数的级别高,则将有符号操作数转换为无符号操作数所属的类型。
- 否则,如果有符号类型可以表示无符号类型的所有可能取值,则将无符号操作数转换为有符号操作数所属的类型。
- 否则,将两个操作数都转换为有符号类型的无符号版本。
ANSI C遵循的规则与ISO 2003 C++相同,这与前述的规则稍有不同;而传统K&R C的规则又与ANSI C稍有不同。例,传统C语言总是将float提升为double,即使两种级别都是float。
整型级别的概念:
- 有符号整型按级别从高到低一次为long long、long、int、short和signed char。
- 无符号整型的排序与有符号整型的排序相同。
- 类型char、signed char和unsigned char的级别相同。
- 类型bool的级别最低。
- Wchar_t、char16_t和char32_t的级别与底层类型相同。
4.3.4 传递参数是的转换
- 传递参数时的类型转换通常由C++函数原型控制。也可以取消原型对参数传递的控制,尽管并不明智。
- C++将对char和short类型(signed和unsigned)应用整型提升。
- 为保持与传统C语言中大量代码的兼容性,在将参数传递给取消原型对参数传递控制的函数时,C++将float参数提升为double。
4.3.5 强类型转换
强制类型转换的格式有两种如下:
(typeName)value;
value(typeName);
第一种格式是C语言,第二种格式是纯粹的C++。强制类型转换不会修改变量本身,而是穿件一个新的、指定类型的值。
四个强制类型转换运算符之一,static_cast<>可用于将值从一种数值类型转换为另一种数值类型。格式,static_castvalue;
程序显示:两种基本的强制类型转换和static_cast<>。
#include<iostream>
int main()
{
using namespace std;
int auks, bats, coots;
auks = 19.99 + 11.99;
bats = (int)19.99 + (int)11.99;//类型转换为int
coots = int(19.99) + int(11.99);//类型转换为int
cout << "auks = " << auks << ", bats = " << bats;
cout << ", coot = " << coots << endl;
char ch = 'Z';
cout << "The code for " << ch << " is ";
cout << int(ch) << endl;//类型转换为int
cout << "Yes, the code is ";
cout << static_cast<int>(ch) << endl;//类型转换为int。using static_cast
return 0;
}
4.3.6 C++11中的auto声明
让编译器能够根据初始值的类型推断出变量的类型。在初始化声明中,使用关键字auto,而不指定指定变量的类型,编译器将把变量的类型设置成与初始值相同。
#include<iostream>
int main()
{
using namespace std;
auto n = 100;//设置为int
auto x = 1.5;//设置为double
auto y = 1.3e12L;//设置为long double
cout << n << endl;
cout << x << endl;
cout << y << endl;
}
不要过度的依赖auto声明使用于简单情形,例如:double类型的0.0。将会导致变量初始化为0而不是0.0。
处理复杂类型,如标准模块(STL)中的类型时,自动类型推断的有时能显示出来。
例,对于C++98代码:
std::vector<double> scores;
std::vector<double>::iterator pv = scores.begin();
C++11允许将其重写为下面形式:
std::vector<double> scores;
auto pv = scores.begin();
总结
C++的基本类型分为两组:有存储为整数的值组成和由存储为浮点格式的值组成。
- 整型之间通过存储值时使用的内存量及有无符号来区分。
- 整型从小到大依次是:bool、char、signed char、unsigned char、short、unsigned short、int、unsigned int、long、unsigned long以及C++11新增的long long和unsigned long long。而wchar_t类型它在这个序列中的位置取决于实现。
- C++11新增类型char16_t和char32_t,它们的宽度以分别存储16和32位的字符编码。
- C++确保了char足够大,能够存储系统基本字符集中的任何成员。
- wchar_t则可以存储系统扩展字符集的任何成员,short至少16位,而int至少与short一样长,long至少为32位,且至少和int一样长。确切的长度取决于实现。
- 字符通过其数值编码来表示。I/O系统决定了编码是被解释为字符还是数字。
浮点类型可以表示小数值以及比整型能够表示的值大得多的值。 - 3种浮点类型分别是float、double和long double。
- 通常,float使用32位内存,double使用64位,long double使用80到128位。
- 通过提供各种长度不同,有符号和无符号的来,能够根据特定的数据要求悬着合适的类型。
C++使用运算符来提供对数字类型的算术运算:加、减、乘、除和求模。对变量赋值、在运算中使用不同类型、使用强制类型转换时,C++将把值从一种类型转换为另一种类型。很多类型转换都是“安全的”,即可以在不损失和改变数据的情况下完成转换。例,int转换为long则是完全安全的。浮点类型转换为整型时,则需要多加小心。
本文详细介绍了C++中的整型变量,包括变量名规则、整型类型、无符号类型、选择合适整型的策略以及整型字面量。此外,还讨论了浮点数的表示、浮点类型以及浮点常量。文章强调了类型转换在C++中的重要性,包括初始化和赋值时的转换、表达式中的转换、传递参数时的转换,并介绍了C++11的新特性,如列表初始化和auto关键字。最后,文章提醒读者注意不同类型转换可能导致的精度损失和数值范围问题。
2549

被折叠的 条评论
为什么被折叠?



