第九讲 if()

       周末很愉快的就过去了,不知道上一讲留给大家思考的问题有没有实现出来,好吧,不管如何,我们今天就从乘法口诀表开始吧:
实现乘法的算法很简单,我们大家都知道怎么实现,所以这个问题所以的考察的要点有两点,一是for循环的运用,二是换行符的使用,如果大家还有疑问,我们不妨先看下程序再来看看是不是还有疑问。
——————————
#include <stdio.h>
#include <stdlib.h>
int main()
{
     
int i,j;


     for(i=1;

i<=9;

i++)
     {
             for(j=1;

j<=i;

j++)
                   printf(“%d*%d=%dt”,j,i,j*i);


             printf(“n”);


     
}   

      system(“PAUSE”);


}
———————————–
程序的设计很简单,不过这其中包含了一个要给大家说的知识点,那就是嵌套循环,这里的嵌套循环就是一个for循环里面又套了一个for循环,嵌套循环的要旨没什么难理解的,就是从外入内又从内入外,为什么什么这么说呢?因为每一个循环都得从最外的循环开始进入,然后执行内部循环,把内部循环执行完成之后,又重新回到外部循环进行下一项,再进入内部循环,所以这样无休无止的循环直到把最外层循环执行完成之后才会退出循环。
嵌套循环的时间复杂度给n的m次方,每个循环所执行的次数,嵌套的循环数,就好比我们现在这个例子,他的时间复杂度就是9的2次方,当然这是数据结构该研究的范畴,或许我们会说一些数据结构的知识,不过不是现在,我们还是回到正题上来。
上面的例子中,当函数执行到第一个for处,i=1,然后进入第二个循环,因为第二个循环用了第一个循环传递进来的i做参数,所以第二个循环j执行到1时便结束了第二个循环,这里就是1*1 = 1,这个时候我们要做的是要换行,但是换行不能用用在第二个循环里面,而要在第一个循环里面来执行,当然有疑惑的同学可以试着把第二循环写成下面这样来运行一下看看结果:
—————————
for(j=1;

j<=i;

j++)
     printf(“%d*%d=%dtn”,j,i,j*i);


—————————–
然后把下面的printf(“n”)给注释起来,说到注释,又得说一下,如果大家不想要某一行代码参与运行,可以在这行代码前添加两条斜杠”\”,当然大家也可以在某行代码的后面添加注释,标明改行代码是干嘛的,这些注释前代码的分号后面记得要加上双斜杠。如果想要把某段代码全部注释起来呢?当然也可以每一行前面添加双斜杠,但还有一个更简单的方法,那就是用单斜杠搭配*号来围起来,怎么围呢?就是正反来一个就好了,像这样即可:
——————————–
/*———————–
   需要注释起来的代码段
————————*/
——————————–
还是回到上面的问题,如果我们把打印换行的那一句给注释起来,大家是不是发觉打印出来的东西特么的别扭,所以,这个例子不光考察了大家对循环的理解,还同时考察了大家对换行符的使用,好吧,说到这里,想必大家都应该清楚了,我们现在来看下输出:
第九讲 if()
 

大家是不是看到每一列都很完整的对齐?这就是有人疑惑的那个t的功劳了,t上一讲我们说了,这是一个水平制表符,他的作用就是水平跳几个空格,保证每一列都能够实现左对齐。乘法口诀表就到这里吧,同时for也就到这里。
————————————-
if,顾名思义,这是一个条件判断语句,通常和else配合使用,也可以单独使用,他的意思是如果什么,那就做什么,否则就做什么。
———————-
if(什么)
     做什么;
else if(什么)
     做什么;
……
else
    做什么;
