C# ( 初级 ) 第一章 —— 分支与循环

章节摘要:C语言中有着许多的算法逻辑和思想,它们总是再不断更新和完善,本章节重点介绍C语言算法逻辑中,最为基础也最核心的算法之二,我将以C语言语句的角度去介绍它们:C语言的分支语句,C语言的循环语句

在正式开始之前,需要介绍什么是C语言的语句。

语句,通常指代一些携带信息的信号,用于传达或记录其中的信息,语句中的信息可以是携带对某种事物的表述,也可以是某种既定的指令,也可以是情感的表达等。C语言中的语句,更多指代在人与计算机的语言交互中,人类主观向计算机下达的指令,实际上,就连计算机应对指令所传达的信息,也都是人为主观用一系列指令规定的。可以说,语句基本是人机交互的行为支撑。

C语言常识补充:

1,C语言拥有三大语言结构

I; 顺序结构

II; 选择结构

III; 循环结构

2,C语言语句以分号 ( ; ) 结束。

3,C语言逻辑 或 与 非

逻辑或 —— || 或者

逻辑与 —— && 并且

逻辑非 —— ! 非

4,C语言中的真与假

0 —— 假

!0 —— 真

只要不是0,就是真,C语言的真假明显,真就是真,不真就是假。

C语言中虽然规定只要不是 0 就是真,但是默认 真 都是 1 

return,返回,满足返回条件以后就结束语句,程序不会往下执行,会直接跳出所在函数,如果不满足,才往下继续,实际上关于 return 返回的逻辑,涉及到 函数栈帧的创建与销毁

关于 函数栈帧的创建与销毁 将会在后续内容进行介绍

else,其他分支,else 拥有一定对应原则,在程序的编译中,理清分支归属很重要

 else 的对应原则,服从就近原则,对应到与之最近的一个 if 或 if else。

第一节,分支语句

C语言中的分支语句,包含 if 语句,switch 语句。

两者基本都满足成立条件就能指令该分支下的语句,主要区别在于它们的服务对象,当需要考虑的情况复杂多样,采用 if语句 将是效率低下的,尽管可以使用 else 来扩充分支,也很难实质的提示效率,此时 switch 就会非常合适,只需要一套全面的判断逻辑,就能重复去选择,从语句效率和篇幅的角度来说 switch 语句更适合处理复杂多变的情况。而当需要处理的情况很少,使用 if 则会更加直接方面快捷。

1.1 if 语句

if ,中文直译就是 " 如果 ",if 语句 包含两类,  if  和 else if

else if 实际上就是 一个额外分支, 根据需要考虑的情况可以适当增加 else if 分支, 但是当条件过多时,应当着重考虑 使用 switch 语句。

下面给出 :if 语句基本框架 


if( 成立条件1 )

//当条件成立才会执行这些
{
语句列表
}

//当上述条件不被满足
else if( 成立条件2 )
{
语句列表
}

//当所有预设条件不被满足

else                           //其实这个 else 可以不写,这里只是为了强调它们的对应关系
{
语句列表
}

下面给出一个十分简单的小例子,该例子稍微结合了 分支语句 中的 if , 循环语句中的 for

循环语句 for :满足条件会持续循环语句列表,后续会介绍

 eg 1.1 : 打印并统计 1 - 100 之间的奇数情况

#include<stdio.h>
int main()
{
    int num = 0;
    int count = 0;
    for (num = 0; num <= 100; num++)
    {
        if (1 == num % 2)                 // num % 2,当num为偶数,将会得0 
        {                                 // 99 % 9 = 0, 99 / 9 = 11
            count++;
            printf(" %-3d", num);
            if (0 == count % 10)
            {
                printf("\n");             //每打印 10 个奇数,换行
            }

        }
    }
    printf("1-100的奇数有 %d 个\n", count);

    return 0;
}

输出结果展示:

小小tips:

1,在编译过程中,声明变量的时候,最好顺便初始化它们,实际上如果不影响程序,初始化为任意合适的量都行,但最好统一初始化为0,当然不一定0总是最合适的。

