前面我说过:“结构化编程语言,用语法限制程序员,只能使用顺序、选择、循环三种结构来解决问题。”
接下来,就讲解这三种结构。
顺序结构
前面我讲过,C语言所有的程序,都必须有一个 main 函数,C语言设计的程序,也是从 main 开始执行,所以,C语言的顺序结构,第一条就是:不论你的源码有多少个函数,都得先找 main,至于 main 运行之前在计算机在做什么,对于计算机科学来说很重要,但对于没什么计算机基础、且初学C语言的你来说,不重要,所以暂时不要在这个问题上浪费精力。
当计算机进入 main 之后,就从main函数的第一条语句开始,按照从上到下顺序,一条一条的执行。比如下面这段代码,虽然 TestParam 函数在 main 函数的上面,但是所有C语言程序,都是从main 开始执行,因此这段代码,先执行 main 函数,进入main函数后,先定义两个变量 iA 和 iB ,并且分别初始化为 0x9 和0x29,然后调用函数 TestParam, iA 和 iB作为函数的实参。
进入 TestParam后,打印两个形参的值,然后返回0;TestParam 函数返回后,回到了main函数,我们可以看到,函数返回值赋值给了 iA,因此 iA被赋值为了0,所以接下来 打印 iA 的值为0。
int TestParam(int x, int y)
{
printf("x == %x, y == %x\r\n", x, y);
return 0;
}
int main(void)
{
int iA = 0x9, iB = 0x29;
iA = TestParam(iA, iB);
printf("iA == %x", iA);
return 0;
}
代码的执行结果如下:
选择结构
C语言的选择结构有两种:if 语句 和 switch 语句
if 语句
if 语句的形式如下:
if(表达式)
{ // 左括号0
} // 右括号0
else
{ // 左括号1
} // 右括号1
当表达式的值为真(非 0 值)时,执行左括号0 和 右括号0 括起来的程序;表达式的值为假时(为0),执行左括号1 和 右括号1 括起来的程序。
比如下面这段程序:
int main(void)
{
int iA = 0x9, iB = 0x29;
if(iA > 0x7)
{ // 左括号0
printf("iA == %x\r\n", iA);
} // 右括号0
else
{ // 左括号1
printf("iB == %x\r\n", iB);
} // 右括号1
}
因为 iA 初始化为0x9,因此 iA > 0x7 的值为真(值为 1),因此应该执行左括号0 和 右括号0 括起来的程序,即打印 iA的值,执行结果如下:
如果我们修改一下程序,把iA 初始化为 0x2:
int main(void)
{
int iA = 0x2, iB = 0x29;
if(iA > 0x7)
{ // 左括号0
printf("iA == %x\r\n", iA);
} // 右括号0
else
{ // 左括号1
printf("iB == %x\r\n", iB);
} // 右括号1
}
执行结果,就变成了打印 iB的值,即:
表达式为假时,如果不需要做任何事情,那么else {} 的部分可以不要。
int main(void)
{
int iA = 0x2, iB = 0x29;
if(iA > 0x7)
{ // 左括号0
printf("iA == %x\r\n", iA);
} // 右括号0
}
switch 语句
switch 语句的基本形式如下:
switch(整形变量)
{ // 左括号0
case 整形常量0:
//TODO
break;
case 整形常量1:
//TODO
break;
default:
//TODO
break;
} // 右括号0
当整形变量的值,与case后面的常量值一样时,执行case后面的程序,直到 break;如果整形变量的值,在任何一个case后面都找不到,那么就执行default 后面的程序,直到 break。
比如某次考试,满分10分,所有成绩用自然数表示,低于6分为不及格,6分为及格,7分、8分为良好,9分和10分为优秀,其他分数无效,就可以写如下程序:
int main(void)
{
int chengJi = 3;
printf("成绩 %d 分\r\n", chengJi);
switch(chengJi)
{ // 左括号0
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
printf("不及格\r\n");
break ;
case 6:
printf("及格\r\n");
break ;
case 7:
case 8:
printf("良好\r\n");
break ;
case 9:
case 10:
printf("优秀\r\n");
break ;
default:
printf("分数无效\r\n");
break;
} // 右括号0
}
执行结果如下:
这里要深入理解一下这句话:“执行case后面的程序,直到 break”。如果我们把上题改一下,输出成绩的等级之前,还得输出与成绩数量相同的 “*” ,那么程序可以写成下面这样:
int chengJi = 3;
printf("成绩 %d 分\r\n", chengJi);
switch(chengJi)
{ // 左括号0
case 5:
printf("*");
case 4:
printf("*");
case 3:
printf("*");
case 2:
printf("*");
case 1:
printf("*");
case 0:
printf("不及格\r\n");
break ;
case 6:
printf("******");
printf("及格\r\n");
break ;
case 8:
printf("*");
case 7:
printf("*******");
printf("良好\r\n");
break ;
case 10:
printf("*");
case 9:
printf("*********");
printf("优秀\r\n");
break ;
default:
printf("分数无效\r\n");
break;
} // 右括号0
}
执行结果如下:
这里要强调,程序进入相应的case后,会一直执行,直到break 。
关于default
首先说明,default 选项可以没有。switc语句中,如果所有case后面的常量,都不匹配,且程序里面有default,那么就会执行 default 后面的语句,直到break;
这里强调一下:default 一定是所有case都不匹配后,才会执行。比如下面这段代码:
int main(void)
{
int chengJi = 100;
printf("成绩 %d 分\r\n", chengJi);
switch(chengJi)
{ // 左括号0
case 5:
printf("*");
case 4:
printf("*");
// ***********注意 default 在这里
default:
printf("分数无效\r\n");
case 3:
printf("*");
case 2:
printf("*");
case 1:
printf("*");
case 0:
printf("不及格\r\n");
break ;
case 6:
printf("******");
printf("及格\r\n");
break ;
case 8:
printf("*");
case 7:
printf("*******");
printf("良好\r\n");
break ;
case 10:
printf("*");
case 9:
printf("*********");
printf("优秀\r\n");
break ;
} // 右括号0
}
执行结果如下:
循环结构
while 循环
while循环的形式如下:
while(表达式)
{
循环体;
}
首先明确一个概念,while后面有一对大括号,他们括起来的语句,叫做循环体。当表达式的值为真(值为非0,下同)时,执行一次循环体;当表达式的值为假(值为0,下同)时,退出循环,执行循环外面的语句。
比如下面这个代码:
int main(void)
{
int i ;
i = 10;
while(i > 0) // 当i 大于0时,执行循环体
{
// 循环体有两条语句: 打印i的值,然后给 i 减一
printf("i == %d\r\n", i);
i --;
}
// 循环退出后,打印 while over 和 i的值
printf("while over %d, \r\n", i);
}
运行结果如下:
do-while 循环
do-while循环的形式如下:
do
{
循环体;
}while(表达式); // 注意,这里有个封号
注意:while(表达式) 的右边有一个封号。那个封号不能少。
do-while循环的执行方式是,先执行一次循环体,然后再判断表达式的值,如果表达式的值为真,就回到do那里,在执行一次循环体;如果表达式的值为假,就退出循环,执行循环后面的语句。
聪明如你,一定可以看出来,do-while 循环里的循环体,至少会执行一次。
请看下面这段代码:
int main(void)
{
int i ;
i = 10;
do
{
// 循环体有两条语句: 打印i的值,然后给 i 减一
printf("i == %d\r\n", i);
i --;
}while(i > 0);
// 循环退出后,打印 while over 和 i的值
printf("while over %d, \r\n", i);
}
执行结果如下:
我们再深入理解一下这句话:do-while 循环里的循环体,至少会执行一次。理解一下,是至少执行一次,不是比 while循环多执行一次,从上面这个例子可以看出来,同样的逻辑,while和 do-while 执行的次数是一样的。
如果do-while循环和 while循环,逻辑相同,再大多数情况下,循环执行次数是一样的,只有当表达式初始为假时,他俩才有区别。
比如下面两段程序,跟前面的程序相比,用于控制循环表达式,变成了 i .> 100。因为 i 的初值是 10,减1之后是9,无论如何不可能大于100,运行一下,我们就会发现,do-while循环,比while循环多执行了一次。
int main(void)
{
int i ;
i = 10;
do
{
// 循环体有两条语句: 打印i的值,然后给 i 减一
printf("i == %d\r\n", i);
i --;
}while(i > 100);
// 循环退出后,打印 while over 和 i的值
printf("while over %d, \r\n", i);
}
int main(void)
{
int i ;
i = 10;
while(i > 100)
{
// 循环体有两条语句: 打印i的值,然后给 i 减一
printf("i == %d\r\n", i);
i --;
}
// 循环退出后,打印 while over 和 i的值
printf("while over %d, \r\n", i);
}
for 循环
for循环的形式如下:
for(表达式1; 表达式2; 表达式3)
{
循环体;
}
for循环中的执行顺序是:
- 执行表达式1
- 判断表达式2的值如果为真,则执行 3. ,否则退出循环;
- 执行循环体
- 执行表达式3,回到 2. 继续执行
聪明如你,一定可以看出来,for循环中,表达式1 只执行一次,所以它通常用来初始化循环条件。表达式3,通常用来改变循环条件。像下面这样:
int main(void)
{
int i ;
for(i = 10; i > 0; i --)
{
// 循环体有一条语句: 打印i的值
printf("i == %d\r\n", i);
}
// 循环退出后,打印 while over 和 i的值
printf("while over %d, \r\n", i);
}
执行结果如下:
C语言所有的循环,都是当型循环
聪明如你,C语言中一定发现了无论 while, do-while,还是for,都是当循环条件为真时,执行循环,这种循环叫做:当型循环。
还有一种循环是循环条件为假时执行条件,直到循环条件为真后退出循环,这种循环叫做:直到型循环,C语言里没有这种循环。