————————
光说不练就是纸上谈兵了,我们来个实例,也便好说明这个问题。
——————————
#include <stdio.h>
#include <stdlib.h>
int main()
{
     
int i;


      while(scanf(“%d”,&

i))
    {
          if(i>=0&

&

i<60)
               printf(“不及格,重考,下一个n”);


          else if(i>=60 &

&

i<70)
               printf(“一般般吧,勉强过关,下一个n”);


          else if(i>=70 &

&

i<90)
                printf(“好像还不错的样子,再接再厉,下一个n”);


          else if(i>=90 &

&

i<=100)
                printf(“漂亮,就是要这样,下一个n”);


          else
                printf(“无效成绩,什么玩意,下一个n”);


   
}

     system(“PAUSE”);



return 0;


}
—————————————
我们在看看运行效果,我们随便输入几个数字看看:
第九讲 if()
是不是觉得挺有意思的啊?是不是发现这好像有些菜单的感觉?嗯,不错,之所以举这个例子,主要是因为后面我们在说到switch()的时候我们用switch来实现这个例子,我们用switch来实现大家就更清楚了,实现菜一个单功能的思路也就更加清晰了。
if()同样可以和for()和while()等函数嵌套使用,关于这一点,留在明天吧,今天给大家留个思考题,大家有兴趣的话去分析一下怎么计算。
———————————————
      ABCDE五人在一场比赛中经过强烈的竞争后终于排下名次来,这五人的共同之处是有同一个好朋友,但遗憾的是他们的好朋友却因为一些事而不能参加,比赛结束后他们的好朋友分别询问了他们的名次,得到的回答如下:
      C不是第一名,D比E低两个名次,而E不是第二名,A既不是第一名也不是最后一名,B比C低一个名次。
      他们的朋友想了想终于得出了答案,现在要让大家用一个控制台程序来实现这个排名,大家能够实现吗?
——————————————

第七讲 数据类型&&C/C++关键字

        开始正事之前说两句题外话,我们这个课虽然叫C/C++,但是我现在给大家说的都是C的基础知识,当然同时也是C++的基础知识,不过大家最好把他当成C来理解,把C部分说完后会给大家讲C++,就好比现在讲OI的时候我并没有把cout和cin给拿进来,因为我怕把大家说懵了,分不清哪个是C那个是C++。可能有人听我这么一说会更纳闷,为什么不说清楚些呢?为什么不特意标明这是C不是C++呢?对此,我想说的是,不管是C还是C++用来写C++的程序是完全没问题的,如果可以,在以后我们编写C++程序的时候我希望大家能够把C++程序写成C风格的,好了废话撤远了,回到正题上来。
 

============================
昨天让大家验证一下putchar()和printf()的效率,不知道各位有没有去验证然后把我前天的结论给推翻,其实这两个函数真没啥好比的,C语言是一门面向过程的语言,讲究的效率,但这两个函数都能够满足,当输出10万个字符时,printf()的效率高于putchar(),但当输出100万个时候,putchar()明显又胜了一筹,所以,对于字符来说,用哪一个作为标准输出函数,就看大家的选择了。今天我们来说说C/C++的关键字和数据类型,下面我们来看看这个程序:
——————————
#include <stdio.h>
#include <stdlib.h>
int main()
{
     
int a,b,c;


      printf(“请输入a和b的值:n”);


      scanf(“%d,%d”,&

a,&

b);


      c = a + b;


      printf(“c = %dn”,c);


      system(“PAUSE”);


      
return 0;


}
————————————
这个程序主要是键入两个数,然输出這两个数的和,现在我们来看看运行结果:
第七讲 数据类型&

&

C/C++关键字
看来毫无问题,我们再来输入两个带小数的看看:
第七讲 数据类型&

&

C/C++关键字
为什么会是这样呢?c似乎就没抓到值一样,我们不妨来设个断点,抓取a和b的值看看有什么异常先,断点我们设在 c = a + b;

这里。
第七讲 数据类型&

&

C/C++关键字
看来只读取了a小数点前面的部分,b完全没有被我们键入的值初始化,这是为什么呢?这就是我们要说的数据类型了。因为我们在一开始声明变量的时候就把他们声明为整形,而我们却键入一个浮点型的数据,所以编译器凌乱了。为了实现能够小数相加,我们只需稍微的修改了上面程序的关键字即可,把int换成float,同时将类型转换换成%f即可。现在我们来看看是不是这样:
第七讲 数据类型&

&

C/C++关键字
第七讲 数据类型&

&

C/C++关键字
 