2,在对 if 的语句成立条件进行编译时,推荐采用 上文的形式, 这样做虽然只是一个很小的优化习惯,却能很好避免成立条件编译时出现一些认为的操作失误。

以上就是对 if 语句的一个基本介绍,本章重点在于介绍 它们的基本信息和基本使用,并不深入探讨它们在实际效用中的一些注意事项

1.2 switch 语句

当需要判断的条件太多时,使用 if else 语句编写将会过于冗杂,可采用 switch 语句来进行编写,以满足更大更多的选项

switch 语句基本框架


switch(变量)
{

case 1:
     语句列表
break;
    case 2:
         语句列表
    break;
...
...
...
        case n:
             语句列表
        break;
//当所有入口条件都不悲满足,就可以加上 default 语句。
default:
     语句列表
break;

}

其中 case x, 表示 箱入口x : 把程序中的变量从这个入口引入使用

注;一旦从某一个窗口引入使用后,如果后面没有break语句来从箱中引出,则会继续往下一个箱入口引入。也就是说,程序本箱会继续从下一个入口在进入下一个箱

可以这样来理解: 整一个 stitch 就像一个仓库,每一个case,相当于一个房间,假设程序需要使用这个仓库,那么当满足case,就进入这个房间,当这个房间中有break,则程序直接退出仓库,如果这个房间中有continue,则继续前往下一个房间。

注;只能前往去过房间的下一个房间。

我绘制了switch的参考图,如下:

图解说明;设定了case 1 2 3 4.

case 1 含有break,程序满足case 1 之后直接跳出仓库。

case 2 含有 continue , 程序 满足 acse 2 之后会进入 case 3中,然后因为case 3 中没有break或continue,将会继续进入 case 4.

case 3 不含有 break 或 continue,程序满足 case 3 之后进入空白房间,然后进入 case 4 ,最后再通过 case 4 的空白房间退出

case 4 不含有 break 或 continue, 程序满足 case 4 之后 将会直接跳出

如果 1 ~ 4 都不被满足,程序将会进入 defalut ,直接跳出仓库

其中 break, 表示 箱出口 : 把程序中的变量从引入的箱中引出,跳出分支选择。

其中 default,表示 不满足: 把程序中的变量引入使用

在这里再简单举例一个 switch 小小例子

eg1.2 :键盘输入停车位,选择车辆

#include<stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
switch (a)
   {
   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;
                     default:
                        printf("没有对应车辆\n");
                     break;
               }
}
return0;

当输入的数字是1-6的时候,可以正常输出对应车辆,输入其他的字符或数字将会不显示。

如果把所有的 break 去掉,那么 ,当输入 1 的时候,就会把1-7的车辆都输出,当输入 3 的时候,就会把3-7的车辆都输出,一此类瑞。当输入的字符或者数字不是1-7,将会显示 “没有对应车辆”

注意,case 后的表达式,只能是整形常量表达式。类似于 1.0,2.5等都不行

可以将多个入口并入一个语句列表

swtich中的break不是必须添加,如果想要多个入口条件都指向一个出口,就可以只用一个出口,也可以没有出口,但是这样意义不大default后面也不是必须加上 break。default写在 swtich中的任意位置都是可行的,加不加break都不影响程序正常运行。

只是说,break语句为该分支语句带来了出口,当满足对应的出口条件,程序就能跳出该分支语句。没有break语句程序就会找到从对应入口进入并且走完整个分支语句,如果没有对应入口,则会跳过全部分支语句

注; switch 可以嵌套使用,一个switch语句中可以在嵌套一个或多个switch

小tips:当全局变量有不止一个的时候,应当明确每一个switch的判断变量,哪一个变量用于哪一个分支条件,要明确清晰。同样,哪一个入口的出口break也要判断清楚

第二节:循环语句

C语言中,给循环语句提供了三种循环模式,分别是:

I : while 循环

II : do while 循环

III : for 循环

