黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------



一、基本运算

1.算数运算

基本运算包括加、减、乘、除、取余运算,下面我们通过代码来感受一下:

<span style="font-size:14px;">int main()
{
// 1.算数运算符的基本使用
int a = 10 + 1 + 2 - 3 + 5;
printf("a=%d\n", a);
int b = -10;
int c = 10 * b;
printf("c=%d\n", c);
// 整数除以整数,结果还是整数
float d = 10 / 3;
printf("d=%.2f\n", d);
// 取余运算(模运算)
// %两边必须都是整数
// %取余结果的正负性只跟%左边的数值有关
int e = 10 % -3;
printf("e=%d\n", e);
return 0;
}</span>

下面是输出结果。


注意d的结果,说明10/3的结果只能精确到个数为,与d的类型无关,d的float类型只是把得出的结果3转成了float类型的3.00。

tips:关于运算顺序
int b =  6 / 3 * 2 ; 这个式子是先算乘法还是除法呢?
别犯懒了,自己敲一下,看看结果不就知道了!!!

2.强制类型转换

那么,我们如何得到精确的除法计算结果呢?
在做运算之前,我们可以用 强制类型转换把被除数或除数转换成小数。具体方法如下:
#include <stdio.h>

int main()
{
    // 把10强制类型转换为float类型
    float d1 = (float)10 / 3;
    printf("d1=%.2f\n", d1);
    
    // 把3强制类型转换为float类型
    float d2 = 10 / (float)3;
    printf("d2=%.2f\n", d2);
    
    return 0;
}
这样就得到了我们想要的答案:



做两到练习题来感受一下算数运算的应用吧:

1.下面的横线中填什么运算符,就可以保证无论a取什么值,b的值都小于10? 

int a =987654321

int b = a _10;

答案是:

int  b = a %  10 ;  //a除以10的所得的余数一定比10小


3.赋值运算、自增自减运算

#include <stdio.h>

int main()
{
// 1-赋值运算------------------------------------------------
    // 这一句其实是两句,int a; a = 5;
    int a = 5;
    // 这个等式看似不成立,但这里的等号不是相等的意思,是赋值的意思
    // a的值+5以后再重新赋值给自己
    a = a + 5; //这句过后 a =5+5=10
    printf("a=%d\n", a);
// 2-复合赋值运算---------------------------------------------
    int b = 1;
    b += 5; // 相当于 b = b + 5;  这句过后 b=1+5=6
    b -= 2; // 相当于 b = b - 2;  这局过后 b=6-2=4
    printf("b=%d\n", b);
// 3-自增自减运算---------------------------------------------
    // a++ 和 ++a 都相当于 a = a + 1; 他们的差别是,a++的赋值效果在下一次调用a时才生效,++a的赋值效果立即生效
    // 下面的代码可以直观的看出 ++a 和 a++ 的区别
    int c = 1;
    printf("c++时,c=%d\n", c++); // c = c + 1 ,c的新值下次生效,本次c的值仍然是1
    printf("c++以后,c=%d\n", c);
    
    int d = 1;
    printf("++d时,d=%d\n", ++d); // d = d + 1 ,d的新值立即生效,本次d的值是2
    printf("++d以后,d=%d\n", d);
    // a-- 、 --a 和 a++ 、++a是一个道理,别犯懒了,自己敲代码试一下吧!!!
    
    return 0;
}

上面代码的执行结果如下:



4.sizeof的用法

#include <stdio.h>