现在是不是正常了?这说明了一点,关键字很重要,下面我们来说说C/C++里面常用的几个关键字。
C/C++的数据类型关键字我们简单的说下下面这几个:
——————————————
int, short, long,unsigned, char,float, double, bool
——————————————-
其中int,short,long,char可以归纳为整形,整形顾名思义,就是整数类型。所以,一旦你声明一个变量为整形后,他就只会读取你的整数部分。所以如果你想要连小数部分读取,就得声明为了float或者double。
为什么表示整形有这么多表示方法呢?其实在C/C++有这么个定义,short不会比int长,同样long不会比int短,所以可以根据自己的需求声明不同的类型来节约资源。
float,double,doublefloat为带小数点的类型,他所声明的大概就相当于数学里面大家所理解的实数。
char,大家可以有些疑惑,明明是个字符型为什么上面把他归纳为整形呢?简单点说,其实每个字符或者标点符号都是被转换为整形来储存在0到127之间的,就好比65表示大写字母A,所以通常意义下是可以用char来表示-128到127之间的整数的。
bool,布尔,通常意义下表示真假,但是很多时候他却和整形挂钩,为什么呢?我想大家都清楚布尔值,那就是0为假1为真,所以有时候在程序里面会看到没有true和false,只有1和0,也就是这个道理,关于C/C++的类型和关键字,可以说是要说他没啥讲的他讲的也很多,要说他有啥讲的又感觉没啥讲的,所以今天就到这里,大家把这几个记下来基本能够应付一些程序了,至于其他今天没提到的,以后在程序里面会给大家解释,那时候大家也就记住了。
 

在讲for循环之前,给大家留个题,大家自己尝试一下怎么实现:
一个小球从100高空自由落下,每次落地弹起的高度是原来高度的一半,求小球第十次落地时共经历了多远?同时计算出第十次的反弹高度是多少?

第八讲 for

        昨天留给大家的问题不知道大家有没有去考虑,我想大家应该都很清楚这是一道物理题,当然我们并没有像研究物理题那样考虑得太多了,这里我们只需要计算出小球第十次接触地面的时候小球所经过的距离之和,再加上在第十次反弹起来的高度,所以这道题和真正的物理题比起要简单得多。
我们先来分析这道题的着手点吧。小球第一次下落时所经过的路程是100M,接下来的都是一上一下,所以我们可以定义一个float变量 h用来储存每次弹起的高度,第一次下落的100M我们就另当别论,不在这一上一下之列,那么现在抛开第一次触地之外,余下来的时间上只有九次了,不过这九次都是一上一下,换句话来说,这九次所经历的路程分别都是h*2。现在却跑出了一个难题,难道我们要用9*h*2吗?答案当然不是,那么我们应该怎么来考虑呢?
为了解答上面留下的问题,我们再声明一个float的变量s来储存小球所路径的路程,当小球没经历一次上下之后便把这个路程储存在s里面,最后我们再把历经9次得来的s相加起来,得到的便是我们所要计算的总路程。
那么最后第十次弹起的高度呢?第十次弹起的高度是第九次弹起的一半,而上面已经得出了第九次弹起的高度h,所以,第十次弹起高度自然就是h/2了。
题目我们已经分析完成,那么怎么来实现呢?这就是我们今天要说的for循环了。我们现在先来看看for循环一般的用法吧:
——————————
     for(表达式1;表达式2;表达式3)
       {
                      do something;
       
}

———————————-
该形式可以这么来理解,表达式1按表达式3的方式靠近表示2,表达式1表示for循环的入口,表达式2表示for循环的出口,表示3控制了for循环的循环方式。例如:
for(int i = 0;

i<n;

i++)
该循环的第一次是i = 0,接着用i++来控制循环方式的,表示i没增加1运行一次for函数,直到i = n-1时结束循环。
上面的函数语句里面我们说到i++这个概念,这是一个新概念,我们不如趁着现在顺便把C/C++里的运算符说一下。
C/C++里面的运算符其实和数学的里面的还是差不多的,就好比+-*/表示加减乘除,不过说到除法(/),C/C++里的整形的除法和数学里的有些不一样,C/C++里需要用两个符号一起方才能够表示一个数学里完整的除法,这两个符号分别是(/)和(%),(/)得到的结果是两数相除的整数部分,(%)得到的是余数部分,如下声明:
——————————-
int   n = 64;
        int   h  = n/60,m = n%60;


        printf(“%d : %d”,h.m);


