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

时间:2021-05-21 00:26:10

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

下面是输出结果。 黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数

注意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;
}
这样就得到了我们想要的答案:
黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数


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

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;
}

上面代码的执行结果如下:
黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数


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;
}

上面代码的运行结果如下:
黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数


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;}


运行结果为:

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

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;
}
运行结果如下:黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数


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;
}
黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数

运行结果说明第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;
}

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

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;}
运行结果为:
黑马程序员——零基础学习iOS开发——04 c语言:基本运算、流程控制、函数

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;
}

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

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;
}

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

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;
}

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


如果我将上面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;
}

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

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


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函数中并没有张三函数的定义,如果李四直接调用张三的函数,编译时是会警告的:


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

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

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

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

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

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

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


tips:

用 #include 包含文件时,如果是自己写的头文件,要用 ” “ 括住,只有系统自带的头文件才用< >括住
多个.c文件一起编译连接时,终端指令可以在每个文件前打个空格

小结:

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