这三类循环的基本逻辑都是满足条件就会重复执行语句,这意味着,如果没有适当的去设置终止条件,会使得程序进入死循环。

2.1 while 循环

while,中文直译就是 “ 当 ”,也就是循环语句判断条件

下面给出 while 语句基本框架

while (条件)

{

    语句列表

}

下面将以一个简单的小例子,来简单的探讨一下:

关于 while 循环, break , continue 之间的一些联系。

eg2.1 将 1 - 100 之间的 偶数打印出来

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    int a = 1;
    int count = 0;
    while (a <= 100)
    {
        if (0 == a % 2) 
        {
        printf(" %d\n", a);
        count++;
        }
    a++;
    }
printf("1-100中的偶数个数为 %d", count);
return 0;
}

 输出结果如下:

同样的,类似于 1.1中的 switch语句, break也可以用于 while语句,作用也是跳出,如上图想要输出1-77之间的偶数,并且只统计1-77的偶数个数,就可以用到break

只需要在if里面再次嵌套 if就行

如下面程序,设定当 a >= 77 就会跳出结束循环

#include<stdio.h>
int main()
{
    int a = 1;
    int count = 0;
    while (a <= 100)
    {
        if (0 == a % 2)
        {
            printf(" %d ", a);
            count++;
        }
        a++;
        if (0 == count % 10)
        {
            printf("\n");
        }
        if (a >= 77)
            break;
    }
    printf("\n1-77中的偶数个数为 %d", count);
    return 0;
}

输出结果如下

将上面程序中的 

break;  改成 continue:

  
      if( a >= 77 )
        {
            break;
        }
//替换为
      if (a >= 77)
        {
            continue;
            printf(" continue 没有跳过这一步!\n");
        }

,会得到结果

可见,在while循环中,break的作用是跳出循环,永远终止循环,但是在switch中不会结束全部程序。相比于 break 结束循环, continue 则是结束循环的某一次,然后回到循环的判断,继续剩下次数的循环(例如上述程序需要执行38次循环),而且continue会跳过该次循环剩下的语句,才进入下一次循环

getchar

下面是一些关于 getchar 的小介绍

getchar —— 获取一个字符 —— getchar的返回值是 int 整形

int a = getchar ();—— 获取一个字符,并以整形方式赋值给a

getchar 获取字符的方式 :

方式 1 : 从一个文件内获取 方式 2 : 从键盘输入一个

putchar —— 输出一个字符

putchar(a) —— 输出一个字符a

EOF —— end of file —— 文件结束标志 —— EOF = -1

Ctrl + Z —— 让getchar读取到 EOF,从而结束读取,有些编译软件上面是 Ctrl + C

在getchar读取的时候,会在 getchar 与 键盘之间出现一个缓冲区,从键盘输入字符后,通过回车 Enter ,将这个输入的字符放到缓冲区里面,并在后面加上一个 \n。而getchar在读取的时候,会先读取字符A,之后再回来读取 \n,这样在输入下一个字符之前,输入的上一个字符就已经输出并且换行

getchar 还可以起到清理缓冲区,让程序重新进入等待的功能。

当之前输入了一些字符串的时候,会产生 字符串+\n,字符串被使用后,还剩下\n留在缓冲区,此时程序会再次读取\n,从而不会等待下一步操作。如果在操作语句之后单独加上一句

getchar();

就可以把缓冲区的\n也一并清除掉,这样程序再次读取缓冲区的时候,由于没有东西,就会进入等待。

如果需要清理的东西太多,一个 getchar 清理不完,则可以借助while循环语句或者其他循环语句来清除

方式如下:

int tmp = 0;

while((tmp = getchar()) != '\n' )

{

;

}

如此,就可以优先把所有缓冲区里面的东西都清除掉

2.2  for 循环

for循环语句基本框架

for( 表达式1 ; 表达式2 ; 表达式3 )
{

    循环语句;
}

其中 表达式1     的作用是     初始化

        表达式2     的作用是     判断

        表达式3     的作用是     调整

举例 :