———————————
上面的函数会打印出1:4,我想大家应该一眼就可以看出来,这其实就是计算随便输入一个分钟数,然后把他用标准小时和分钟打印出来,从这个例子里大家是不是明白了C/C++里面为什么会需要两个除法了吧,这里面的取余和取整都有很多妙用,当然具体情况还得靠大家去实现。
C/C++里面同样也有()运算,还有=,不过大家要记住一点,C/C++里面的=不是数学里面的=,C/C++里面的=是个赋值运算符,简单点说就是把右值赋给左值,通常情况下右值都是一个常量,左值是一个可变的变量,当然如果大家想要使用等号,那么记得使用“==”,也就是连写两个等号,事实上,在C/C++里面“==”存在的意义几乎就是用来断定的,通常用在if和while里面。
除了上面这些常用的运算符外,C/C++里面还有两个特殊的运算符,++ 和 –,++表示自加1,–表示自减1,如果这两个运算符出现变量的左边便是先加(减)再取变量的值,如果在右边,那就是先使用后再自加(减)给下次再使用该值。
当然C/C++里面同样存在逻辑运算符,和数学里面一样,他也有或且非,我们通常用&

&

表示或,用||表示且,用!表示非:
—————————————–
1<5 &

&

1>7     (该表达式为假,布尔值为0);
1<5 || 1>7        (该表达式为真,布尔值为1);
!(1<5 &

&

1>7)  (该表达式为真,布尔值为1);
!(1<5 &

&

1>7)  (该表达式为假,布尔值为0);
——————————————
通过上面的例子大家是不是明白了逻辑预算法的用了吧,
说了这些,就是让大家对运算符有所了解,现在我们言归正传,再回到我们刚才的正题上来。如果说刚才大家不知道该如何实现,那么现在是不是一切都在掌控之中了呢?首先把需要用的头文件包含起来,这个函数比较简单,就用一个标准输出IO就好,所以我们只需要包含stdio.h就好:
#include <stdio.h>
当然为了使用system(“PAUSE”)我们在包含另一个头文件:
#include <stdlib.h>
接下来我们分别声明三个变量,分别用来储存路程和高度
float  s = 100,h = 100;
int i = 0;
现在我们用for循环来计算高度和路程,用i来控制该循环,由于我们只需要循环9次,所以可以如下声明:
for(i;

i<9;

i++)
由于每一次反弹期的高度是上一次的一半,所以我们得出:
h = h/2;
大家是不是对这句有些疑惑,为什么h/2 就等于h了呢?这不符合数学逻辑啊,是啊,这本来就是什么数学逻辑,因为这里的h是变量,=并不表示等,而是赋值,所以这里是把上次的高度除以2后把值赋给h,从而改变了h的值。
明白了这里的赋值操作之后接下来我们应该把这个高度乘以2后加上上次的路:
 s = s + h*2;
每落地一次便是循环一次,所以每循环一次便会计算出上次反弹起的高度和所历经的路程,所以到此处我们的循环又开始下一次循环,直到循环九次后退出循环,然后打印出两关的s和h/2(第十次弹起的高度当然是我们计算出来的第九次的一半),下面我们把上面的代码整理一下:
——————————-
#include <stdio.h>
#include <stdlib.h>
int main()
{
    float h = 100,s = 100;


    
int i = 0;


     for(i;

i<9;

i++)
    {
          h = h/2;


          s = s + h*2;


     
}

      printf(” 小球下落共经过:%f米           n”,s);

    
      printf(“小球第10次落地后弹起的高度: %f米n”,h/2);

 
     system(“PAUSE”);

return  0;


}
——————————————–
好吧,现在我们来看看输出吧:
第八讲 for
至于这结果对与不对,有兴趣的同学可以自行笔算来核对一下吧。
现在想必大家都对for循环和运算符有一定的理解了,为了加深些印象,现在再留一道题给大家思考一下:
用for循环打印乘法口诀表:
提示一下吧,这里顺便说一下C/C++里的转义符:
a         警报(ANSIC)
b         退格
f         走纸
n         换行
r         回车
t         水平制表符
v         垂直制表符
\         反斜杠()
‘         单引号(‘)
”         双引号(“)
?         问题(?)
�oo       八进制值(o表示一个八进制数字)
xhh       十六进制值(h表示一个十六进制数字)