目标
阅读完这篇文章,你可能会了解到:
- 维X柠檬茶还不错,智乃超可爱.
- 让程序相应你的输入,并输出某些内容
- 了解不同的变量类型
-
如果
逻辑结构 - zhx的冰红茶做题法
- NOIP题目格式
算法基本结构
当在做题时,基本步骤是什么:
- 读题.不读题做个P.
- 思考.不思考做个P.
- 回答.不回答做个P.
同样的,一个程序至少要包括后2个过程.而通常,程序会包括3个过程.如果你理解了意思,接下来,开始吧.
例1:请问今天你要来点...
抱歉,rabbit house是去不了了,不过今天集训队可以去开封菜.教练报销哦.
开封菜有很多吃的,比如牛肉汉堡,鸡肉汉堡,薯条,可乐,各种高热量食品,对身体贼好(雾).现在,你已经能写hello, world
了,搞一个点餐程序应该不难.
输入
第一行一个N
,表示有N
个人点餐.
接下来N
行,每行一个数字.其中
- 1 代表牛肉汉堡
- 2 代表鸡肉汉堡
- 3 代表薯条
输出
对于每一个人,你需要输出单独一行,共N
行,每行为其点餐的中文名.
范围
- 对于30%,0 < N < 10000
- 对于100%,0 < N < 1000000
啊哈,第一道题
"应该不难"这种说法,绝对是坑,请记住.
现在暂时简化这道题:假设集训队的同学贼懒,他们打算让教练把所有人的吃的一起带回来.
这样点餐的就只有1个人了.(笑)
如同做别的题一样,读题是必须的.而且人们会发现,OI
的题目背景都相当的有趣,它总是试图去模拟一个喜闻乐见的现实情况,让人们会心一笑.有时也会在题目里玩梗.各位可爱的出题人小哥哥小姐姐的脑洞都是很大的,如果没有他们,OI
也许也会充斥着无聊的经验技巧类题目...可没有暗指什么东西哦.
...
顺便这给抽象问题带来很大麻烦.尤其是一些出题人套背景毫无艺术感,题目会变得很恶心.
思路
太简单了,你懂得.
魔法导入:输入?
为了解决这个例题,获取客户的点餐是必要的.
输入设备有很多,例如键盘,鼠标,扫描仪,摄像头,以及通过这些输入设备输入的预先保存的数据.针对这些输入,有不同的获取方式.
比赛中(注意不单单NOIP比赛),常见的输入方式是标准输入
和文件输入
.如何获取鼠标,摄像头,扫描仪一类的输入,请搜索.或者,等我几万年更新一次添加上.
标准输入
这个概念存在于shell.shell会打开3个标准文件
,分别为标准输入,标准输出,标准错误输出
不同于windows.在windows下,文件可能是指图片,文档,表格,网页,游戏存档...但是屏幕就是屏幕,cpu就是cpu,鼠标就是鼠标.而在linux下,
文件
这个概念并不是只指文件,它可能是电脑的某些硬件!linux将操纵和读取硬件属性抽象成对一类特殊的文件
的操作.对的,如果你想操纵硬件,只需要读写文件!比起windows是不是很有趣?实际上,linux原本是希望将所有的硬件都表示成文件,可惜在实际使用上,全面贯彻这种做法不明智,往往在某些情况下,仍然将硬件特殊处理更方便.因此,linux有所取舍.
的确有系统把所有东西都当作文件,可以了解一下
plan 9
.可以回头跟别人装哔
获取标准输入,需要
- 引入适当头文件,在不同的头文件里有获取不同输入的方法
- 从输入流中得到输入
头文件?
这是c++组织代码的一种方法.想像一下,总不能把10w行代码写在一个文件里.当把它们拆开保存到不同文件里而且还要再进行管理时,头文件就诞生了.头文件的作用即是通过
预编译指令
(下方)将散落在不同文件内的代码链接起来.在C++中存在如此的几种文件.了解就行,竞赛中用不上.
- .cpp/.cxx 这类文件中保存代码的实现.
- .h 这类文件中保存声明,同时链接实现.c++中的声明和实现可以分离,声明即表示"我们有这个功能",实现顾名思义.如此安排自有其道理.
- .hpp 实现与声明在同一文件内的新格式.目的是为了减少引用的文件数目.
现在你不用过多的担忧什么功能在什么里,在接下来你总会渐渐记住,也会有一个专门的表格记载重要的头文件.
像刚刚说的,注意!
- ==标准输入输出(standard I/O)在头文件
iostream
内.==
在代码开头写如下代码引入
#include <iostream>
using namespace std;
#include <>
是引入某个头文件的命令,这行代码引入了iostream
(input/output stream).
我听说还有
#include ""
对的.它们的不同体现在查找这个文件位置的顺序.使用
<>
会优先寻找标准库
,而""
会优先搜索你编写的代码.至于有毛线用,你可以自己想象,或者未来能用上的话,会说.标准库
这个概念将会在今后渐渐说起.
我听说
#
开头的代码有特殊作用不错,听说的很多,能不能把你听说的途径告诉我.以
#
开头的代码叫做预编译指令
,它将告诉编译器该如何处理你编写的代码.还有很多预编译指令将会在后面被介绍.
那行using是啥?
你先这么用着.在竞赛范围内,你不需要这个知识.但你问的好.
1班和2班里都有一个小孩子叫小明,如何区分他们?人们于是称他们
1班小明
和2班小明
.在程序里,往往也有这种问题.如果有多个人同时给自己的程序起名叫小明
,就会导致问题.为了避免这种麻烦,cpp有名字空间
的概念.张三和李四写的程序分别放进各自的空间
,不就如同分班一样解决了冲突吗?而
using namespace xxx
就是声明:在你写的程序里,允许xxx
内的东西全部搀和进来.
弹丸里有七海,樱花庄里也有七海,到底哪个是哪个呢?不管了,反正都很可爱.
引用之后,我们获得了特多的方法和结构.其中,有一个叫做cin
.意义可能为c系的输入(in),用于获取标准输入
.
使用如下代码获取客户点的餐.
int order;
cin >> order;
第一行代码创建(声明)一个可以保存整数的变量(int),它的名字叫order
.
==在C++中,声明一个变量的语法如<type> <name>
.必须记住.==
通用替换法
在魔导书里,通常使用
<描述>
来标记一个必须填写的空格.使用[描述]
来表示一个可以忽略不写的空格.这个标准事先存在,并不是魔导书瞎创的.
这玩意和数学的变量有啥关系?
emmm它和数学的变量还稍稍有区别.最好别把它们混在一起.
第二行使用>>
操作符从cin
中取出一个输入并存入order
.
其实它还挺象形的不是吗.
==cin
就是iostream
中提供的读取标准输入的结构==,它就是这个名字,永远是,不管在哪都是.记住.
魔法导入:赋值
你可能在数学里见过这个神奇的字眼.但最好别把他们混在一起.
在c++中,赋值意味着,将一个值赋给一个变量,使用=
运算符.
对,=
并不表示相等,而是赋值,搞清楚.==
才表示判断相等.
观察下面的代码.
order = 1;
order = 2;
order = 3;
order = (1==2);
代码依次使得order中存储1,2,3,(下方揭晓).
魔法预导入:运算
先扔掉这个题.嘿,既然我们读入了一个整数,可不可以对它加加减减?
你先造个计算器算算帐也不是不可以.
运算由运算符提供.c++支持加减乘除基本运算(抱歉,不支持乘方),以及一些在计算机上特有的运算.你可能能猜到了怎么表示,但现在我们不讨论.
魔法导入:逻辑结构-if
现在我们有客户的点餐代号了,该怎么判断它是哪个套餐?
判断相等
显然要把代号和已知的套餐编码对比,找出相同的.
如何对比?
使用<1> == <2>
.它会对比<1>
和<2>
.
注意,不能像数学那样写<1> == <2> == <3>
,这在C++中是不允许的.如何转化将在运算
一篇介绍.
上不同的餐
正式介绍if
.搭配==
,if能够在相等或者不等时执行不同的代码,将它用来处理点餐正好.
if (判断) //成立那么就执行这一条代码
if (判断) {
//成立那么就执行
}
if (判断) {
//成立那么就执行
} else {
//不成立那么就执行
}
if (判断) {
//成立那么就执行
} else if (另一个判断) {
//上一个if不成立但这个成立那么就执行
} else {
//2个都不成立就执行
}
可见if的结构可以说比较复杂了,它的结构差不多就上面那些.
if
为一个固定的关键字,此后紧跟一个小括号,小括号内填写一段判断(比如用==
连接的判断).而后跟随一段代码,if
将会在判断成立时才运行这段代码.
大括号{}
表示一块代码段,实际上可以在"任何"地方使用{}
圈出一块区域写代码.跟随在if
身后的{}
代码段被if
所影响.
避免使用第一种格式
使用第一种格式容易造成理解上的困难(不是说它难看...你会明白的),在使用时要三思.
注释
为了更好的理解代码,在代码中,你可以使用注释来解释某些代码的意思(是给人看的).它们不会对程序产生任何影响.
- 使用
//
来开始一段注释.可以在新的一行或者每行的结尾.- 使用
/* [注释] */
来圈起一大段可以跨行的注释
作用域
如果你想了解更多的话,
{}
实际上并不是圈出一段区域写代码这么简单.在c++中,{}
同时圈出了一个作用域.作用域内的声明会覆盖掉作用域外的声明.意思就是,一旦在新的作用域内创建了一个已经存在的变量或者函数,那么在这个作用域内就只能使用新创建的了.同时,在代码执行出作用域后,作用域内创建的东西都会被销毁.(严格来说,是创建在栈上的东西将被销毁,但暂时不需要管这么多)可我就是想管
行行行,管管管.在程序运行时,内存被划分为2个不同的区域.一个是栈,一个是堆.栈是有限的且快,堆是无限的且慢.按照上面解释的变量创建方法
<type> <name>;
创建的基本类型变量都存储在栈上,并会在作用域结束后自动销毁.与自动相对应的自然就是不自动,在堆上创建的东西必须手动销毁才能释放掉内存.
将它写成餐点判断
if (order == 1) {
//点餐是牛肉汉堡
} else if (order == 2) {
//点餐是鸡肉汉堡
} else if (order == 3) {
//点餐是薯条
} else {
//点错了,没这玩意
}
魔法导入:输出
继续我们的iostream
,有了输入了,自然也有输出.
给你个机会,根据cin
的命名特点猜猜输出是什么名字.别看了!先别看下面的内容!猜完再看.
emmm,知道答案或者确定就是猜不出来的话,使用鼠标划选下面的黑框框
(mmp居然不能写html代码,那算了)
<html>
<a style="font-color:black;background-color:black;">cout</a>
</html>
和你猜的一样吗?是的,就是这种命名风格.
与cin
相反的,向输出流输出内容,使用<<
.
为了不影响体验,把这玩意放得向下点.
.
.
.
.
.
.
.
.
.
cout << "牛肉汉堡" <<endl;
暂时将endl
理解为换行(回车)即可.
如果非想知道,cout
内部存在缓冲区
,endl
的作用是输出并清空缓冲区...这东西一展开讲就完蛋了,所以现在先停一停.
流的链式操作
如同你看到的,在这行代码里同时出现了两个
<<
.对cin
和cout
的操作都可以如此同时使用多个>>``<<
,想多少多少.
代码
然后,这个点餐程序就是
#include <iostream>
using namespace std;
//正文开始
int main() {
int order;
cin >> order;
if (order == 1) {
cout << "牛肉汉堡" <<endl;
} else if (order == 2) {
//点餐是鸡肉汉堡
cout << "鸡肉汉堡" <<endl;
} else if (order == 3) {
cout << "薯条" <<endl; //点餐是薯条
} else {
//点错了,没这玩意
cout << "你点的啥玩意,没有,再见" <<endl;
}
return 0;
}
魔法导入:emmmmm多出来一些东西-c++代码结构
你注意到上面的代码多出来一些东西.在此统一解释.
c++的程序大概分为2段,预编译指令和正文.
在正文部分,出现了莫名其妙的
int main() {
代码需要有一个启动的位置.到底该从什么地方开始执行代码?这个函数
给出了开始的位置,关于它更多的内容在之后讲解.
一睹为快
函数就是一个大箱子,把一段常用的代码(比如算乘方)封起来,方便重复使用.
main()
不止提供启动的位置,同时会传递启动的命令行参数.
运行
至此,代码就写完了.可以运行了.
打开一个shell,输入
$ g++ <filename>.cpp -o <filename>
$ ./<filename>
按理来说,只要你编写无误,就可以在这之后按一个数字再回车,程序会告诉你你点了什么.
命令行格式
在上面的命令中,每行前都带有一个
$
.它表示一段命令的开始,请忽略掉,不要一同输入.类似的还有
#
.二者有不同的含义,但是对我们来说没啥用.
结
实际上,你可能只会了目标里的一点点.
其他的会说的.
网友评论