美文网首页
NOIP魔导书#1 我想要杯柠檬茶

NOIP魔导书#1 我想要杯柠檬茶

作者: kanari | 来源:发表于2018-07-27 14:53 被阅读0次
    假装柠檬茶

    目标

    阅读完这篇文章,你可能会了解到:

    1. 维X柠檬茶还不错,智乃超可爱.
    2. 让程序相应你的输入,并输出某些内容
    3. 了解不同的变量类型
    4. 如果逻辑结构
    5. zhx的冰红茶做题法
    6. NOIP题目格式

    算法基本结构

    当在做题时,基本步骤是什么:

    1. 读题.不读题做个P.
    2. 思考.不思考做个P.
    3. 回答.不回答做个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.可以回头跟别人装哔

    获取标准输入,需要

    1. 引入适当头文件,在不同的头文件里有获取不同输入的方法
    2. 从输入流中得到输入

    头文件?

    这是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的作用是输出并清空缓冲区...这东西一展开讲就完蛋了,所以现在先停一停.

    流的链式操作

    如同你看到的,在这行代码里同时出现了两个<<.对cincout的操作都可以如此同时使用多个>>``<<,想多少多少.

    代码

    然后,这个点餐程序就是

    #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>
    

    按理来说,只要你编写无误,就可以在这之后按一个数字再回车,程序会告诉你你点了什么.

    命令行格式

    在上面的命令中,每行前都带有一个$.它表示一段命令的开始,请忽略掉,不要一同输入.

    类似的还有#.二者有不同的含义,但是对我们来说没啥用.

    实际上,你可能只会了目标里的一点点.
    其他的会说的.

    相关文章

      网友评论

          本文标题:NOIP魔导书#1 我想要杯柠檬茶

          本文链接:https://www.haomeiwen.com/subject/bkxgmftx.html