int a = 0;

for ( a = 1; a <= 10; a += 2)

{

        printf("%d",a);

}

这个程序先定义  a = 0  为初始值,在for循环里面,第一次循环时把a的值  初始化  为 a = 1,然后判断 a 是否满足 <= 10 , 如果满足,就进入进入循环,执行 打印 。然后再回到 调整,执行 a += 2 (把a+2 再次赋值给a)。此hi结束第一次循环,之后程序由回到for循环的初始化环节,开启第二次循环,以此类推,一直执行到 判断 a 时,结束for循环。并且把每一次循环得到的a值(是每一次循环中 a 被初始化以后的值)打印出来。

所以上述简单程序将会打印输出 1 3 5 7 9

如果在上述程序中加入一个 continue

int a = 0;
for (a = 1; a <= 10; a += 2)
{
    if (5 == a)
    {
        continue;
    }
    printf("%d", a);
}

输出结果就变为了 1 3 7 9,可以发现,当 a=5的时候,满足if条件,continue跳出本次循环,不执行printf打印操作,因此a = 5并没有被打印输出,但是for循环并没有被i终止,程序会回到本次循环的调整环节,此时 a = 7。所以在下一次循环的判断环节之前,a的值就已经被初始化为 a = 7.

综上可以发现,在for语句中,每次循环有三个环节,continue 作用于 判断环节,而且跳出循环时,也只是跳过了该环节的操作,程序跳过该环节以后,还是会在同一次循环中进入下一个环节,即调整环节

for( ; ; ) 的时候,程序进入死循环,因外当判断环节被省略,那么程序每次进入判断环节的时候,恒定判断为真(省略/空,默认为真),故而一直循环下去

当for循环只省略初始化环节的时候,程序采用全局变量中的初始值来进入循环,由于没有进行初始化,变量的值将会保持最后一次循环中的调整环节调整的值

2.3  do while 循环

和 while 循环的区别在于, do while 循环是先编译循环内容,再编译循环条件,并不会说是 do while 会先执行一次循环在判断是否执行下一次循环

do while 语句 基本框架

do

{

    循环语句

} while (成立条件)

do while 循环 的逻辑与 while 循环基本一致。

二分查找

利用 while 循环来实现一个C语言中的查找算法: 二分查找

二分查找,又名折半查找,旨每次都选取中间的数据与被查找的数据进行比较,根据情况向小或者大的方向去减半,直到找到 数据 或者 不满足循环条件结束循环。

二分查找基本框架

int left = 0; —— 定义左端位置,数组起始位置

int right = sz - 1; —— 定义右端位置,数组末尾位置 ———— 解释 3

while( left < right ) ———— 解释 1

{

    int mid = ( left + right ) / 2; —— 定义中间位置

    if ( arr[mid] < k ) —— 假设需要查找的元素是k

    {

        left = mid + 1;

    }

    else if ( arr[mid] > k )

    {
    
        right = mid - 1;

    }

    else

    {

        printf("找到了,位置为%d", mid);

        break;

    }

}

if( left > right) ———— 解释2

printf("没有发现目标")

}

代码解释:

解释1 ;

设定左端位置小于等于右端,是因为程序识别数组元素是从左到右(从0开始),而二分查找的时候,在确定中点位置以后,需要进行元素比较,以确定端点移动方向,从而,左右端点像目标区域靠拢,相向而行。


解释2 ;

在左右端点相向而行的时候,如果目标元素存在于被查找数组,则会在两端点相遇的时候最终确定出目标元素的确切位置,但是一旦两端点在循环的时候穿过了对方,就表明该数组中没有目标元素


解释3 ;

设定右端为 sz - 1,是因为数组的位置从0开始计,n个元素的数组,元素位置为 0 ~ n-1. 而 sz , 就是数组的元素个数,即为 数组大小 比上 数组单个元素大小

sc = sizeof ( arr ) / sizeof ( arr [0] )

至此,关于 C语言初步的  分支与循环 就暂告一段落。

  • 38
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值