int main()
{
    // sizeof的用法
    int size1 = sizeof(10.3);
    int size2 = sizeof 10.7;
    
    printf("10.3在内存中占%d个字节\n", size1);
    printf("10.7在内存中占%d个字节\n", size2);
    
    int a = 10;
    int size3 = sizeof(a);
    int size4 = sizeof a;
    printf("a在内存中占%d个字节\n", size3);
    printf(“a在占内存中%d个字节\n", size4);
    
    
    int size5 = sizeof(char);
    printf("char数据类型在内存中占%d个字节\n", size5);

    // 下面这个写法是错误的,数据类型作为sizeof的参数必须加括号
    // int size = sizeof char;

    return 0;
}

上面代码的运行结果如下:



5.关系运算

#include <stdio.h>

int main()
{
     // 关系运算符有:大于、大于等于、小于、小于等于、等于、不等于
     //             >    >=      <    <=      ==   !==

     // 关系运算只有两种运算结果:
     // 1.条件成立就返回1,真
     // 2.条件不成立就返回0,假
    
    int a = 10;
    int b = 11;
    
    int result1 = b >= a + 2;
    printf(“result=%d\n", result1);
    
    // 算数运算符的优先级高于关系运算
    int c =  2 != 4 + 4 * 7 > 30 == 1;
    printf(“c=%d\n", c);

    return 0;
}


运行结果为:


tips:

看到类似 4 * 7 != 28 - 3 == 5 + 7 > 8  这样的式子是不是很恼人?

本篇末尾会提供运算符优先级顺序列表,但其实你根本不必被那烦人的表格,记不准的时候写个式子测试一下结果就ok了。

我认为实际编程中没有人会这样写式子的,为了可读性,大家会默默的加上小括号。



6.逻辑运算


逻辑运算有三种:逻辑与、逻辑或、逻辑非

1)逻辑与
#include <stdio.h>

int main()
{
    // 1.逻辑与 格式:条件1 && 条件2
    // && 两边都为真时,结果为1,否则为0
    
    int a, b, c;
    a  =  10>3 && 7<6;
    printf("a=%d\n", a);
    b = 100 && 0;
    printf("a=%d\n", b);
    
    a = 10;
    b = 10;
    // 一旦&&左边不成立,直接判断最终结果为0,就不会继续判断&&右边的语句了
    c = (a<5) && (++b>=11);
    // 由于&&右边的语句没有被执行,所以b的值仍然是10而不是11
    printf("a=%d, b=%d, c=%d\n", a, b, c);

    return 0;
}
运行结果如下:



2)逻辑或
#include <stdio.h>

int main()
{
    // 逻辑或 条件1 || 条件2
    // ||左右的两个条件只要有一个成立(为真),结果即为真,否则结果为假
    int a = 100;
    int b = 0 || a;
     
    int c = 10;
    int d = 10;
    int e = (c<5) || (d++ - 10);
    
    printf("b=%d, d=%d, e=%d\n", b, d, e);
    
    return 0;
}


运行结果说明第12行中逻辑或运算符右边的d++被执行了。


3)逻辑非

int main()
{
    // 逻辑非 格式:!条件
    // 如果条件成立,就返回0;如果条件不成立,就返回1
    
    int a = !(10>8);
    
    // -10不等于0,所以 -10=真,!-10 = !真 = 假 = 0
    int b = !-10;
    // 逻辑非的优先级大于逻辑运算符
    int c = !10>8;
    
    int d = !!10;
    
    printf("a=%d\n", a);
    printf("b=%d\n", b);
    printf("c=%d\n", c);
    printf("d=%d\n", d);
    
    return 0;
}

运行结果如下:


7.三目运算

三目运算又称三元运算,即需要三个操作数(一个条件,两个数值)来参与运算。
三目运算的用法如下:
int main()
{
    // 三目运算符  格式:条件 ? 数值1 : 数值2
    // 如果条件成立,返回数值1,否则返回数值2
    // int x = !3 ? 8 : 9  // 这样用是可以的 
    // 计算3个整数之间的最大值
    int a = 10;
    int b = 999;
    int c = 1000;
    
    // 求出a、b的最大值
    int abMax = (a > b) ? a : b;
    // 求出abMax和c的最大值
    int abcMax = (abMax > c) ? abMax : c;
    // 这一句和上面是等效的,但是可读性太差了,不推荐这样写。
    // int abcMax = (((a > b) ? a : b) > c) ? ((a > b) ? a : b) : c;
    
    printf("最大的数是%d\n", abcMax);

    return 0;
}
运行结果为:


tips:
一下子学了这么多种运算符,对于他们运算优先级排序是不是有点头大呢?
分不清的时候查下表格或写几行代码验证一下,计算机是不会记错的。
以后用多了自然就记住了,不必在这上面太过纠结。

运算符优先级顺序表:

优先级

(从高到低)

描述

运算符

1

括号

()、[]

2

正负号

+、-

3

自增自减,非

++、--、!

4

乘除,取余

*、/、%

5

加减

+、-

6

移位运算

<<、>>、>>>

7

大小关系

>、>=、<、<=

8

相等关系

==、!=

9

按位与

&

10

按位异或

^

11

按位或

|

12

逻辑与

&&

13

逻辑或

||

14

条件运算

?:

15

赋值运算

=、+=、-=、*=、/=、%=

16

位赋值运算

&=、|=、<<=、>>=、>>>=




二、流程控制

1.选择结构

默认情况下,计算机只会傻傻的按顺序从前向后执行我们的代码,这被称为顺序结构。
但当我们需要因某些条件而触发某个功能时,就需要用到一种新的结构——选择结构。

1)if条件
我们先来看一下下面的代码示例,注意看注释。
#include <stdio.h>
int main()
{
        int a = 10;
        // 如果条件1成立,执行这个代码块内的语句,后面的else if以及else代码块都不再执行;
        // 如果条件1不成立,则进入下一个条件判断
        if (a>9) // 条件1
        {
            printf("a大于9\n");
            // 其他你想要执行的语句……
            // 你甚至可以在if中嵌套一个if
            if (a==10)
            {
                printf("程序进入了if中嵌套的if代码段\n");
            }
        }
        // 如果条件2成立,执行这个代码块内的语句,后面的else if以及else代码块都不再执行;
        // 如果条件2不成立,则进入下一个条件判断
        else if (a>8) // 条件2
        {
            printf("a大于8\n");
        }
        // 如果条件3成立,执行这个代码块内的语句,后面的else if以及else代码块都不再执行;
        // 如果条件3不成立,则进入下一个条件判断
        else  if (a>7) // 条件3
        {
            printf("a大于7\n");
        }
        // 条件1、2、3都不成立时,才执行这个代码块内的语句
        else // 这里不需要写条件,只要else之前的条件都不满足,就会进入else代码块
        {
            printf("能来到这里,a一定小于或等于7\n");
        } 

    return 0;
}



if条件判断有三种关键字:if 、else if 、else ,从字面上大概可以猜出,他们是互斥的,简单说就是他们其中只有一个可以被执行。上面代码的执行结果也证明了这一点。

如果多个同级的(不发生相互嵌套的)if按顺序排列下来,如果条件满足,他们都可以被执行。我把之前的代码稍微做了修改,把else if 中的else都删掉了,看看结果有什么不同。

#include <stdio.h>
int main()
{
        int a = 10;
        // 如果条件1成立,执行这个代码块内的语句,后面的else if以及else代码块都不再执行;
        // 如果条件1不成立,则进入下一个条件判断
        if (a>9) // 条件1
        {
            printf("a大于9\n");
            // 其他你想要执行的语句……
            // 你甚至可以在if中嵌套一个if
            if (a==10)
            {
                printf("程序进入了if中嵌套的if代码段\n");
            }
        }
        // 如果条件2成立,执行这个代码块内的语句,后面的else if以及else代码块都不再执行;
        // 如果条件2不成立,则进入下一个条件判断
        if (a>8) // 条件2
        {
            printf("a大于8\n");
        }
        // 如果条件3成立,执行这个代码块内的语句,后面的else if以及else代码块都不再执行;
        // 如果条件3不成立,则进入下一个条件判断
        if (a>7) // 条件3
        {
            printf("a大于7\n");
        }
        // 条件1、2、3都不成立时,才执行这个代码块内的语句
        else // 这里不需要写条件,只要else之前的条件都不满足,就会进入else代码块
        {
            printf("能来到这里,a一定小于或等于7\n");
        } 

    return 0;
}



if的使用注意:

如果jf后面不写大括号,if的条件成立与否只决定if条件后第一条语句是否被执行,后面的其他语句按顺序照常执行

在if条件后面定义变量需要注意:
    // 下面的代码是错误的:作用域不明确
    if (10 > 6)
        int a = 5;
    // 如果要在if后面的语句中定义新的变量,必须用大括号{}扩住变量

tips:
我们尽可能的用else if而不是多个if并列。当使用多个else if并列时 ,如果有一个条件成立,系统就不会再判断后面的条件,这样可以提高程序的运行效率。

2)switch

#include <stdio.h>
int main()
{
    // 前面case中的值都不等于switch中的值时,进入default代码块
    // break:退出整个switch语句
    // 如果case后面没有break,就会执行后面所有case中的语句,直到遇到break为止
    int b = 10;
     
     switch (b)
     {
         case 10:
             printf("A\n");
             b++;
             // break;
         case 5:
             printf("B\n");
             b++;
             // break;
         case 0:
             printf("C\n");
             b++;
             // break;
         default:
             printf("D\n");
             b++;
             break;
     }
     
     printf("b的值是%d\n", b);

    return 0;
}



如果我将上面case 5 中的break注释打开,猜猜看,会是什么结果?

3)if 和 switch 的区别
1>if 能完成的功能,switch 并不一定能完成。
2>有些情况下,if 与 swith 可以互换。
3>switch 能做的功能,if 都可以做。


2.循环结构

有些时候我们需要程序重复执行一段代码,如果我们用拷贝粘贴的方式实现,一旦有一天代码需要更改,所有你拷贝过得代码都需要改。
有没有更高大上的方法呢?我们可以用循环结构来解决这种问题。

1)while 循环

格式如下:

 while (条件)

 {

   循环体

    // continue;  //结束当前的循环体,进入下一次循环体的执行

    // break;     //直接结束整个while循环

 }

 

 运行原理

 1.如果一开始条件就不成立,永远不会执行循环体

 2.如果条件成立,就会执行一次循环体,执行完毕,再次判断条件是否成立......

 3.看是否有其他条件可能会用到continue、break、或嵌套选择结构、循环结构


下面我来拟一个需求,用while循环实现这个需求。

小明做俯卧撑,最多能做50个,每做一次他就数一次“我做了XX个俯卧撑”,每做到10的倍数,他就默念,不喊出声音。今天他状态不佳,做到第33个就累趴下了。


#include <stdio.h>
int main()
{
    // 1.先确定需要重复执行的操作:输出做了几次俯卧撑
    // 2.再确定约束条件:最多做50个俯卧撑
    // 3.其他条件:每到10得倍数时,不输出字符串
    //            做到第33个时,累趴下了 =。=
    
    // 定义一个变量记录做的次数
    int count = 0;
    
     while (count<=50)
     {
         ++count;
         
         if (count%10 == 0)
         {
             // 直接结束这一次循环体,进入下一次循环
             continue;
         }
         
         printf("我做了%d个俯卧撑\n", count);
         // 今天状态不好,只做了33个 =.=
         if (count==33)
         {
             printf("尼玛,我累趴下了 =。=\n");
             break;
         }
     }
    return 0;
}

这是输出结果,太长了,所以我截屏了最后的部分。



2)do while 循环

do while和while的用法几乎一样,唯一的区别是do while至少会执行一次循环体,执行一次后再开始判断条件是否成立。

do while (条件)

 {

    循环体

    // continue;  // 结束当前的循环体,进入下一次循环体的执行

    // break;     // 直接结束整个while循环

 }


3)for 循环

