内容简介
1、第一部分第五课:简易计算器
2、第一部分第六课预告:控制流程,随心所至
简易计算器
上一课《【C++探索之旅】第一部分第四课:内存,变量和引用》中,我们已经学习了挺重要的内存的概念,变量的知识,对引用这个C++中常用的技术也有了初步的了解。
我们在上一课开头处用一个小小计算器的存储技术引出内存的概念。其实我们的电脑兄也是一个计算器,只不过高端大气上档次了很多,不然怎么会被称为
computer呢?英语中compute这个词,正是《计算》的意思,而加上r就构成了名词。computer就是“计算机”。(复论学好英语对编程的
帮助)。
所以,电脑不仅能储存数据,还能进行很复杂的计算。
这一课我们就来聊聊计算。
请求用户输入信息
上一课中,我们学习了如何在控制台(console)中显示变量的值。现在我们来做相反的事情:请求用户为我们的程序提供输入,以存储到内存中。
从控制台读数据
也许你也注意到了(如果现在才注意到,是不是有点后知后觉?哈哈),C++用了很多英语的单词。应该说基本所有的编程语言都使用了很多英语单词,所以英语很重要。
有些编程你不需要用到太多高深的数学知识,但是英语却是天天见啊,大宝还不一定天天见呢~
比如我们的输出流cout,就是由c和out组成,是console out的意思,console表示“控制台”,out表示“向外,出去”。表示输出到控制台。是标准输出流。因此我们用cout从程序向控制台输出数据。
而与它相对应的就是cin啦,是console in的意思,in表示“向内,进来”。表示从控制台读入。因此我们用cin从控制台读入数据。
与cout配合,我们需要一个运算符 <<
与cin配合,我们需要一个运算符 >>
至于cin和cout,<<和>>究竟原理如何,等以后学了类和对象我们再说。目前只需要知道怎么使用即可。
我们来看一个例子:
#include <iostream> using namespace std; int main() { cout << "您几岁了 ?" << endl; int userAge(0); // 我们在内存中申请一个整型变量(初始值为0),以存放我们的年龄数值 cin >> userAge; // 我们请求用户输入数据,赋值给userAge变量 cout << "您已经" << userAge<< "岁了" << endl; // 显示变量值 return 0; }
运行,输出如下:
您几岁了 ?
28
您已经28岁了
原理解析
那么上面的程序中究竟发生了什么呢?
首先,程序显示"您几岁了 ?"这一段信息,至此并没有什么特别。然后,在第8行,程序向操作系统请求在内存中为其分配一块区域(好比上一课说的一个抽屉),用于存放一个int类型的变量,名称是userAge(抽屉的标签),并在抽屉里存放入一个初始值0。
接着,就有新知识点了。我们可以看到控制台里输出"您几岁了 ?"之后,换了一行(主要是endl的作用,endl是end line的缩写,表示"结束行",所以自然要换行啦),然后出现了一个闪烁的光标,等待用户输入。
用户输入数值以后(例如28),程序就把这个数值赋给userAge,代替原先的0。最后再把变量的值输出。
巧记 >>和<<
初学C++,我们容易搞混<<和>>的用法,到底哪一个是和cout(标准输出)配合,哪一个和cin(标准输入)配合呢?
不用担心,你不是一个人,很多人也经常记不清楚。
那么如何记住这两个运算符呢?
其实很简单:
我们还是用userAge这个变量来举例。
cout << userAge cin >> userAge
你看不管怎样,userAge,也就是内存中的变量,总是位于运算符右边,而cout和cin总是位于运算符左边。
那么 << 就是从内存中取出变量的值,给cout使用,使其能够将变量的值显示到控制台,因此 << 的流向是从内存到cout。
而 >> 就是将cin获取的用户输入控制台的数值赋给变量,因此 >> 的流向是从cin到内存。
当然,我们可以配合图示来记忆,你就永远不会搞错啦:
如果以后你还会搞错,不要跟别人说你是看谢什么恩铭的文章学的。开个玩笑~
其他变量
当然了,上面提到的知识点,也可用于其他变量类型,例如:
#include <iostream> #include <string> using namespace std; int main() { cout << "您叫什么?" << endl; string userName("无名氏"); // 在内存中申请一个string类型的抽屉 cin >> userName; // 将用户输入的数据赋值给userName cout << "PI的值是多少?" << endl; double piValue(-1.); // 在内存中申请一个double类型的抽屉 cin >> piValue; // 将用户输入的数据赋值给piValue cout << "您叫" << userName<< " ,您认为PI的值是" << piValue << endl; return 0; }
这次我想不需要给出什么解释了吧,自己运行此程序试试吧。
空格的问题
测试下上面的程序,是不是发现有点小问题?
假如我们如下运行:
您叫什么?
Isaac Newton
PI的值是多少?
您叫Isaac,您认为PI的值是0
很奇怪是吗?程序并没有请求我们输入PI的值,而是将PI的值改为了0。而且Newton不见了。哦,no,牛顿不见了,咋办?小苹果都不知道该往谁头上掉了(小编你可以了...)
要说原因,这是空格的问题。当用户按下回车时,程序会把用户输入在控制台的数据拷贝到内存的"抽屉"中,但是它会在第一个空格或回车符处停住。当用户输入的是数值时,并没有问题,因为数值里没有空格。
但是当输入的是字符串(string)时,可能会有空格。这样,电脑就会在第一个单词结尾处截断,毕竟电脑也是挺呆萌的。这样,在上例中,程序就会以为Newton是PI的值。
所以,我们须要截取所有一整行,而不是第一个单词。那就要用到getline函数了。
我们将 cin >> userName 用getline函数替换,如下:
#include <iostream> #include <string> using namespace std; int main() { cout << "您叫什么?" << endl; string userName("无名氏"); // 在内存中申请一个string类型的抽屉 getline(cin, userName); // 将用户输入的整一行放入userName这个抽屉 cout << "PI的值是多少?" << endl; double piValue(-1.); // 在内存中申请一个double类型的抽屉 cin >> piValue; // 将用户输入的数据赋值给piValue cout << "您叫 " << userName<< " ,您认为PI的值是 " << piValue << endl; return 0; }
我们看到cin和userName还是在那里,只不过这次它们是作为getline的参数被使用了。
这次,运行程序后,就没有问题了:
您叫什么?
Isaac Newton
PI的值是多少?
3.14
您叫Isaac Newton, 您认为PI的值是3.14
首先请求PI的值
假如我么首先使用cin >> 然后才使用getline呢?比如我们先请求用户输入PI的值,然后再请求用户输入名字。
你会发现程序又出问题了。程序并没有向用户请求输入名字,而且输出了随便什么东西。
为了解决这个问题,我们须要在cin >>之后使用cin.ignore()
如下所示:
#include <iostream> #include <string> using namespace std; int main() { cout << "PI的值是多少?" << endl; double piValue(-1.); // 在内存中申请一个double类型的抽屉 cin >> piValue; // 将用户输入的数据赋值给piValue cin.ignore(); cout << "您叫什么?" << endl; string userName("无名氏"); // 在内存中申请一个string类型的抽屉 getline(cin, userName); // 将用户输入的整一行放入userName这个抽屉 cout << "您叫 " << userName<< " ,您认为PI的值是 " << piValue << endl; return 0; }
如果我们混合使用>>和getline,记得须要在cin >> 语句之后用cin.ignore()。这是一个规则,要记住。
改变变量的值
要进行运算,我们离不开变量。
首先,我们来看看如何改变变量的值吧。我们用=(等号)来进行数值的改变。假设我有一个int型的变量,我想要改变它的值,我首先写这个int型变量的名称,后面跟一个=号,再接新的数值。这就是变量的赋值。例如:
int number(0); // 在内存中申请一个抽屉,存放一个int类型变量,叫number,初始值为0 number = 5; // 将number的值改为5
我们也可以直接把一个变量的值赋给另一个变量:
int a(4), b(5); // 定义两个变量 a = b; // 将变量b的值赋给a
上面两句程序做了什么呢?
首先,我们定义了两个int变量,分别取名为a和b,也就是在内存中申请了两个抽屉,初始值分别是4和5。
接着 a = b; 这句话将b的值赋给a,也就是用5代替了a原先的值4,如下图所示:
#include <iostream> using namespace std; int main() { int a(4), b(5); // 定义两个变量 cout << "a的值是 : " << a << ", b的值是 : " << b << endl; cout << "赋值!" << endl; a = b; // 将b的值赋给a cout << "a的值是 : " << a << ", b的值是 : " << b << endl; return 0; }
运行,输出:
a的值是 : 4, b的值是 : 5
赋值!
a的值是 : 5, b的值是 : 5
b的值并没有改变,在赋值时,只有等号左边的值(称为左值)会改变,等号右边的值(右值)不会改变。这也不是说赋值运算中的这两个变量是一样的,只是它们的值相等而已。
这是个好的开始,但是要称得上一个最基本的计算器,我们还缺点什么。是的,缺运算符。
最基础的计算器
我们从最基本的运算符开始介绍,首先是加法运算符:+
例如:
#include <iostream> using namespace std; int main() { int result(0), a(5), b(8); result = a + b; cout << "5 + 8 = " << result<< endl; return 0; }
运行,输出:
5 + 8 = 13
给出基础的运算符的表:
运算 |
符号 |
用例 |
---|---|---|
加法 |
+ |
result = a + b;
|
减法 |
- |
|
乘法 |
* |
|
除法 |
/ |
|
取模 |
% |
|
上表中前面四个运算符都好理解,但是最后一个"取模"是什么意思呢?小学数学老师好像没有教我啊。
取模就是除法运算的延伸。因为例如整数除法,我们有除不尽的时候,就会多出点"边角料",这个边角料就是模了,其实就是余数。
因此,假如 13 / 4 等于 3 余 1 (因为 3 乘以4,再加1等于13)
那么1就是13 / 4 的模。
13 % 4 就等于1
有了这么多运算符,我们就可以组合出复杂一些的运算啦,例如:
result = ((a+b) * c ) - d;
常变量
这标题有点奇怪,不是吗?
什么叫常变量?要么常量,要么变量。
好吧,常变量就是不能改变的变量。
要声明常变量,我们使用const关键字。const是constant的缩写,表示"恒定的"。用const声明的变量不可在之后的程序中被更改,不然程序运行会报错。
只
要适合用const的地方,都尽量用const。因为我们不但可以避免一些程序的错误(比如防止修改我们不想要其值改变的变量),而且const变量使得
编译器更加有效率(因为const变量,编译器之后就不会再去检查它的值有没有被改变了,不会再去重复取它的值,因为知道其值不能被改变)。
const用法如下:
string const password("wAsTZsaswQ"); // 密码 double const pi(3.14); // PI的值 unsigned int const maxLifePoint(100); // 生命值的最大取值
下一课中,我们还会再聊const这个关键字。
缩略形式
程序员是很勤劳的,但是他们又是很会偷懒的。
会偷懒和偷懒不一样,偷懒是贬义,会偷懒是褒义。会偷懒是指我们如果可以用更简便的方法来完成某事,尽量不用原先复杂冗余的形式。因为这样可以节省开销,降低程序复杂度。
我们就来看看几个运算符的缩略形式吧。
在编程中,很多时候,我们需要将变量进行减1的运算,或者加1的运算。一般我们会这样写:
int a(4); a = a + 1; // 使a增加1
但是不觉得 a = a + 1; 写起来有点重复吗?写了两次a诶,不能忍啊。
因此我们可以用自增运算符来完成同样的操作。
自增运算
自增运算符是++
也就是在变量名后跟++
例如:
int a(4); a++; cout << "a的值是 : " << a << endl;
运行,输出:
a的值是 : 5
自减运算
自减运算就是将变量的值减1啦。
int a(4); a--;
之后a的值变为3。
自增运算符和自减运算符,有不同的摆放位置,不一定放在变量名后面,也可以放在变量名前面。作用有所不同。
a++; // 先使用a的值,再对a进行加1操作 ++a; // 先对a进行加1操作,再使用a的值
例如:
int b(0), a(2); b = a++; cout << "a的值是 : " << a << " , b的值是 : " << b << endl; b = ++a; cout << "a的值是 : " << a << " , b的值是 : " << b << endl;
运行,输出:
a的值是 : 3 , b的值是 : 2
a的值是 : 4 , b的值是 : 4
为什么呢?
因为第一次的时候,我们使用 b = a++; 是先将a的值赋给b,然后再对a进行加1操作。这句结束后,a的值变为3,b的值是2
接着,我们使用b = ++a; 是先将a的值加1,再将a的值赋给b。所以a的值首先变为4,再赋值给b,因此b的值为4。
要记忆也很容易,假如是a++的形式,由于变量名在左边,所以先使用变量,再进行之后的++操作;假如是++a的形式,由于++符号在先,因此先进行自增操作,再使用变量。
其他运算符
其他运算符就是基础运算符(加,减,乘,除,取模)与等号的结合使用了:
+=, -=, *=, /= et %=
例如:
#include <iostream> using namespace std; int main() { double number(5.3); number += 4.2; // number现在等于 9.5 number *= 2.; // number现在等于 19 number -= 1.; // number现在等于 18 number /= 3.; // number现在等于 6 return 0; }
更多数学运算
也许你觉得不够过瘾,毕竟我们只是做了一些很基础的运算。
那么如果你要进行比如开平方根这样的运算,该如何做呢?
我们需要引入一个C++的标准库:数学库,是cmath
#include <cmath>
在这个头文件里,包含了很多数学计算相关的函数。如下表(没有列全):
函数名称 |
符号 |
函数 |
用例 |
---|---|---|---|
平方根 |
sqrtx |
sqrt()
|
result = sqrt(x);
|
正弦值 |
sin(x) |
sin()
|
|
余弦值 |
cos(x) |
cos()
|
|
正切值 |
tan(x) |
tan()
|
|
指数 |
ex |
exp()
|
|
次方 |
ab |
pow()
|
|
自然对数 |
lnx |
log()
|
|
以10为底的对数 |
log10x |
log10()
|
|
绝对值 |
|x| |
fabs()
|
|
向下取整 |
× |
floor()
|
|
向上取整 |
× |
ceil()
|
|
总结
- 为了请求用户输入数据,我们使用如下格式:cin >> variable,之后用户输入的数据就储存在variable变量中。
- 不要搞混了标准输入和标准输出运算符的方向:cin >> 是标准输入,cout <<是标准输出。
- 在C++中,我们可以做很多基本的运算:加,减,乘,除,等等。例如:result = a +b
- const变量是一旦定义就不能修改其值的变量(记得,不是常量)。我们用关键字const来声明。
- 为了一个变量能够进行加一运算,我们可以用自增运算符++,variable++。还有一个自减运算符--,variable--,进行减一运算。
- 如果你要进行更复杂的数学运算,例如计算平方根,那么需要引入C++的标准数学库,就是cmath。使用方法: #include <cmath> 之后你就可以用标准数学库中的各种函数了,例如计算平方根:result = sqrt(100);
第一部分第六课预告
今天的课就到这里,一起加油吧!
下一课我们学习:控制流程,随心所至