前言
学习C语言,必须要掌握的是三大结构——顺序、分支和循环。一切C语言程序都可以用这三个结构总结,因此熟练掌握它们,对于写程序以及理解程序都是非常有必要的。
目录
顺序结构
简而言之,顺序结构就是一切程序从首行开始,自顶向下进行编译。这是C语言最基本的结构,听起来很简单,但是往往有很多细小的错误就是由于没有注意到这一点而导致。主要的错误可能有以下两个:
变量声明
#include<stdio.h>
int main()
{
printf("%d", num);
return 0;
}
int a = 10;
乍一看,貌似上述代码没有问题,有的同学会觉得“欸!没有错啊!a是一个全局变量,应该是可以答应的啊?”。但是,就像上面说的,顺序结构,a的定义是在main函数之后的,因此系统先编译到printf语句,此时系统还不知道a已经被定义过了,因此会弹出错误 :
对此只能说同学们对于变量还不够了解,详情可以参照上篇博客,简单来说就是a的声明周期是整个程序,但是a的作用域没有包含main函数。
函数声明
#include<stdio.h>
int main()
{
int a = 1;
a = func(a);
printf("%d", a);
return 0;
}
int func(int a)
{
return a + 1;
}
同样的,当我们试图运行上面的程序的时候,系统再次给出了报错,也许有的同学还没有学过函数,没有关系,不妨碍我们解读这段代码
func函数是你输入一个数,返回这个数+1,对于编译器给出的报错,找不到标识符即系统不知道func这个单词是什么意思,同样可以类比上面变量的定义。对于func函数而言,我们定义了,但是自顶向下编译的时候未发现这个函数,因此也就出现了上方的报错,这也就是为什么经常看见在main函数前面有多个一行的代码,这就是下节会讲到的函数的声明。
循环结构
什么叫循环?
什么叫循环?
什么叫循环?
上面就是一个循环,C语言用于循环的语法主要有三个,do-while,while,for
while
许多同学应该都认识这个单词,while---当...的时候,C语言同样可以这样理解。例如我们看下列代码
#include<stdio.h>
// while(条件)
// {
// 命令语句;
// }
int main()
{
int i = 10;
while (i >= 0)
{
printf("%d\n", i);
i = i - 1;
}
return 0;
}
简单分析,当第一次运行到while处时,i = 10,while (i >= 0),当i >= 0时,才执行后面的行为,十大于零,显然可以继续下去,而进行了一系列操作之后,系统就会再次判断i是否满足条件,也就是重新返回到while语句一行,再次判断一下i是否还满足i >= 0的条件。由于每次打印完之后,i都会减1,因此最后当i变为-1的时候,不满足i >= 0,因此自然就不再执行下面的预计,让我们来看看结果:
do-while
学习了while之后,do-while将很好理解。可以看出相比于while,多出一个do在while前面,那么显然易见,do-while就是先执行一遍,再进行判断
#inlude<stdio.h>
// do
// {
// 命令语句;
// }while (判断条件);
int main()
{
int i = 10;
do
{
printf("%d\n", i);
i = i - 1;
}while (i >= 20);
return 0;
}
很多同学第一眼一看,i = 10,判断条件是i >= 20,那么自然无法执行命令语句,但是实际运行结果显然和我们的分析不一样:
而出现这种情况,就是while和do-while之间的差别,do-while是一定会执行一遍,再进行判断,而while是先判断,再决定要不要执行命令语句。
for
#include<stdio.h>
// for (初始化语句; 判断语句; 调整语句)
// {
// 命令语句;
// }
int main()
{
int i = 10;
for (i = 0; i < 10; i = i + 1)
{
printf("%d ", i);
}
return 0;
}
for语句看起来相对较麻烦,但是麻烦带来的,自然而然就是精明,因此在平时使用中,大部分时间我们都会使用for。如上面的代码,先对i初始化为0,每次先进行判断 i 是否满足判断语句,然后执行命令语句,最后执行挑战语句,对i的值进行调整,运行结果如下:
同时值得注意的一点就是,for语句中的三个条件都可以省略,可以单独省略,也可以一起省略,因此当你看见for( ; ; )的时候大可不必觉得奇怪,这就是一个死循环,
break
如果我们想要在数组中查找某一个特定的数字,当我们第一次查找到之后就可以退出循环了,此时我么该怎么做呢?答案是加入 break,告诉系统,这个循环该退出了,例如:
#include<stdio.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, target = 6;
for (int i = 0; i < 10; i = i + 1)
{
if (arr[i] == target)
break;
printf("did not find\n");
}
printf("%d", i);
return 0;
}
但是需要注意的是,break只能跳出一个循环,也就是说,当循环嵌套时,无法全部全部跳出
continue
假如需要打印一个数组,但是希望只打印正数部分,那么可以用continue解决,其作用是,跳过后面的执行语句,返回到判断部分,如:
#include<stdio.h>
int main()
{
int arr[] = { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }, i = 0;
for (i = 0; i < 10; i = i + 1)
{
if (arr[i] < 0)
continue;
printf("%d\n", i);
}
return 0;
而对于continue值得注意的是,for语法的调整语句不属于continue之后的执行语句,因此continue之后依旧会对i进行调整
分支结构
if....else....
#include<stdio.h>
// if(判断语句1)
// 执行语句1;
// else if (判断语句2)
// {
// 执行语句2;
// 执行语句3;
// }
// else
// 执行语句4;
//
//
int main()
{
int i = 0, k = 0;
scanf("%d", &i);
if (i < 0)
printf("-1\n");
else if (i == 0)
{
printf("0\n");
k = 1;
}
else
prinf("1\n");
if (k == 1)
printf("输出就是i本身");
printf("k此时等于1");
}
if ... else语句中必须要由if开头判断第一个条件是否成立,然后才能用else if ,值得注意的有两点:
一、if或者else if 或者 else其后只能加上一条执行语句,如果想要加上多条执行语句,则需要用大括号将其括起来。
二、 if 以及else if 之后都必须要有判断条件,但是else不需要, else的意思是,除去else 之前if 和else if 判断的条件之外的所有条件。
switch
#include<stdio.h>
// switch (n)
// {
// case 情况1:
// 执行语句1;
// break;
// case 情况2:
// 执行语句2;
// breakl
// case 情况3:
// 执行语句3;
// break;
// default:
// 执行语句4;
// break;
// }
int main()
{
int i = 0, k = 0;
scanf("%d", &i);
switch (i)
{
case 1:
printf("good\n");
break;
case 2:
printf("bad\n");
case 3:
printf("normal\n");
break;
default:
printf("wrong\n");
break;
}
return 0;
}
相比较于if 语句,switch语句显得相对笨拙,只能判断特定的选项,即case之后接的只能是对switch括号中的变量的某一个取值,例如上图中对int类型的变量 i 就只能判断 i 的取值,而值得注意的几点有:
一、如果是对字符变量的判断,则case之后需要接字符,例如判断是不是字符a是 case 'a'
二、每一个case之后必须要跟上一个break表示跳出switch语句,否则如果从该case进入switch语句,程序会一直执行,直到遇见break或者遍历完switch,如上图中,输入2,将打印bad和normal
三、default的作用相当于if else语句中的else,表示除去上方所有case之外的情况,注意!default不一定放在所有case之后,可以放在若干case中间,此时需要根据顺序结构判断具体情况
goto语句
goto语句是一个相对而言比较特殊的语句,一般情况下无法单独作为分支结构,而是通常与if等常规的分支结构连用 ,用法如下:
在程序某一行给出loop标签,可设置loop1,loop2等,加上冒号,表示此处是一个标志点。
当需要使用goto语句的时候,使用 goto loop,可以为goto loop1,goto loop2等,此时程序将无条件跳转到标志点继续开始执行。
lir
#include<stdio.h>
int main()
{
int i = 0, arr[5][5], x = 0, y = 0;
for (i = 0; ; i++)
{
for (x = 0; x < 5; x++)
{
for (y = 0; y < 5; y++)
{
arr[x][y] = i;
if (i == 15)
goto loop;
}
}
}
loop:
for (x = 0; x < 5; x++)
{
for (y = 0; y < 5; y++)
{
printf("%d", arr[x][y]);
}
}
return 0;
}
例如在上述代码中。利用goto语句直接跳出多个循环,如果用一个break的话就只能跳出一个循环,而多个break的话则无法满足原本的要求。
在一些相对比较复杂,或者有多层循环嵌套的时候,goto语句往往有奇效,但是由于goto语句功能实在太强大,loop标签的位置基本上可以设置在程序的任何一个位置,因此在使用goto语句的时候一定要做好备注,不然当多个goto语句连用的时候,程序的可读性将大大降低,往往看你的程序的人一会就不知道程序已经goto到哪里去了。所以做优秀的程序员,首先从写好备注开始。