for ( 语句1;条件 ;语句2)
{
        循环体
         continue; //结束本次循环体,进入下次循环体
        break;        //结束整个循环

语句1:初始化语句(只在整个for循环开始时执行一次)
语句2:增量语句(每次循环体执行后,执行一次该语句)

执行过程:初始化语句—>条件成立—>循环体—>增量语句—>条件成立—>循环体—>增量语句—>……

我们再让小明用for循环做一次俯卧撑吧  =。=

#include <stdio.h>
int main()
{
    for (int count = 1; count <= 50; count++)
    {
        if (count%10 == 0)
        {
            // 直接结束这一次循环体,进入下一次循环
            continue;
        }
        
        printf("我做了%d个俯卧撑\n", count);
        
        if (count==33)
        {
            printf("尼玛,我累趴下了 =。=\n");
            break;
        }
    }
  

运行结果是一样的,这里我就偷个懒,不截图了。

tips:
for的一些使用注意:
#include <stdio.h>
int main()
{
    /* 不要随便在for()后面写分号,写分号相当于for循环体是一个空语句
    for (int i=0; i<5; i++);
    {
        printf("哈哈\n");
    }*/
    
    /* 错误:变量a的作用域不明确
     如果要在循环体中定义新的变量,必须用大括号{}包住
    for (int i=0; i<5; i++)

        int a = 10;
    */
    
    // 最简单的利用for循环实现死循环
    // for(;;);
    
    return 0;
}


三.函数

 1.什么情况下定义函数:

当我们需要重复执行某一个功能时,我们就可以把用以支持这个功能的代码块封装到一个函数中,每次需要执行这个功能时,只要调用对应的函数就可以了。

printf 其实就是系统帮我们封装好的一个函数。

 2.函数的定义格式

 返回值类型 函数名(形式参数列表)

 {

   函数体

 }

 3.定义函数需要明确的东西

 1>起一个有意义的函数名

 2>返回值类型

 3>需要传什么参数进来


#include <stdio.h>

int average(int num1, int num2)
{
    return (num1 + num2)/2;
}

int main()
{
    int a = 10;
    int b = 8;
    
    int c = average(a, b);
    
    printf("c is %d\n", c);
    
    int a1 = 11;
    int b1 = 20;
    
    int c1 = average(a1, b1);
    printf("c1 is %d\n", c1);
    
    return 0;
}

 4.函数的注意点

 1.默认情况下,不允许有函数的名称一样

 2.函数不能嵌套定义

 3.函数不能重复定义,但是可以重复声明

 4.如果有函数的声明,没有函数的定义

 1>编译可以通过,因为编译器只会检测语法合不合理,并不会检测函数有没有定义

 2>链接报错,因为链接的时候会检测函数是否定义



四、多人团队开发文件结构

第三章的函数除了可以封装代码外,还有提高团队开发效率的作用。比如在一个项目中,李四负责写main函数,张三的数学很好,负责写计算用的函数,李四和张三可以把他们的代码写在两个文件中,最后在一起完成连接就可以了。
但李四的main函数中并没有张三函数的定义,如果李四直接调用张三的函数,编译时是会警告的:




其实,函数不但有定义,还有声明,只要在main函数所在的文件中声明要调用的函数,编译器就认为我们有这个函数,也就不会警告。

函数的声明格式:返回值类型  函数名(形参);   //注意最后要写上分号

但张三可能写了很多个计算用的函数,没次有改动,李四都要去重新拷贝一份声明过来,很麻烦,也容易出错。

张三想了一个办法,把所有的函数声明写在一个被称作”头文件”的文件中(后缀是.h),这样李四只要在它的文件头部写上这一句: #include  “zhangsan.h”,就ok了。

这是我用多文件完成的一个求平均数的简单程序:



tips:
用 #include 包含文件时,如果是自己写的头文件,要用 ” “ 括住,只有系统自带的头文件才用< >括住

多个.c文件一起编译连接时,终端指令可以在每个文件前打个空格


小结:

1.注意运算符直接的优先级,记不清时写两句简单的代码验证一下
2.a++ 与 ++a是有区别的,前者累加效果下次生效,后者即时生效
3.如果逻辑与的第一个条件不成立,第二个条件中的语句根本不会被执行
4.选择结构 if ,连续写多个if会一次判定其条件;if后连续写else if,只会执行第一个满足条件的代码块。
5.注意break、default在case中的用法,注意continue、break在循环结构中得用法

To be continue……
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值