一、简单变量
把信息存储在计算机中,程序必须记录3个基本属性:
- 信息将存储在哪里;
- 要存储什么值;
- 存储何种类型的信息。
1.变量名
C++变量名必须遵循以下几种命名规则 :
- 在名称中只能使用字母字符、数字和下划线(_)。
- 名称的第一个字符不能是数字。
- 区分大写字符与小写字符。
- 不能将C++关键字用作名称。
- 以两个下划线和大写字母打头的名称被保留给实现(编译器及其使用的资源)使用。以一个下划线开头的名称被保留给实现,用作全局标识符。
- C++对于名称的长度没有限制,名称中所有的字符都有意义,但有些平台有长度限制。
注:用下划线开头的命名变量的名称不会导致编译错误,但会导致行为的不确定性。
2.整型
C++的基本整型(按宽度递增的顺序排列):char、short、int、long、long long,其中每种类型都有符号版本和无符号版本。
- char一般8位
- short至少16位;
- int至少与short一样长;
- long至少32位,且至少与int一样长;
- long long 至少64位,且至少与long一样长。
位与字节:
计算机内存的基本单元是位(bit)。即0和1,就像电子开关,关表示0,开表示1。二进制。
字节(byte)通常指的是8位的内存单元。字节就是描述计算机内存量的度量单位,1KB等于1024字节,1MB等于1024KB。C++的字节的定义与此不同,C++字节由至少能够容纳实现的基本字符集的相邻位组成,也就是说,可能取值的数目必须等于或超过字符数目。也就是说C++的字节可能大于8位字节,具体由实现决定。
#include <iostream> #include <climits>//头文件climits定义了符号常量,包含了语句#define INT_MAX 32767 //在程序中查找INT_MAX,并将所有的INT_MAX都替换为32767 //只查找单独的单词,跳过嵌入的单词,例子:预处理器不会将PINT_MAXIM替换成32767 using namespace std; int main() { 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<<"Maximun values: "<<endl; cout<<"int: "<<n_int<<endl; cout<<"short: "<<n_short<<endl; cout<<"long: "<<n_long<<endl; cout<<"long long: "<<n_llong<<endl; return 0; }
输出结果
int is 4 bytes. short is 2 bytes. long is 8 bytes. long long is 8 bytes. Maximun values: int: 2147483647 short: 32767 long: 9223372036854775807 long long: 9223372036854775807
1.sizeof运算符和头文件limits
sizeof运算符返回类型或变量的长度。
头文件climits定义了符号常量来表示类型的限制。
(2)初始化
初始化将赋值与声明合并在一起。也可以使用字面常量来初始化。可以将变量初始化为另一位变量,条件是后者已经定义过了。甚至可以用表达式来初始化变量,条件是当程序执行到该声明时,表达式中的值都是已知的。
注:最好在声明变量的时候就初始化变量。
C++还有另一种C语言没有的初始化语法:
int wrens(3);//int wrens=3
(3)C++初始化方式
4.无符号类型
无符号类型的优点是可以增大变量能够存储的最大值。例:short表示的范围是-32768~+32767,则无符号版本的表示范围为0~65535。仅当数值不会为负时才应使用无符号类型。要创建无符号版本的基本整型,只需使用关键字unsigned来声明即可:
注:unsigned 是unsigned int的缩写
#include <iostream> #include <climits>//头文件climits定义了符号常量,包含了语句#define INT_MAX 32767 //在程序中查找INT_MAX,并将所有的INT_MAX都替换为32767 //只查找单独的单词,跳过嵌入的单词,例子:预处理器不会将PINT_MAXIM替换成32767 #define ZERO 0; using namespace std; int main() { short sam=SHRT_MAX; unsigned short sue =sam; cout<<"Sam has "<<sam<<" dollars and Sue has "<<sue<<" dolloars deposited."<<endl <<"Add $1 to 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<<" 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 deposted."<<endl<<"Lucky Sue!"<<endl; return 0; }
输出结果:
Sam has 32767 dollars and Sue has 32767 dolloars deposited. Add $1 to each account. Now Sam has -32768 dollars and Sue has 32768 dollars deposited. Poor Sam! Sam has 0 dollars and Sue has 0 dollars deposited. Take $1 from each account. Now Sam has-1 dollars and Sue has 65535 dollars deposted. Lucky Sue!
当取的数大于(小于)定义的范围时,会循环回去从最小(最大)的数开始取。防止上溢和下溢。
5.选择数据类型
根据实际情况选择。节省一点就是赢得一点。
6.整型字面值
整型字面值(常量)是显式书写的常量,如212或1776。与C相同,C++能够以三种不同的计数方式来书写整型:基数为10、基数为8、基数为16(十进制、八进制、十六进制)。
include <iostream> using namespace std; int main() { int chest = 42; int waist = 0x42; int inseam = 042; cout<<"Monsieur cuts a striking figure!\n"; cout<<"chest = "<<chest<<" (42 in decimal)"<<endl; cout<<"waist = "<<waist<<" (0x42 in hex)"<<endl; cout<<"inseam = "<<inseam<<" (042 in octal)"<<endl; return 0; }
输出结果:
Monsieur cuts a striking figure! chest = 42 (42 in decimal) waist = 66 (0x42 in hex) inseam = 34 (042 in octal)
注:不管值书写为十进制、八进制还是十六进制,最后都将以相同的方式存储在计算机中——被存储为二进制数。
十进制以八进制和十六进制输出代码:
#include <iostream> using namespace std; int main() { int chest = 42; int waist = 42; int inseam = 42; cout<<"Monsieur cuts a striking figure!\n"; cout<<"chest = "<<chest<<" (decimal for 42)"<<endl; cout<<hex;//manipulator for changing number base cout<<"waist = "<<waist<<" (hexadecimal for 42)"<<endl; cout<<oct;//manipulator for changing number base cout<<"inseam = "<<inseam<<" (octal for 42)"<<endl; return 0; }
输出结果:
Monsieur cuts a striking figure! chest = 42 (decimal for 42) waist = 2a (hexadecimal for 42) inseam = 52 (octal for 42)
7.C++如何确定常量的类型
程序的声明将特定的整型变量的类型告诉了C++编译器,一般C++将整型常量默认存储为int类型。(除非使用其他特殊的后缀来表示特定的类型,或者值太大,不能存储为int。)
后缀是放在数字常量后面的字母,用于表示类型。(大小写都可以)
8.char类型:字符和小整数
char类型是专门为存储字符(如字母和数字)而设计的。char类型是另一种整型。它足够长,能够表示目标计算机系统中的所有基本符号——所有的字母、数字、标点符号等。虽然char最常用被用来处理字符,但也可以将它用做比short更小的整型。
#include <iostream> using namespace std; int main() { char ch; cout<<"Enter a character: "<<endl; cin>>ch; cout<<"Hola!"; cout<<"Thank you for the "<<ch<<" character."<<endl; return 0; }
输出结果
Enter a character: M Hola!Thank you for the M character.
C++对字符用单引号,对字符串使用双引号。
cout.put()函数,该函数显示一个字符
#include <iostream> using namespace std; int main() { 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<<"Display char ch using cout.put(ch): "; cout.put(ch); cout.put('!'); cout<<endl<<"Done"<<endl; return 0; }
输出结果:
The ASCII code for M is 77 Add one to the character code: The ASCII code for N is 78 Display char ch using cout.put(ch): N! Done
cout.put()的意思是,通过类对象cout来使用函数put()。
char字面值:在C++中,书写字符常量的方式有多种。对于常规字符(如字母、标点符号和数字),最简单的方法是将字符用单引号括起。这种表示法代表的是字符的数值编码。这种表示法优于数值编码,它更加清晰,且不需要知道编码方式。
有些字符不能直接通过键盘输入到程序中。对于这些字符,C++提供了一种特殊的表示方法——转义序列。
注:应该像处理常规字符那样处理转义序列。也就是说,将它们作为字符常量时应用单引号括起来,将它们放在字符串中时,不要使用单引号。
通用字符集:C++实现支持一个基本的源字符集,即可用来编写源代码的字符集。它由标准美国键盘上的字符(大写和小写)和数字、C语言中使用的符号组成。
signed char 和unsigned char :与int不同的是,char在默认情况下即不是没有符号,也不是有符号。是否有符号由C++实现决定。如果将char用作数值类型,则unsigned char 和signed char之间的差异将非常重要。unsigned char类型的表示范围通常为0~255,而signed char的表示范围为-128~127。另一方面,如果使用char变量来存储标准ASCII字符,则char有没有符号都没关系,在这种情况下,可以使用char。
wchar_t:(宽字符类型)可以表示扩展字符集。wchar_t类型是一种整数类型,它有足够的空间,可以表示系统使用的最大扩展字符集。wchar_t类型的输入和输出用wcin和wcout。
C++11新增的类型:char16_t和char32_t:当wchar_t类型不满足要求时,便出现了char16_t和char32_t类型,前者是无符号的,长16位,后者也是无符号的,但长32位。
9.bool类型
布尔变量的值可以是true或false,转换为int类型1是true,0是false。
二.const限定符
关键字const叫限定符,因为它限定了声明的含义。在C++中可以用const值来声明数组的长度。
注:在C++中不要使用#define来定义符号常量,而使用const。
三.浮点数
浮点数是C++的第二组基本类型。浮点数提供的值范围更大。对于带小数的数字,计算机将这样的值分为两部分存储,一部分表示值,另一部分用于对值进行放大或缩小。如34.5634和3456.34两个数字除了小数点的位置不同外,其他都是相同的,可以把第一个数表示为0.345634(基准值)和100(缩放因子),第二个数表示为0.345634(基准值相同)和10000(缩放因子更大)。缩放因子的作用是移动小数点的位置,术语浮点因此而得名。C++中表示浮点数的方式与之相同,只不过C++中基于的是二进制,因此缩放因子是2的幂,不是10的幂,浮点数能够表示小数值、非常大和非常小的值,它们的内部表示方法与整数有天壤之别。
1.书写浮点数
第一种是常用的标准小数点表示法:
12.3 90789.34 0.00078 8.0
即使小数部分为0(如8.0),小数点也将确保该数字一浮点格式(而不是整数格式)表示。
第二种表示浮点值的方法叫作E表示法:如3.45E6,这指的是3.45与1000000相乘。E6指的是10的6次方。E表示法最适合于非常大和小的数,E可以是e,指数以可以为负,如8.33E-4=0.000833。
2.浮点类型
C++有3种浮点类型:float、double和long double。在C++中float至少有32位。double至少48位,且不少于float,long double至少和double一样多。这三种类型的有效位数可以一样多。
3.浮点常量
在默认情况下,像8.24和2.4E8这样的浮点常量都属于double类型。如果希望常量为float类型,请使用f或F后缀。对于long double类型,可使用l或L后缀(由于l看其他像数字1,因此最好用L)
4.浮点数的优缺点
优点:1.可以表示整数之间的值。2.由于有缩放因子,它们可以表示的范围大很多。
缺点:浮点运算的速度通常比整数运算慢,且精度将降低。
四.C++算术运算符
C++提供了几种运算符来完成5种基本的算术计算:加法、减法、乘法、除法以及求模。每种运算符都使用两个值(操作数)来计算结果。运算符及其操作数构成了表达式。
#include <iostream> using namespace std; int main() { float hats,heads; cout.setf(ios_base::fixed,ios_base::floatfield);//其中ios_base::fixed表示:用正常的记数方法显示浮点数 // ios_base::floatfield表示小数点后保留6位小数。 cout<<"Enter a number: "; cin>>hats; cout<<"Enter another number: "; cin>>heads; cout<<"hats = "<<hats<<";head = "<<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; }
输出结果:
Enter a number: 50.25 Enter another number: 11.17 hats = 50.250000;head = 11.170000 hats + heads = 61.419998 hats - heads = 39.080002 hats * heads = 561.292480 hats / heads = 4.498657
代码解读:11.17+50.25应该等于61.42,但是输出结果是61.419998。这不是运算问题;而是由于float类型表示有效位的能力有限。在C++中float只保证有6位有效位。如果将61,419998四舍五入成6位,将得到61.4200,这是保证精度下的正确值。如果需要更高精度,请使用double或long double类型。
1.运算符优先级和结合性
当两个运算符的优先级相同时,C++将看操作数的结合性(associativity)是从左到右,还是从右到左。从左到右的结合性意味着如果两个优先级相同的运算符被同时用于同一个操作数,则首先应用左侧运算符。从右到左的结合性则首先应用右侧的运算符。
注:仅当两个运算符被用于同一个操作数时,优先级和结合性规则才有效。
int dues = 20*5+24*6
运算符优先级表明了两点:程序必须在做加法之前计算20*5,必须在做加法之前计算24*6。但优先级和结合性都没有指出应先计算哪个乘法。一般人们可能认为先做左侧的乘法,但是在这种情况下,两个*运算符都没有用于同一个操作数,所以该规则不适用。事实上,C++把这个问题留给了实现,让它来决定在系统中的最佳顺序。对于这个例子来说,两种顺序的结果是一样的,但是也有两种顺序结果不同的情况。
2.除法分支
除法运算符(/)的行为取决于操作数的类型。如果两个操作数都是整数,则C++将执行整数除法。这意味着小数部分将被丢弃,使得最后的结果是一个整数。如果其中有一个(或两个)操作数是浮点值,则小数部分将保留,结果为浮点数。
#include <iostream> using namespace std; int main() { cout.setf(ios_base::fixed,ios_base::floatfield);//其中ios_base::fixed表示:用正常的记数方法显示浮点数 // ios_base::floatfield表示小数点后保留6位小数。 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; }
输出结果:
Integer division: 9/5 = 1 Floating-point division:9.0/5.0 = 1.800000 Mixed division: 9.0/5 = 1.800000 double constants: 1e7/9.0 = 1111111.111111 float constants: 1e7f/9.0f = 1111111.125000
代码分析:从第一行输出可知,整数9除以整数5的结果为整数1,4/5的小数部分(或0.8)被丢弃。在C++中对于不同的类型进行运算时,C++将把它们全部转换为同一种类型。如果两个操作数都是double类型,则结果为double类型;如果两个操作数都是float类型,则结果为float类型,记住,浮点常量在默认情况下为double类型。当一个为floet类型一个为double类型,最后结果为double类型。
3.求模运算符
求模运算符返回整数除法的余数。求模运算符适用于解决要求将一个量分成不同的整数单元的问题,例如将英寸转换为“英尺+英寸”的形式,或者将美元转换为元、角、分、厘。
4.类型转换
C++自动执行很多类型的转换:
- 将一种算术类型的值赋给另一种算术类型的变量时,C++将对值进行转换;
- 表达式中包含不同的类型时,C++将对值进行转换;
- 将参数传递给函数时,C++将对值进行转换。
4.1初始化和赋值进行的转换
C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换为接收变量的类型。
4.2以{}方式初始化时进行的转换(C++11)
C++11将使用大括号的初始化称为列表初始化(list-initalization),因为这种初始化常用于给复杂的数据类型提供值列表。它对类型转换的要求更严格,即变量的类型可能无法表示赋给它的值。例如,不允许将浮点类型转换为整型。在不同的整型之间转换或将整型转换为浮点型可能被允许,条件是编译器知道目标变量能够正确的存储给它的值。
4.3表达式中的转换
当同一个表达式中包含两种不同的算术类型时,C++将执行两种自动转换:首先,一些类型在出现时便会自动转换;其次,有些类型在与其他类型同时出现在表达式中时将被转换。
自动转换:在计算表达式时,C++将bool、char、unsigned char、signed char、和short值类型转换为int。例:true被转换为1,false被转换为0。这些转换被称为整型提升(integral promotion)。
其他整型提升:如果short比int短,则unsigned short类型将被转换为int;如果两种类型的长度相同,则unsigned short类型将被转换为unsigned int类型。这种规则确保了在对unsigned short进行提升时不会损失数据。当运算涉及两种类型时,较小的类型将被转换为较大类型。
4.4传递参数时的转换
传递参数时的类型通常由C++函数原型控制。然而也可以取消原型对参数传递的控制,尽管这样做并不明智。在这种情况下C++将对char和short类型(unsigned和signed)应用整型提升。另外,为保持与传统C语言中大量代码的兼容性,在将参数传递给取消原型对参数传递控制的函数时,C++将float参数提升为double。
4.5强制类型转换
C++还允许通过强制类型转换机制显式地进行类型转换。强制类型转换不会修改变量本身,而是创建一个新的、指定类型的值,可以在表达式中使用这个值。C++中static_cast<>可用于将值从一种数值类型转换为另一种数值类型。运算符static_cast<>比传统强制类型转换更严格。
#include <iostream> using namespace std; int main() { int auks,bats,coots; auks=19.99+11.99; bats=(int)19.99+(int)11.99; coots=int(19.99)+int(11.99);//C++新语法 cout<<"auks = "<<auks<<", "; cout<<"bats = "<<bats<<", "; cout<<"coots = "<<coots<<endl; char ch='Z'; cout<<"The code for "<<ch<<" is "<<int(ch)<<endl; cout<<"Yes,the code is "<<static_cast<int>(ch)<<endl; return 0; }
输出结果:
auks = 31, bats = 30, coots = 30 The code for Z is 90 Yes,the code is 90
程序分析:将19.99和11.99相加。结果为31.98。将这个值赋给int变量auks时,它被截短为31。但在进行加法运算之前使用强制类型转换时,这两个值将被截短为19和11,因此bats和coots的值都为30。
4.5C++11中的auto声明
C++11新增了一个工具,让编译器能够根据初始值类型的类型推断变量的类型。auto是一个C语言关键字。在初始化声明中,如果使用关键字auto,而不指定变量的类型,编译器将把变量的类型设置成与初始值相同。
五.课后编程题
1.
#include <iostream>
using namespace std;
const int FOOT_TO_INCH=12;
int main() {
int height;
cout<<"Please enter your height int inches_";
cin>>height;
cout<<"Your height convert to "<<height/FOOT_TO_INCH;
cout<<" foot and "<<height%FOOT_TO_INCH<<" inches height.";
return 0;
}
2.
#include <iostream>
using namespace std;
const int FOOT_TO_INCH = 12;
const double INCH_TO_METER = 0.0254;
const double KILLOGRAM_TO_POUND = 2.2;
int main() {
int height_foot,height_inch;
double weight_pound,height,weighht,BMI;
cout<<"Please enter your height foot: ";
cin>>height_foot;
cout<<"Please enter your height inches: ";
cin>>height_inch;
cout<<"Please enter your weight in pounds: ";
cin>>weight_pound;
height = (height_foot*FOOT_TO_INCH+height_inch)*INCH_TO_METER;
weighht = weight_pound/KILLOGRAM_TO_POUND;
BMI=weighht/(height*height);
cout<<" Your BMI is "<<BMI<<endl;
return 0;
}
3.
#include <iostream>
const int DEGREE_TO_MINUTE = 60;
const int DEGREE_TO_SECOUND =3600;
using namespace std;
int main() {
int degree,minute,second;
double degree_style;
cout<<"Enter a latitude in degrees, minutes, and seconds: "<<endl;
cout<<"First,enter the degrees : ";
cin>>degree;
cout<<endl;
cout<<"Next,enter the minutes of arc: ";
cin>>minute;
cout<<endl;
cout<<"Finally,enter the second of arc: ";
cin>>second;
cout<<endl;
degree_style=degree+(double)minute/DEGREE_TO_MINUTE+(double)second/DEGREE_TO_SECOUND;
cout<<degree<<" degrees, "<<minute<<" minute, "<<second<<" second, "<<" = "<<degree_style<<" degrees";
return 0;
}
4.
#include <iostream>
using namespace std;
const int DAY_HOUR =24;
const int HOUR_TO_MINUTE = 60;
const int MINUTE_TO_SECOND = 60;
int main() {
long long seconds;
int days,hours,minutes;
cout<<"Enter the number of second: ";
cin>>seconds;
cout<<seconds;
days=seconds/(DAY_HOUR*HOUR_TO_MINUTE*MINUTE_TO_SECOND);
seconds=seconds%(DAY_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";
return 0;
}
5.
#include <iostream>
using namespace std;
int main() {
long long global_amount,american_amount;
double population_percent;
cout<<"Enter the world's population: ";
cin>>global_amount;
cout<<"Enter the population of the US: ";
cin>>american_amount;
population_percent=100*(double)american_amount/(double)global_amount;
cout<<"The population of the US is "<<population_percent<<"% of the world population";
return 0;
}
6.
#include <iostream>
using namespace std;
int main() {
double distance_in_miles,fule_in_gallon;
double fule_consume;
double distance_in_kilometer,fule_in_litre;
cout<<"Enter the distance in miles: ";
cin>>distance_in_miles;
cout<<"Enter the fuel consume in gallon: ";
cin>>fule_in_gallon;
fule_consume=distance_in_miles/fule_in_gallon;
cout<<"The fuel consume is "<<fule_consume<<" miles/galon."<<endl;
cout<<"Enter the ditance in kilometer: ";
cin>>distance_in_kilometer;
cout<<"Enter the fuel consume in litre: ";
cin>>fule_in_litre;
fule_consume = (fule_in_litre/distance_in_kilometer)*100;
cout<<"The fuel consume is "<<fule_consume<<" L/100km.";
return 0;
}
7.
#include <iostream>
using namespace std;
const double GALLON_TO_LITRE = 3.785;
const double HKM_TO_MILE = 62.14;
int main() {
double fuel_consume_eur;
double fuel_consume_us;
cout<<"Enter the fuel consume in europe(L/100km): ";
cin>>fuel_consume_eur;
fuel_consume_us=(GALLON_TO_LITRE*HKM_TO_MILE)/fuel_consume_eur;
cout<<"The fuel consume is "<<fuel_consume_us<<" mile/gallon."<<endl;
return 0;
}