文章目录
- 一.什么是语句
- 二.控制语句
- 三(一).分支语句if-else
- 3.1if
- 3.2if-else
- 3.3if-else嵌套
- 3.4悬空else
- 3.5if语句判断的流程
- 3.6if语句可能会犯的小错误
- 三(二).分支语句switch
- 四.循环语句
- 4.1while语句
- 4.2do while语句
- 4.3for语句
- 4.4一道简单又不简单的小题目
- 4.5循环总结
- 4.6循环上的一些小建议
- 五.goto语句
一.什么是语句
C语言语句基本可以分为5类
- 表达式语句
简单来讲就是一个以分号结尾的语句。
- 函数调用语句
例如add();这就是调用了一个名字叫add的函数,这个就是函数调用语句
- 控制语句
接下来讲的分支,循环语句就是控制语句
- 复合语句
复合语句又称为语句块,把一堆语句用花括号括起来,形成一个单独的语句块
- 空语句
就是一个分号,虽然有这个语句但是有和没有对程序没什么影响。
一般用在循环里,可以当成一个空的循环体。
也可以在以后调试设置在这里一个断点
也可以在这里放一个空语句,以后想在这里插个新的代码,就可以能一下找到位置,也可以理解为增加代码可读性。
二.控制语句
控制语句又分三种:
1.条件判断语句也叫分支语句:if,switch语句
2.循环执行语句:do-while,while,for语句
3.转向语句:goto,break,continue,return语句
三(一).分支语句if-else
语法结构:
//1.
if(表达式)
语句;
//2.
if(表达式)
语句1;
else
语句2;
//3.
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
当然也可以在一个if语句里在嵌套if语句
if(表达式)
if(表达式)
{}
else
语句2;
3.1if
if(表达式)
语句;
if就是如果的意思,后面跟的是一个表达式,整个代码的意思就是:如果这个表达式为真,就执行后面的这个语句。如果为假就不执行这个语句,代码就会跳过这个if,去执行之后的代码。
在C99标准出来之前,C语言是没有bool值这个概念的,if判断真假的方法是:
if后面的表达式的结果是0就是假,非0即真
if后面的表达式的逻辑判断是真的话就是真,否则就是假
逻辑判断:
一个表达式判断是否为真,比较low的理解就是看这个表达式它有没有说谎,有就是假,否则就是真。
&&是逻辑与的符号:
表达式1 && 表达式2.只有两个表达式都为真的时候,这整个表达式的结果才是真,否则是假。你可以把它理解为乘法,结果为真就是1,为假是0.这样的话是不是只有1*1才是1,其它情况都是0.
||是逻辑或的符号:
表达式1 || 表达式2.只有两个同时为假,结果才是假,其它情况都为真。这里你可以理解为加法。当然这个的1+1结果还是1.
!是逻辑非的符号
!表达式。如果表达式是1,整个结果是0,否则就相反。
例子:
int main()
{
int i = 10;
if (i == 10)
printf("YES\n");
return 0;
}
这句if代码的意思是如果i这个变量的值等于10就执行后面的这个printf函数。也就是i==10这个表达式结果为真就执行后面的语句。
屏幕上确实打印了我们想要的YES。
\n
这个代表换行,就是输出完之后换一行,下次如果还想在屏幕上打印时就从YES下面那行开始写入信息。
=和==的区别:
一个=是赋值
a=20就是把20赋值给a,此时a的值就是20.
a=20这个语句结束后结果就相当于20.
a=21这个语句结束后的结果就相当于21.
两个=是判断相等
假入a的值现在是20.
a == 20这个结果就是1,也就是真。如果此时a的值是19呢?那刚才那个代码的值是假也就是0.
现在我通过两个代码来带大家理解逻辑为真,和结果为真有什么区别:
int main()
{
int i = 0;
if (i == 0)
{
printf("hello");
}
if (i = 0)
{
printf("hi");
}
return 0;
}
这个代码的结果是什么?
发现这里只打印了一个hello,那是因为第一个if判断的是i==0因为i的值的确为0,也就是说这个表达式的结果为真,所以可以打印if里面的内容。
那为什么第二个if语句里面内容没有被执行呢?那是因为这里不是判断,而是赋值i=0,说明把0这个值赋给i。赋值完之后if后面括号的内容就是:
if(0)
而在C语言中0为假,非0即真。所以不执行其里面的内容。
3.2if-else
if(表达式)
语句1;
else
语句2;
现在我们希望给别人两种选择如果你选择了1就执行语句1,否则执行语句2.
int main()
{
int i = 0;
scanf("%d", &i);
if (i < 18)
printf("未成年");//语句1
else
printf("成年");//语句2
}
这个代码就是如果你输入的i值小于18,也就是if后面语句结果为真,就执行语句1.否则就执行语句2。
假如我们现在语句1不止一句话:
int main()
{
int i = 0;
scanf("%d", &i);
if (i < 18)
printf("未成年");//语句1
printf("666");//语句2
else
printf("成年");//语句3
}
像这样如果i < 18的值为真的话,程序会执行语句1和语句2吗?
会发现不行,系统会报错,这是因为如果if语句下面没有加上花括号,if结果为真的时候系统不知道执行语句1,还是语句2.所以才会发生错误,所以我们这样改一下:
int main()
{
int i = 0;
scanf("%d", &i);
if (i < 18)
{
printf("未成年");
printf("666");
}
else
printf("成年");
}
现在就可以正常打印了。if,else后面只有一句代码时,可以省略掉{},但是为了养成两行的习惯,推荐不管后面有几句代码,都加上{}。
3.3if-else嵌套
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
你可以if,else,if…这样一直写,这根据你自己的需求来定。其实这段代码最开始是长这个样子的:
if(表达式1)
语句1;
else
if(表达式2)
语句2;
else
语句3;
if(表达式3)
语句3;
...
但是这样写可读性变得非常差,所以把它改成最上面的样子。这个语句可以帮我们写一个多分支的代码:
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("少年\n");
}
else if (age >= 18 && age < 30)
{
printf("青年\n");
}
else if (age >= 30 && age < 50)
{
printf("中年\n");
}
else if (age >= 50 && age < 80)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}
}
3.4悬空else
先看一段代码:
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
这会打印哪个呢?可能有人脑子一热,a是0啊,if(a==1)结果为假肯定会执行下面的haha。但结果真是如此吗?
发现什么都没有输出,这是为什么呢?因为如果一个else对应多个if时,这个else会去匹配离它最近的if。其实代码应该长这样:
画方框的可以当成if(a == 1)里面的一个语句块。也就是说if(a = = 1)的结果为假的话,程序会跳过后面整个语句块。直接到return 0;所以程序什么也不会输出。
如果我们想要打印哈哈,就可以这样改:
int main()
{
int a = 0;
int b = 2;
if (a == 1)
{
if (b == 2)
printf("hehe\n");
}
else
printf("haha\n");
return 0;
}
人为的加上一个花括号,强行让最后一个else与第一个if相匹配。
有一个小细节:
在最开始没有加花括号的时候,if不是只会执行它后面的一个语句吗?上面这样写会不会出现问题?如果向下面这样写还有没有问题?
int main()
{
int a = 0;
int b = 2;
if (a == 0)
if (b == 1)
printf("hehe\n");
else
printf("666\n");
else
printf("haha\n");
return 0;
}
这里的if我没有加括号,但是我下面写了四行代码,现在它能不能执行打印666这个字符串呢?
运行结果上看是做的到的,为什么呢?不是是能执行一句吗?打印“666”都是第四句了,其实里面嵌套的if-else语句它可以当成一个语句,因为程序走到这一步的时候,if-else它只能进入到其中一个语句块中,另一个是不会进的。上面这个代码是进入到else语句,也就是说外面的if执行它后面的语句时是把else当成它的语句,而且进入到else之后不管else里面有多少行代码都不管了,都会执行,像这样:
int main()
{
int a = 0;
int b = 2;
if (a == 0)
if (b == 1)
printf("hehe\n");
else
{
printf("666\n");
printf("666\n");
printf("666\n");
printf("666\n");
}
else
printf("haha\n");
return 0;
}
3.5if语句判断的流程
- 先执行if后面括号里的表达式或函数,得到结果
- 根据条件执行判断功能
- 最后在执行分支功能
什么意思呢?
int main()
{
int a = 1;
if (a == 0)
printf("ah");
else
printf("a==1");
return 0;
}
第一步先执行if后面的表达式拿到结果。
第二步在进行判断,判断是进入if还是else或者是if else的代码块当中。
第三步就是执行if/else里面的语句块。
3.6if语句可能会犯的小错误
有时候初学者可能会这样写代码:
int i = 0;
if(i == 0);
{
printf("hello");
}
这样写是对的吗,当然是对的,但是这代码能得到你希望的值吗?那就不一定了,这里的错误就是习惯给一句代码后面加上分号。if后面本来是不需要加分号的,而这里你给加上了,如果你有一个很长的代码,这个地方出现了这样的一个小错误,而且更要命的是编译器还检查不出来这样的错误,以后找BUG就会花相当长的时间。
这里就是给大家提个醒,防止你们这样写。
还有一个小错误:
int i = 0;
if(i = 0)
{
printf("hello");
}
这里把==写成了=,这样写编译器也同样检查不出来。所以为了避免出这样的错误,我比较推荐下面这种写法:
int i = 0;
if(0 == i);
{
printf("hello");
}
这样反过来写,如果你少写一个等于号,编译器就会直接报错的。
三(二).分支语句switch
switch(整型表达式/整型)
{
//语句项
//一些case语句:
case 整形常量表达式:
语句;
}
这种case语句可以有很多个。举个例子:
int main()
{
int day = 4;
switch (day)
{
case 1:
printf("星期一\n");
case 2:
printf("星期二\n");
case 3:
printf("星期三\n");
case 4:
printf("星期四\n");
case 5:
printf("星期五\n");
case 6:
printf("星期六\n");
case 7:
printf("星期天\n");
}
return 0;
}
这里的意思就是,先看switch后面的整型表达式结果是多少,是1的话就从case 1:后开始执行就是打印星期一,表达式是2就执行case 2:后面的内容打印星期二…但是这样写还少了些东西导致结果和我们希望的不一样。
发现如果day的值是4的话,我们本希望它能打印星期四,但是它把星期五,六,天的都打印出来了。这是因为程序只是把case 4:当成入口,这个程序的出口则是在switch语句里面的这个语句块末尾,因为switch不像if语句那样有判断和执行功能,它只有判断功能。所以我们希望在打印完星期四后就停止,所以加上限制条件:
int main()
{
int day = 4;
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
}
return 0;
}
这里加上break的限制条件。break的意思是程序运行到这里的时候,终止运行,程序会跳出这个程序块,执行switch后面的语句。break就是上面讲的控制语句里的转向语句的其中一种。
小总结一下:
switch语句只有判断功能,没有分支功能,switch只不过是拿着后面的整形表达式来一个一个与后面的case相比较,比较成功了就进去,换句话说switch语句中switch只起到一个类似寻找的功能将switch后面的结果和case一个一个比较,而真正的判断功能是case来实现。但因为switch语句里没有分支功能(只执行某一个语句块的功能),执行到相应case的代码块后会不断继续向下进行直到结束,所以这里需要加break来进行一个分支功能。
但是switch语句还有一个新的语句default语句,这个有什么用呢?假如此时我们的变量day是9:
发现什么都没有输出,但是我们希望输入的数字不是1-7时想要输出一个“输入错误”,这时候就要用到default了。
int main()
{
int day = 9;
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
default:
printf("输入错误\n");
}
return 0;
}
把default加在最后面,意思是上面的case都不是入口的话,就全执行default后面的代码。
这里有一个小建议:
每个switch-case后面都加一个default语句,即使你这个代码不需要它。
现在还有一个小拓展,如果我希望星期一~星期五输出工作日,星期六,日是休息日,其它就是输入错误,该如何改呢?
int main()
{
int day = 3;
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
default:
printf("输入错误\n");
}
return 0;
}
这里有好理解了,如果day=1~5的时候不管从哪个入口进入,都是执行依次printf函数然后退出。
可能会出错的问题:
case后面的语句块不需要加花括号。当然加了也没什么问题。
每个case后面的不是分号而是冒号。
补充(一):
整型表达式:
首先整型是int,short,long,long long,char这些。表达式就是平常经常接触的加减乘除,逻辑运算,移位运算…这些。而整形表达式就是这些表达式运算时类型必须是整型。
上面switch后面跟的是整型或整形表达式。其实大部分都是整型,因为整型表达式的结果还是整型。
整型常量表达式:
限制条件比整形表达式还多一点,不仅要求你是整型,你还必须是常量,如果case后面是个变量就会出问题。
补充(二):
有没有可能会写下面这种代码,就是在case语句里面定义变量?
int main()
{
int day = 9;
switch (day)
{
case 1:
int i = 10;
printf("星期一\n");
printf("星期一\n");
printf("星期一\n");
printf("星期一\n");
printf("%d\n", i);
break;
default:
printf("输入错误\n");
}
return 0;
}
运行一下会发现有报错。
说明case里面本身是不能定义变量的,但如果你非要去定义它也是可以的:
int main()
{
int day = 1;
switch (day)
{
case 1:
//在case和break之间加上括号
{
int i = 10;
printf("星期一\n");
printf("星期一\n");
printf("星期一\n");
printf("星期一\n");
printf("%d\n", i);
}
break;
default:
printf("输入错误\n");
}
return 0;
}
当然本身肯定是不建议这样写的,你需要定义一个变量,完全可以放在外面定义,但是如果非要在里面定义,最后将case里面代码封装成一个函数,然后在调用。像这样:
void show()
{
int i = 10;
printf("星期一\n");
printf("星期一\n");
printf("星期一\n");
printf("星期一\n");
printf("%d\n", i);
}
int main()
{
int day = 1;
switch (day)
{
case 1:
show();
break;
default:
printf("输入错误\n");
}
return 0;
}
补充(三):
default语句一定要放在最后吗?答案不是,你可以把它放在任意位置甚至是第一个case语句上面都是没问题的,不影响你的结果。
补充(四):
不推荐将break换成return,这个随便看看就行吧,一般switch语句都是用break来结束,你非要跟别人与众不同,这不是一个好的编码习惯。
补充(五):
不推荐switch后面的常量表达式写成bool类型的判断:
int a = 0
switch(a == 0)//像这种判断是不推荐的,虽然编译器不会报错
{}
补充(六):
既然case后面跟的需要是一个常量,这个常量可以是const修饰的变量吗?
int main()
{
const int day = 1;
switch (day)
{
case day:
printf("星期一\n");
break;
default:
printf("输入错误\n");
}
return 0;
}
答案是不行的:
这是因为const修饰的变量虽然强制变成了常量,但是它的本质还是变量。
补充(七):
推荐switch-case语句的规范:
- case后面的常量推荐用一定的顺序来写:a,b,c…或者1,2,3…这些。如果匹配的数据不是这些可以尝试用宏,枚举常量替换。
- 推荐将匹配正常的放在前面,匹配异常的放在后面如default.
- 推荐按匹配的频率放在前面,比如case 2:要匹配的频率很大,最后将这个case放在最前面,来提高效率。
上面这些通过不同场景来自行更改。
- 尽量简化每种case后面的内容,如果很多可以尝试用函数封装起来。
- 把每个需要匹配的case都写出来,比如星期一~星期六如果你想偷点懒将星期天这个结果扔给default也是不好的。最好是把每个结果都写出来,将其他默认结果扔给default.
四.循环语句
4.1while语句
while(表达式)
循环语句;
这里的表达式真就会一直执行里面的循环语句,知道表达式的结果变成假才结束。
举个例子:
int main()
{
int i = 5;
while (i--)
{
printf("hello\n");
}
return 0;
}
大概流程是先判断while里面的表达式是否为真发现是5然后5–变成4,然后执行里面的printf语句,执行完之后又回去while那里看是不是真…这样一直循环直到while里面的表的式变成0,也就是假的时候结束。
现在在写一段代码:
int main()
{
int i = 0;
while (i < 10)
{
if (i == 5)
{
break;
}
printf("%d ", i);
i++;
}
return 0;
}
看结果:
发现break在while里面也同样适用,i==5为真的时候就跳出去。
现在我们再来看一个新的语句:continue
int main()
{
int i = 0;
while (i < 10)
{
if (i == 5)
{
continue;
}
printf("%d ", i);
i++;
}
return 0;
}
再看一下这个代码会执行什么效果:
这里不好展示,其实是代码执行到5时,一直卡在这里造成了死循环。continue是代码执行到这里的时候直接返回到最开始的while那里判断,continue后面的代码就不会被执行。注意这里回到的是while判断的那个地方,而不是回到循环内部的第一句。
上面的代码就会导致当i为5的时候,进入if语句走到continue然后跳回到while那里,就这样一直重复造成死循环。所以我们把刚才的代码稍微改一下:
int main()
{
int i = 0;
while (i < 10)
{
i++;
if (i == 5)
{
continue;
}
printf("%d ", i);
}
return 0;
}
把i++移到上面去看看效果:
发现打印的时候直接跳过了5.
上面写的那么多代码就是为了更好的理解continue的用途。
小总结:break和continue
break在循环语句里的作用是跳出循环/跳出当前语句块,在switch语句是跳出switch语句。
continue是遇到这个语句,就是不执行continue后面的内容,而是回到循环最开始的地方也就是判断的地方,重新开始。这里要注意的是break只能在循环语句:while,do while,for和选择语句:switch中使用。
continue只能在循环语句里使用。
4.2do while语句
do while的用法:
do
循环语句;
while(表达式);
这个和while循环大同小异,while语句是先判断如果为真才执行里面语句,do while是什么都不管,先执行一次循环,在去判断while里面的表达式,如果为真就进循环,否则就退出。写个例子:
int main()
{
int i = 0;
do
{
i++;
if (i == 5)
continue;
printf("%d ", i);
} while (i < 10);
return 0;
}
先执行循环,i++然后判断在打印出来,而遇到5的时候和while语句一样跳过,回到while判断部分。所以这个代码打印1-10中除了5的数字。
同理不要搞混了continue执行之后回到的位置:
4.3for语句
for(表达式1; 表达式2; 表达式3)
循环语句;
表达式1:
表达式1为初始化部分,用于初始化循环变量的。
表达式2:
表达式2为条件判断部分,用于判断循环时候终止。
表达式3:
表达式3为调整部分,用于循环条件的调整。
我直接来举个例子:
int main()
{
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", i);
}
return 0;
}
第一部分是初始化变量i,说明循环将从i为0开始判断,后面的流程我用图来表示:
这样写的好处是把调整部分和判断部分放在了一起。不像while那样,调整部分写在循环体内。while里面的内容很多的时候,就很容易把人搞得晕头转向。
同理break,continue在for循环里同样适用,且用法一样。
for循环里面的这三部分,都可以省略不写,但是初学者不建议这样,容易出错。
for循环里面的控制条件也可以不止一个:
int main()
{
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
return 0;
}
}
小补充:
学习上面的while,do-while语句可以知道,里面用continue语句的时候是回到条件判断处也就是while后面括号那里。但是for循环也是一样吗?向下面这个代码:
int main()
{
int i = 0;
for (i = 0; i < 4; i++)
{
printf("continue before : %d\n", i);
if (i == 2)
{
printf("continue\n");
continue;
}
printf("continue after : %d\n", i);
}
}
程序运行到continue后是回到条件判断出:i<4。还是回到i++处呢?当然和while它们一样不会回到循环内部第一句的地方。
假设回到的是i<4的这个地方,但是看看我上面画的那个流程图可以发现回到i<4那个地方之后进行判断,如果为真会继续执行循环内部程序,也就是说这样写会造成一个死循环因为此时的i始终为2,因为没有机会到达i++这个地方。但事实是如此吗?
运行一下发现,没有死循环,正常结束,再仔细看打印continue后继续打印了两行,而且后面的那个数字变成了3,也就是说明在运行到continue后i++了一次,这不就说明了for语句中遇到continue会回到条件更新那个地方而不是条件判断这个地方:
但是如果,你的for循环是这样写的呢?
for(int i = 0; i < 5;)
{
i++;
if(i == 2)
continue;
}
直接说结论,如果for语句后面没有条件更新这个部分,运行到continue会直接执行条件判断也就是i<5这一部分的。
4.4一道简单又不简单的小题目
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
这里最大的坑就是for循环里的判断部分,这里是只有一个=,说明这是个赋值语句,把0赋值给k说明这个语句的结果就是0,为假。所以这个循环一次都不执行就退出来了。
4.5循环总结
循环中除了死循环一般都要包含三种条件:
1.循环初始化
2.循环判定
3.循环更新
int main()
{
int count1 = 10; //循环初始化
while (count1 > 0)//循环判定
{
printf(".");
count1--; //循环更新
}
printf("\n");
// 循环初始化 循环判定 循环更新
for (int count2 = 10; count2 > 0; count2--)
{
printf(".");
}
printf("\n");
int count3 = 10; //循环初始化
do
{
printf(".");
count3--; //循环更新
} while (count3 > 0); // 循环判定
return 0;
}
一般死循环的写法:
int main()
{
while (1)
{
printf(".");
}
for (;;)
{
printf(".");
}
do
{
printf(".");
} while (1);
return 0;
}
4.6循环上的一些小建议
- 如果在写循环嵌套的时候,如果可以尽量把循环次数多的放在内层,如果做不到也没事,就是一个小建议。因为这样可以避免在多层循环中跳转的次数。
- for循环写的时候尽量使用前闭后开区间的写法,向下面这样:
//[0,10)前闭后开区间
for(int i = 0; i < 10; i++)
这样写可以一眼看出来循环体要执行10次。如果是前闭后闭呢?
//[0,9]前闭后闭区间
for(int i = 0; i <= 9; i++)
上面这个虽然也是循环10次,但是观察的时候没有第一种直观。
- 这个了解一下就行,for循环判断的时候尽量不要用浮点型,因为浮点型可能会造成一些精度损失。
五.goto语句
这个语句比较简单:
start:
printf("1");
printf("1");
printf("1");
goto start;
上面start就是一个标签,这个名字由你随意去定,当程序运行到goto start的时候,程序会蹦到start:这个位置继续向下执行,上面这个代码就相当于一个死循环了。
goto语句只要在当前所在的代码块里,不管标签位置在哪都可以蹦过去。但是出了当前的代码块运行就会出错,向下面这个:
void test()
{
start:
printf("goto test");
}
int main()
{
goto start;
return 0;
}
再来看看错误结果:
因为它在一个代码块里哪里都能去,如果用多了可能会因为粗心导致的错误,而且你还很难找到这个错误,同理这样写对代码的可读性也减少了。
所以说尽量少用,下面我随便写一个应用场景:
int main()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
for (int k = 0; k < 10; k++)
{
if (k == 5)
break;
}
}
}
printf("hello\n");
return 0;
}
像这样我希望k为5的时候就跳出循环打印hello,这只加一个break能成功吗?当然不行一个break只能跳出一个for循环,这里要真的跳出去还需要在其它for循环里再加break,但是如果其它循环还有其它代码,这种操作又会变得很危险,所以在跳出多个循环语句的时候goto是给很方便的东西:
int main()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
for (int k = 0; k < 10; k++)
{
if (k == 5)
goto end;
}
}
}
end:
printf("hello\n");
return 0;
}