C语言笔记-分支结构循环结构

《C语言》笔记

4、分支

80~90之间!\n");
case’C’: printf(“你的成绩在70~80之间!\n”);
case’D’: printf(“你的成绩在60~70之间!\n”);
case’F’: printf(“你的成绩在60以下!\n”);
default: printf(“请输入有效的成绩评级\n”) ;
}
return 0;

}
请输入分数:A
你的成绩在90分以上!
你的成绩在80~90之间!
你的成绩在70~80之间!
你的成绩在60~70之间!
你的成绩在60以下!
请输入有效的成绩评级


**思考:为什么会执行我们并不需要的语句?**

**因为switch语句中的case只是一个标签,满足这个标签就跳转到这个标签会执行标签下的语句然后继续*<font color=red>往下执行</font>***,不会跳出语句,所以要加入break!

```c
#include <stdio.h>

int main()
{
	int dj;
	
	printf("请输入分数:");
	scanf("%c", &dj);
	
	switch(dj) 
	{
		case'A': printf("你的成绩在90分以上!\n"); break;
		case'B': printf("你的成绩在80~90之间!\n"); break;
		case'C': printf("你的成绩在70~80之间!\n"); break;
		case'D': printf("你的成绩在60~70之间!\n"); break;
		case'F': printf("你的成绩在60以下!\n"); break;
		default: printf("请输入有效的成绩评级\n") ; break;//这里最后可以不用加,为了保持良好的编程习惯还是要加上
	}
	return 0;	
}

分支结构的嵌套

if(表达式)
	if(表达式)    //内嵌if
		.....
	else
		......
else 
	if(表达式)     //内嵌if
		......
	else
		......
		

根据流程图写代码

流程图是用一些图框来表示各种操作,直观形象 img

在这里插入图片描述

例如上述的判断年龄是否成年程序可以画成类个样儿:判断框左右的“Y”和“N”分别表示表达式的值为“真”和“假”的两种情况。

在这里插入图片描述

再比如上述成绩等级判断程序可以画成类个样子:

在这里插入图片描述

问题:那我用什么工具来画流程图呢?

推荐微软的Visio

练习例子:

在这里插入图片描述

程序代码为:

#include<stdio.h>
int main()
{
    int a,b;
    printf("请输入两个整数:");
    scanf("%d %d",&a,&b);
    if(a!=b)
    {
        if(a>b)
        {
            printf("%d>%d\n",a,b);
        }
        else
        {
            printf("%d<%d\n",a,b);
        }
     
    }
    else
     {
         printf("%d=%d\n",a,b);
     }
    return 0;
}

轻谈bug1 — 悬挂else**

请看一个故事:三班的大成喜欢四班的小石,想约小石周末去万达看电影;这时候有两个问题:那天小石同学有没有空?黄历上那天适不适合出门?

显然第一个问题才是主要的,因为第二个过于迷信,我们要相信科学!

我们把这个故事写成代码:

#include<stdio.h>
int main()
{
    char isFree,isGood;
    printf("是否有空?(Y/N)");
    scanf("%c",&isFree);
    
    getchar();//输入时候出现了回车,第二个输入值就变成了空格!此时需要用getchar();过滤掉回车,否则会出错!
   
    printf("是否适合出门?(Y/N)");
    scanf("%c",&isGood);
    
    if(isFree=='Y')
    	if(isGood=='N')
    		printf("请相信科学!\n");
    else
    {
    	printf("没空大概率是不想理你\n");
	}
    return 0;
}
输出:
是否有空?(Y/N)Y
是否适合出门?(Y/N)Y
没空大概率是不想理你
EMMM明明有空为啥没空呢,bug!

这是因为C语言有一个原则:else与最接近它的if匹配!

C语言不管空格(python空格很重要),不过我们还是要形成良好的编程习惯,加上空格!

解决方法很简单!第一个if 加上大括号就好!所以我们以后只要有if都要加上大括号!

轻谈bug2 — 等于号带来的问题

故事续:我们接下来要判断小石是否喜欢大成?

#include<stdio.h>
int main()
{
    char isLike;
    printf("小石你喜欢大成吗?(Y/N)");
    scanf("%c",&isLike);
       
    if(isLike='Y') //判断表达式的‘=’号是赋值符号,非零值编译器都会默认为真,我们需要改成逻辑符号'=='
   {
   	printf("祝福\n");
   }
    else
    {
    	printf("还是有机会的\n");
	}
    return 0;
}
输出:
小石你喜欢大成吗?(Y/N)N
祝福
EMMM明明不喜欢为啥还祝福呢,bug!

这里比较简单。就是前面if判断表达式的‘=’号是赋值符号,编译器都会默认为真,我们需要改成逻辑符号’==’

5、循环结构

while语句

while(表达式)// 表达式为真则执行循环体里面的内容,循环体可以是单个语句也可以是程序块
	循环体
image-20200812193604192

例子1:计算1+2+3+…+100的结果。

流程图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ec8Cdn8E-1622461797848)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200812194438440.png)]

程序:

#include<stdio.h>
int main()
{
    int i=1,sum=0;
	while(i<=100)
	{
	sum=sum+i;
	i=i+1;	//i++效果一样
	 } 
	printf("结果是:%d",sum);
    return 0;
}
i++ \++i == i=i+1
区别
i++ 返回原来的值,++i 返回加1后的值。
i++ 不能作为左值,而++i 可以。
1、首先,单独拿出来说++i和i++,意思都是一样的,就是i=i+12、如果当做运算符来说,就是a=i++或者a=++i这样的形式。情况就不一样了。
    先说a=i++,这个运算的意思是先把i的值赋予a,然后在执行i=i+1;
    而a=++i,这个的意思是先执行i=i+1,然后在把i的值赋予a;
    举个例子来说,如果一开始i=4。那么执行a=i++这条语句之后,a=4,i=5;那么执行a=++i这条语句之后,i=5,a=5;同理,i----i的用法也是一样的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xRc8mx9m-1622461797848)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200812195251331.png)]

例子2:统计从键盘输入的一行英文句子的字符个数(循环一次,次数加1)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-juk9Jaku-1622461797848)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20200812195803029.png)]

getchar函数

getchar 函数从标准输入流(stdin)中获取下一个字符。

相当于调用 getc(stdin) 函数。

#include <stdio.h>
...
int getchar()(void);

如果函数调用成功,返回获取的字符(用整型表示其 ASCII 码)。

返回值如果是 EOF,表示该函数调用失败:

  • 如果标准输入流位于处于结束的位置,该函数返回 EOF,并设置标准输入流的结束标志符。
  • 如果出现其他错误,该函数同样返回 EOF,并设置错误标志符代替。

程序

#include <stdio.h>

int main()
{
        int count = 0; //初始化为0

        printf("请随意一个英文句子:");

        while (getchar() != '\n') //只要不是回车就不是结束,直到回车(换行)停止循环
        {
                count = count + 1;
        }

        printf("你总共输入了%d个字符!\n", count);

        return 0;
}
输出:
请随意一个英文句子:I LOVE YOU
你总共输入了10个字符!
//空格也算字符

do …while 语句

do
	循环体
while(表达式);

如果我们把 while 语句比喻为一个谨慎的小伙子的话,那么 do…while 语句就是一个莽撞的汉子。

因为 while 是先判断表达式,如果表达式结果为真,才执行循环体里边的内容;

而 do…while 则相反,不管三七二十一,先执行循环体的内容再判断表达式是否为真。

注意:do…while 语句在 while 后边一定要用分号(;)表示语句结束。

img

可以看出当我们需要验证密码正确时候,是有do…whlie语句只需要写一次输入密码即可

image-20200812201102932image-20200812201102932

#include<stdio.h>
int main()
{
    int i=1,sum=0;
	do
	{
	sum=sum+i;
	i=i+1;	//i++效果一样
	 } 
	while(i<=100);
	printf("结果是:%d",sum);
    return 0;
}

while语句在入口处判断表达式,因此成为入口条件循环;do…while语句在出口处判断表达式,因此成为出口条件循环;索引无论表达式是否成立,do…while循环体都会被循环一次

循环体的基本结构
int count=0;//初始化计数器
while(count<10)//循环条件
{
	printf("xxxx\n");
	count=count+1;  //count++;  更新计数器
}

这三个动作是分散在不同的部分的,若是可以在同个地方集中就好了,于是乎我们就有了 for循环

for循环语句

for(表达式1;表达式2;表达式3)
    /*表达式1是循环初始化表达式; 表达式2是循环判断表达式;表达式3是循环调整表达式*/
	循环体
#include<stdio.h>
int main()
{
	int i,sum;
    for(i=1,sum=0;i<=100;i++)//表达式中有两个式子则用逗号隔开
    {
    	sum=sum+i;
	}	
	printf("结果是:%d",sum);
    return 0;
}

练习例子:判断一个数是否是素数。(素数是在大于1的自然数中,除去1和本身无法被其他自然数整除的数)

#include<stdio.h>
int main()
{
	int i,num; 
	_Bool flag=1;//使用布尔类型判断是否可以被除去1和本身的数整除
	printf("请输入一个整数:");
	scanf("%d",&num); 
    for(i=2;i<=num/2;i++) // 这里num/2就可以了 
    {
    	if(num%i==0)
    	{
    		flag=0;	//若是可以被整除则赋值为0			
		}
	}
	if(flag)//这里表示为1 则不能被整除,所以是素数 
	{
		printf("%d是素数\n",num);
		}	
	else{
		printf("%d不是素数\n",num);
	}
    return 0;
}
灵活的for语句

表达式1,表达式2,表达式3可以按照需要进行省略(分号不能省)

for(表达式1;表达式2;表达式3)
for(;表达式2;表达式3)
for(表达式1;;表达式3)
for(;;表达式3)
for(;;)//代表永远为真的循环。死循环
.........
循环嵌套

先执行内循环再执行外循环

#include<stdio.h>
int main()
{
	int i,j;
    for(i=0;i<3;i++)
    {
    	for(j=0;j<3;j++)
    	{
    		printf("i=%d,j=%d\n",i,j);
		}
	}	
    return 0;
}
输出:
i=0,j=0
i=0,j=1
i=0,j=2
i=1,j=0
i=1,j=1
i=1,j=2
i=2,j=0
i=2,j=1
i=2,j=2

练习例子,打印九九乘法表

#include<stdio.h>
int main()
{
	int i,j;
    for(i=1;i<=9;i++)
    {
    	for(j=1;j<=i;j++)
    	{
    		printf("%d*%d=%-2d  ",i,j,i*j);//%-2d表示按照两位数的形式左对齐,要右对齐就是%2d
		}
		putchar('\n');//内层循环决定行,要换行 
	}	
    return 0;
}
输出:
1*1=1
2*1=2   2*2=4
3*1=3   3*2=6   3*3=9
4*1=4   4*2=8   4*3=12  4*4=16
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81

break语句

跳出循环

#include<stdio.h>
int main()
{
	long long i,num;//测试比较大的数,使用long long 
	_Bool flag=1;
	printf("请输入一个整数:");
	scanf("%d",&num); 
    for(i=2;i<=num/2;i++) // 这里num/2就可以了 
    {
    	if(num%i==0)
    	{
    		flag=0;	//若是可以被整除则赋值为0	
			break;	//只要是能被2整除就一定不是素数了,所以跳出循环	
		}
	}
	if(flag)//这里表示为1 则不能被整除,所以是素数 
	{
		printf("%lld是素数\n",num);//longlong对应的是%lld
		}	
	else{
		printf("%lld不是素数\n",num);
	}
    printf("i=%lld\n",i);//查看循环的计数
    return 0;
}
请输入一个整数:100000000
100000000不是素数
速度会比原来快很多(因为现在cpu太好了,看不太出来差别)
continue语句

当满足某个条件的时候,跳出本轮循环进入下一个循环

而break是跳出整个循环!

#include<stdio.h>
int main()
{
	int ch;
	while((ch=getchar())!='\n')//判断输入,直到输入换行时候循环结束
	{
		if(ch=='C')//忽略用户输入带有C的字符 
		{
			continue;
		}
		putchar(ch);//若是带有C,本操作不执行,直接进入下一次循环 ,获取下一个字符 
	}
	putchar('\n');

    return 0;
}
输出
I LOVE CAT AND DOG
I LOVE AT AND DOG
#include<stdio.h>
int main()
{
	int i;
	for(i=0;i<100;i++)
	{
		if(i%2)//若是不能被2整除(非零)则跳出本次循环
		{
			continue;
		}
		printf("%d\n",i);//最终得到所有被0~100能2整除的数
	 } 

    return 0;
}

上述例子改为while循环

#include<stdio.h>
int main()
{
	int i=-1;//因为程序一开始i加1所以从-1开始
	while(i<100)
	{
		i++;//必须放在if前面,若是放在if里面1%2非0则不再执行+1操作,程序陷入死循环
		if(i%2)
		{		
			continue;
		}
	printf("%d\n",i); 
	}				
    return 0;
}

可以看出for和while是不一样的!

6、知识点补漏

赋值运算符“=”

.....
int a;
....
a=5;//赋值运算符的左边必须是一个lvalue,变量名就是lvalue
.....

lvalue(左值)

lvalue 这个名字最初确实来自于 E1 = E2(E1 就是那个可改变的左值)。但更合理的解释应该是将 lvalue 理解为 locator value(特定位置的值),rvalue 则应该是 value of an expression(表达式的值)。

所以,单纯用左边(left-value)和右边(right-value)来理解是不全面的。

lvalue 是用于识别或定位存储位置的标识符

#include <stdio.h>
int main()
{
        int a = 5;
        ++(a++);
        return 0;
}
代码出错,bug!

(a++) 是先将变量 a 的值(5)做为整个表达式的值返回,再将 a 自增 1(类似于 a = a + 1)。

所以这里 ++(a++); 相当于 ++(5), a = a + 1;

那当然要报错啦,5 是一个常量,当然不能给你 5 = 5 + 1 咯~

复合的运算符

a += 1;     a=a+1
a -= 2;		a=a-2
a += 3;		a=a+3
a /= 4;		a=a/4
a %= 5;		a=a%5
自增自减运算符

当我们需要对一个变量加一或减一并赋值给自己的时候,我们可以写成 i++、i— 或 ++i、–i 的形式。

它们也被称为增量减量运算符,或 ++、-- 运算符。

它们的区别是:

  • i++ 是先使用变量 i 中保存的值,再对自身进行 ++ 运算;
  • ++i 是先对自身进行 ++ 运算,再使用变量 i 的值(这时候变量i的值已经加 1 了)。

另外,自增、自减运算符只能作用于变量,而不能作用于常量或表示。

#include<stdio.h>
int main()
{
	int i=5,j;
	j=i++;//先把i的值5赋值给j,i自身再加1
	printf("i=%d,j=%d\n",i,j);
	
	i=5;
	j=++i;//先把i的值加1变成6,再加1
	printf("i=%d,j=%d\n",i,j);				
    return 0;
}
输出
i=6,j=5
i=6,j=6

逗号运算符

逗号表达式的语法是:表达式1,表达式2,表达式3,… ,表达式n

  • 逗号表达式的运算过程为:从左往右逐个计算表达式
  • 逗号表达式作为一个整体,它的值为最后一个表达式(也即表达式n)的值。

不过,逗号运算符在C语言的所有运算符中,是最没有地位的那个。

因为连赋值运算符的优先级都比逗号运算符要高,所以……

a = 3, 5/*相当于*/
a=35

例子分析

a=(b=3,(c=b+4)+5)
/*先将变量b赋值为3;
然后变量c赋值为b+4的和,即7;
接下来把c的值+5;
最后赋值给a,所以a的值为12*/

注意:在 C 语言中看到的逗号,不一定就都是逗号运算符,因为在有些地方,逗号仅仅是被用作分隔符而已。

int a, b, c; 
scanf("%d%d%d", &a, &b, &c); 
/* 这里逗号都是作为分隔符使用,而不是运算符。  */

条件运算符

有一个操作数的运算符称为单目运算符,有两个两个操作数称为双目运算符,然而 C 语言还有唯一的一个三目运算符,它的作用是提供一种简写的方式来表示 if-else 语句。

语法:exp1 ? exp2 : exp3;

exp1 是条件表达式,如果结果为真,返回 exp2,如果为假,返回 exp3

if (a > b)
{
    max = a;
}
else
{
    max = b;
}
/*相当于*/
max = a > b ? a : b;

goto 语句**

goto 语句可以说是一个历史遗留,因为早的编程语言都留有很多汇编语言的痕迹,比如 goto 语句就是其中之一。

goto 语句的作用就是直接跳转到指定标签的位置。

语法:goto 标签;

其中标签需要被定位于某个语句的前边,比如:

#include <stdio.h>
int main()
{
        int i = 5;
        while (i++)
        {
                if (i > 10)
                {
                        goto Label;//当i>10的时候跳出循环,跳到Label的地方
                }
        }
Label:  printf("Here, i = %d\n", i);
        return 0;
}

重要:开发中要尽量避免使用 goto 语句。 其实就连 C 语言的作者也觉得 goto 语句非常容易被滥用,并且建议一定要谨慎使用,甚至根本不用它。

但在一种情况下使用 goto 语句是情有可原的,那就是当面临要跳出多层循环的时候,使用 goto 语句要比多个 break 语句好使。

注释

C 语言的注释有两种方式,一种是大家常用的,将注释写在两个连续斜杠的后边:

// 这是注释,编译器不会理会

/*  这是注释
	适用于多行*/

,不一定就都是逗号运算符,因为在有些地方,逗号仅仅是被用作分隔符而已。**

int a, b, c; 
scanf("%d%d%d", &a, &b, &c); 
/* 这里逗号都是作为分隔符使用,而不是运算符。  */

条件运算符

有一个操作数的运算符称为单目运算符,有两个两个操作数称为双目运算符,然而 C 语言还有唯一的一个三目运算符,它的作用是提供一种简写的方式来表示 if-else 语句。

语法:exp1 ? exp2 : exp3;

exp1 是条件表达式,如果结果为真,返回 exp2,如果为假,返回 exp3

if (a > b)
{
    max = a;
}
else
{
    max = b;
}
/*相当于*/
max = a > b ? a : b;

goto 语句**

goto 语句可以说是一个历史遗留,因为早的编程语言都留有很多汇编语言的痕迹,比如 goto 语句就是其中之一。

goto 语句的作用就是直接跳转到指定标签的位置。

语法:goto 标签;

其中标签需要被定位于某个语句的前边,比如:

#include <stdio.h>
int main()
{
        int i = 5;
        while (i++)
        {
                if (i > 10)
                {
                        goto Label;//当i>10的时候跳出循环,跳到Label的地方
                }
        }
Label:  printf("Here, i = %d\n", i);
        return 0;
}

重要:开发中要尽量避免使用 goto 语句。 其实就连 C 语言的作者也觉得 goto 语句非常容易被滥用,并且建议一定要谨慎使用,甚至根本不用它。

但在一种情况下使用 goto 语句是情有可原的,那就是当面临要跳出多层循环的时候,使用 goto 语句要比多个 break 语句好使。

注释

C 语言的注释有两种方式,一种是大家常用的,将注释写在两个连续斜杠的后边:

// 这是注释,编译器不会理会

/*  这是注释
	适用于多行*/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小邹子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值