第三章:处理数据
简单变量
整型整型 short 、int 、long 和 long无符号类型选择整型类型整型字面值C++如何确定常量的类型char 类型:字符和小整型bool类型 cosnt 限定符浮点数
书写浮点数浮点数类型浮点常量浮点数的优缺点 C++算术运算符
运算符优先级和结合性除法分支求模运算符类型转换
初始化和赋值进行转换
第三章:处理数据面向对象的本质是设计并扩展自己的数据类型。
C++内置类型:
- 基本类型。复合类型。
信息存储在计算机中需要记录三个基本属性:
- 存储的位置。存储的值。存储的类型。
变量的命名规范:
- 数字、字母、下划线组成。不以数字开头。区分大小写。不能使用关键字。
命名方案:
- 整型变量名前加 n字符串前面加 str布尔值前面加 b指针前面加 p单个字符前面加 c类成员值前面 m_
char、short、int、long和C++11新增 long long 每种类型都有符号版本和无符号版本共计10种类型。
整型 short 、int 、long 和 longC++提供灵活标准:
- short 至少16位。int 至少和 short一样长。long 至少32位,且至少和 int 一样长。long long 至少64位,且至少和 long 一样长。
short 是 short int 简称。
long 是 long int 简称。
程序清单3.1 limits.cpp
代码演示:
#include#include int main() { using std::cin; using std::cout; using std::endl; 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(short) << " bytes." << endl; cout << "long is " << sizeof(long) << " bytes." << endl; cout << "long long is " << sizeof(long long) << " bytes." << 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 << "Maximum int value = " << INT_MAX << endl; cout << "Bits per byte = " << CHAR_BIT << endl; return 0; }
运行结果:
C++编译过程中,现将源代码传递给预处理器,预处理完成替换之后被编译。
预处理器只查找独立的标记,跳过嵌入的标记。
初始化:将赋值和声明合并。
如果不对函数内部的变量进行初始化,则改变量的值是不确定的。
在声明变量时进行初始化,避免忘记赋值的情况发生。
C++11 使得可以将大括号初始化器用于任何类型,这是一种通用的初始化语法。
优点:增大变量能够存储的最大值。
使用关键字 usigned 修饰。
unsigned 本身是 unsigned int 的缩写。
程序清单3.2 exceed.cpp
代码演示:
#include#include #define ZERO 0 int main() { using std::cin; using std::cout; using std::endl; short sam = SHRT_MAX; unsigned short sue = sam; cout << "Sam has " << sam << "dollars and Sue has " << sue << "dollars deposited." << endl; cout << "Add $1 to each account." << endl << "Now "; sam = sam + 1; sue = sue + 1; cout << "Sam has " << sam << " dollars and Sue has " << sue << " dollars deposited.nPoor Sam!" << endl; sam = ZERO; sue = ZERO; cout << "Sam has " << sam << " dollars and Sue has " << sue << " 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 << " dollars deposited." << endl; cout << "Lucky Sue!" << endl; return 0; }
运行结果:
C++不保证符号整型超过限制是不出错。
选择整型类型int 被设置为对目标计算机而言的自然长度。
自然长度:计算机处理起来效率最高的长度。
如果没有非常有说服力的理由来选择其他类型,则应该使用 int。如果变量的值不可能为负,则可以使用无符号类型表示更大的值。如果知道变量所表示的整数值大于16位整数的最大值,则使用 long,及时系统上 int 为32位,也应该这样做。
(原因:移植到16位系统上程序可以正常工作。)如果要存储的值超过20亿,使用 long long。使用 short 可以节省内存,当有大型数组时,才有必要使用 shrot。如果只需要一个字节,可使用char。
整型字面值
- 十进制:第一位为 1 ~ 9 基数为 10。八进制:第一位为 0,第二位为 1~7 基数为 8。十六进制:前两位为 0x 或者 0X 基数为 16。
程序清单3.3 hexoct.cpp
代码演示:
#includeint main() { using std::cin; using std::cout; using std::endl; int chest = 42; int waist = 0x42; int inseam = 042; cout << "Monsieur cuts a stricking figure!n"; cout << "chest = " << chest << " (42 in decimal)n"; cout << "waist = " << waist << " (0x42 in decimal)n"; cout << "inseam = " << inseam << " (042 in decimal)n"; return 0; }
运行结果:
默认情况下 cout 以十进制显示整数,不管整数在程序中如何书写。
所有数都以相同的方式存储在计算机中:二进制数存储。
cout进制输出控制符:
- dec 十进制输出。hex 十六进制输出。oct 八进制输出。
默认格式为十进制,修改格式之前,格式一直有效。
程序清单3.4 hexoct2.cpp
代码演示:
#includeint main() { using namespace std; int chest = 42; int waist = 42; int inseam = 42; cout << "Monsieur cuts a stricking figure!n"; cout << "chest = " << chest << " (decimal for 42)n"; cout << hex; cout << "waist = " << waist << " (hexadecimal for 42)n"; cout << oct; cout << "inseam = " << inseam << " (octal for 42)n"; return 0; }
运行结果:
cout << hex; 等代码不会在屏幕上显示任何信息,只是修改 cout 显示整数的方式。
除非有理由存储为其他类型,否则将C++整型常量存储为 int 类型。
数字常量后面的字母用于表示类型:
- l 或 L 表示为 long 常量。u 或 U 表示 unsigned int 常量 。ul (采用任何顺序,大小写均可)表示 unsigned long 常量。ll 或 LL 表示 long long 常量。ull 、Ull、uLL 和 ULL 表示 unsigned long long 常量。
不带后缀的十进制数: 使用:int、long 或 long long 能够存储该数的最小类型。
不带后缀的十六进制数或八进制数:使用 int、unsigned int long、unsigned long 、long long 或 unsigned long long 能够能够存储该数的最小类型。
十六进制常用来表示内存地址,内存地址无符号。
char 类型:字符和小整型char 类型:
- 比 short 更小的整型。字符类型。
程序清单3.5 chartype.cpp
代码演示:
#includeint main() { using namespace std; char ch; cout << "Enter a character: " << endl; cin >> ch; cout << "Hola! "; cout << "Thank you for the " << ch << " character." << endl; return 0; }
运行结果:
cin 和 cout 的行为由变量类型引导。
C++对字符用单引号,字符串用双引号。
程序清单3.6 morechar.cpp
代码演示:
#includeint main() { using namespace std; char ch = 'M'; int i = ch; 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.push(ch): "; cout.put(ch); cout.put('!'); cout << endl << "Done" << endl; return 0; }
运行结果:
C++将字符表示为整型,方便操纵。
char 字面量:将字符使用单引号括起来,表示字符的数值编码。
转义字符:
像处理常规字符一样处理转义字符。
作为字符常量时,用单引号括起来。
放在字符串中时,不要使用单引号。
换行操作:
- cout<
可以基于字符的八进制和十六进制编码来使用转义字符。
符号适用于任何编码方式,可读性更强,应使用符号序列,不要使用数字转义序列。
程序清单3.7 bondini.cpp
代码演示:
#includeint main() { using namespace std; cout << "aOperation "HyperHype" is noew activated!n"; cout << "Enter your agent code:_________bbbbbbbb"; long code; cin >> code; cout << "aYou entered " << code << "……n"; cout << "aCode verified! Proceed with PlanZ3!n"; return 0; }
运行结果:
char 默认情况下既不是没有符号,也不是有符号。是否有符号由C++实现决定。
可以显示将类型设置为 signed char 或 unsigned char。
用 char 存储标准 ASCII 字符,char有没有符号都没关系。
C++处理无法用一个8位表示的字符集:
- 如果大型字符集实现是基本字符集,编译器厂商可以将 char 定义为一个16位的字节或更长的字节。同时支持一个小型基本字符集和一个较大的扩展字符集,8位char可以表示基本字符集,另一种类型 wchar_t 表示扩展字符集。
wchar_t :整数类型,有足够的空间,可以表示系统使用的最大扩展字符集。
C++新增的类型:
- char16_t:无符号,长16位,使用前缀 u 表示 char16_t 字符常量和字符串常量。例如:u'C' 和 u"be good"char32_t:无符号,长32位,使用前缀 U 表示 char32_t 字符常量和字符串常量。例如:U'R' 和 U"dirtyrat"
wchar_t、char16_t 和 char32_t 有底层内置数据类型——一种内置整型,底层类型随系统。
bool类型bool 变量的值可以是 true 或 false。
C++将非零解释为true,将零解释为false。
字面值 true 和 false 可以通过整型提升转换为 int 类型,true转换为 1,false转换为0。
任何数值或指针都可以被隐式转换为bool值,非零值转换为true,零转换为false。
程序中多个地方使用同一个常量,需要修改该常量时,只需要修改一个符号定义即可。
C++处理常量的方法:使用 const 关键字来修改变量的声明和初始化。
常量被初始化之后,编译器不允许再修改该变量的值。
常见做法:将常量名称首字符大写或将整个名称大写。例如:Months,MONTHS。
在声明中对于 const 进行初始化,否则该常量的值将是不确定的,且无法修改。
const 相对于 #define 的优势:
- const 能够明确类型。可以使用C++作用域规则将定义限制在特定的函数或文件中。可以将 const 用于更复杂的类型。C++中(而不是C)可以使用 cosnt 值来声明数组长度。
带小数部分的数字。
浮点数能够表示:
- 小数值。非常大的值。非常小的值。
- 标准小数表示。例如:123.456E表示法(适合表示非常大或非常小的值)。例如:3.45E6 表示 3.45 * 10^6
E表示法规则:
- 可以使用 E 或 e。指数可以是正数也可以是负数。数字中间不能有空格。
按照有效位数和允许的指数最小范围划分:
- float。有效位数至少32位。通常为32位。至少6位有效位。double。有效位数至少48位,且不少于 float。通常为64位。至少15位有效位。long double。有效位数至少和 double 一样多。通常为80、96 或 128位。三种类型指数范围至少 -37 到 37。
ostream 方法 setf():迫使输出使用定点表示法,更好地了解精度,防止程序把较大值切换为E表示法,使程序显示到小数点后六位。
程序清单3.8 floatnum.cpp
代码演示:
#includeint main() { using namespace std; 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 << ", a million tubs = " << million * tub; cout << ",nand ten million tubs =" << 10 * million * tub << endl; cout << "mint = " << mint << " and a million mints = " << million * mint << endl; return 0; }
运行结果:
默认情况下浮点数常量都是 double 类型。
如果希望为 float 类型,使用 f 或者 F后缀。
long double 类型后缀使用 l 或 L。
优点:
- 可以表示正数之间的值。可以表示的数值范围大很多。
缺点:浮点运算速度比正数运算慢,且精度将降低。
程序清单3.9 fltadd.cpp
代码演示:
#includeint main() { using namespace std; float a = 2.34E+22f; float b = a + 1.0f; cout << "a = " << a << endl; cout << "b - a = " << b - a << endl; return 0; }
运行结果:
分析:float 只能表示数字中的前 6位 或者前 7位,因此修改第23位对于数值不影响。
基本类型分类:
- 符号整型 :signed char、short、int 和 long。无符号版本称为无符号整型。C++11新增整型:long long 。整型:bool、char、wchar_t、符号整数和无符号整型。C++11新增:char16_t 和 char32_t。浮点型:float、double 和 long double。算术类型:整型 和 浮点型。
基本算术计算:
- 加法。减法。乘法。除法。求模。(求余数)
每种运算符有两个操作数。
表达式:操作数 + 运算符。
如果两个操作数是整数,则结果为商的整数部分,小数部分被丢弃。例如:17 / 3 等于 5。
求模运算:
- 例如:19 % 6 为 1。两个操作数必须都是整型,将运算符用于浮点数将导致编译错误。如果其中一个操作数为负数,则结果的符号满足如下规则: (a/b)*b + a%b = a。
变量和常量都可以用于操作数。
程序清单3.10 arith.cpp
代码演示:
#includeint main() { using namespace std; float hats, heads; cout.setf(ios::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; }
运行结果:
float只保证6位有效位。
如果需要更高的精度,请使用 double 或 long double。
优先级:
- 算数运算符遵循先乘除,后加减。可以用括号来执行自定义优先级。/ * % 由优先级相同。减和加优先级相同,但比乘除低。
结合性:
- 优先级相同时看操作数结合性。乘除都是从左向右结合。仅当两个运算符被用于同一个操作数时,优先级和结合性才有效。例如:int num = 20 * 5 + 24 * 6 没有指出应该先算那个乘法。C++让实现决定在系统中最佳顺序。
如果两个操作数都是整数,则执行整数除法,结果的小数部分将被丢弃。
如果其中有一个(或两个)操作数是浮点值,则小数部分保留,结果为浮点数。
程序清单3.11 divide.cpp
代码演示:
#includeint main() { using namespace std; cout.setf(ios::fixed,ios_base::floatfield); cout << "Integer division: 9/5 = " << 9 / 5 << endl; cout << "Floating-point division: 9.0/5.0 = " << 9.0 / 5.0 << endl; cout << "Mixed division: 9.0/5 = " << 9.0 / 5 << endl; cout << "double constants: 1e7/9.0 = " << 1e7 / 9.0 << endl; cout << "float constants: 1e7f/9.0f = " << 1e7f / 9.0f << endl; return 0; }
运行结果:
不同类型计算时,C++把它们转换为同一类型。
如果两个操作数都是 double 类型,则结果为 double 类型。
如果两个操作数都是 float类型,则结果为 float 类型。
浮点常量默认情况下是double 类型。
运算符重载简介:
- 使用相同的符号进行多种操作。根据上下文来确定运算符的含义。C++有内置运算符重载,支持扩展运算符重载,以便能够用于用户定义的类。
返回整数除法的余数。
程序清单3.12 modulus.cpp
代码演示:
#includeint 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; }
运行结果:
C++自动执行多种类型转换:
- 将一种算术类型的值赋给另一种算术类型的变量时,C++将对值进行转换。表达式中包含不同类型时,C++将对值进行转换。将参数传递给函数时,C++将对值进行转换。
C++允许将一种类型的值赋给另一种类型的变量,值将被转换为接受变量的类型。
注意:
int a = 1; long b = 2; b = a;
上面赋值完成后,a 的类型不变,生成和b类型相同的变量赋值给b。
潜在的数制转换问题:
赋值给 bool 变量:
- 将 0 赋值给 bool 变量时,将被转换为 false。非零值将会被转换为 true。
float 值对于 int 变量来说可能太大。
程序清单 3.13 assig.cpp
代码演示:
#includeint main() { using namespace std; cout.setf(ios::fixed,ios_base::floatfield); float tree = 3; int guess(3.9832); int debt = 7.2E12; cout << "tree = " << tree << endl; cout << "guess = " << guess << endl; cout << "debt = " << debt << endl; return 0; }
运行结果:
注意:将浮点型转换为整型时,C++采取截断(丢失小数部分)而不是四舍五入。



