c语言学习 (二)分支和循环和getchar的使用注意

目录

二、分值语句和循环语句

1.什么是语句

2.分支语句(选择结构)

2.1 if

if练习

2.2 switch

switch练习

3.循环语句

3.1 while

3.1.1break介绍

3.1.2 continue介绍

我们在这补充两点知识:EOF和getchar()(很重要!缓冲区问题)、putchar()

3.2 for

3.3 do while


前言:c语言是一门结构化的程序设计语言

1.顺序结构、2.选择结构、3.循环结构

我们生活中所有的情况也就这三种

二、分值语句和循环语句

本章我们重点学习分值语句和循环语句

1.什么是语句

c语言中由一个分号,隔开的就是一条语句。比如:

printf("hello");

1 + 2;

2.分支语句(选择结构)

2.1 if

语法结构:

if(表达式)

        语句;

---------------------------------------------------------------------------------------------------------------------------------

if(表达式)

        语句1;

else //默认if中的表达式的补集

        语句2;

---------------------------------------------------------------------------------------------------------------------------------

// 多分支

if(表达式1)

        语句1;

else if((表达式2)

        语句2;

...

else //默认表达式1 U 表达式2 U 表达式3 U ...的补集

        语句n;

解释一下,如果表达式的结果为,则语句执行。

在c语言中如何表示真假?

0表示假,非0表示真。

如果条件成立,要执行多条语句,应该使用代码块。

#include<stdio.h>
int main()
{
    if(表达式)
    {
        //语句列表1;
    
    }
    else
    {
        //语句列表2;
    
    }
    return 0;
}

这里的一对{}就是一个代码块。

如果不加{},则if只能跟后面第一个分号之前的语句保持关联.

如果没有代码块,else只能匹配离自己最近的未匹配的if

注意:if条件判断相等时,注意是用==而不是=;

if练习

输出1-100之间的所有奇数。

#include<stdio.h>

int main()
{
    int i = 0;
    while (i <= 100)
    {
        if (i % 2 == 1)
            printf("%d ", i);
        i++;
    }
    return 0;
}

2.2 switch

switch语句也是一种分值语句。常常用于多分支的情况。

比如:

输入1,输出星期一

输入2,输出星期二

输入3,输出星期三

输入4,输出星期四

输入5,输出星期五

输入6,输出星期六

输入7,输出星期七

如果我们写成if...else的形式程序太冗杂了,我们就需要简单的语法,switch语句

switch(整形表达式)

{

        语句项;

}

语句项是什么?

是一些case语句:

如下:

case 整型常量表达式:

        语句;

我们用代码来表示一下:

#include<stdio.h>

int main()
{
    int day = 0;
    scanf("%d", &day);
	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");
		break;
	}
    return 0;
}

 我们day输出几,就会从case几进入,大家可以想想如果没有break会输出什么?

没有break的话,从case进入后,会从case几后的语句进行顺序输出

如:我们一周只区分工作日和休息日

#include<stdio.h>

int main()
{
    int day = 0;
    scanf("%d", &day);
	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");
		break;
	}
    return 0;
}

 default 子句(default 相当于if语句中的最后的else。)

如果表达的值为所有的case标签的值都不匹配怎么办?

其实没事,结果就是所有的语句都被跳过。

程序并不会终止,也不会报错,因为这种情况在c中并不认为适合错误。

但是,如果你并不想忽略不匹配所有标签的表达式的值时,

你可以在语句列表中加一条default子句,把下面的标签

default:

写在任何一个case标签可以出现的位置,当switch表达式的值不匹配所有case标签的值时,这个default子句后面的语句就会执行

编程好习惯

每一个switch语句都放一条default子句是好习惯。

switch练习

#include<stdio.h>

int main()
{
    int n = 1;
    int m = 2;
	switch (n)
	{
	case 1:
		m++;
	case 2:
		n++;
	case 3:
		switch (n)
		{
			//switch允许嵌套shiy
		case 1:
			n++;
		case 2:
			m++; 
			n++; 
			break;
		default:
			break;
		}
	case 4:
		m++;
		break;
	default:
		break;
	}
	printf("m = %d, n = %d\n", m, n);
    return 0;
}

思考一下m和n都是几?? 

3.循环语句

3.1 while

我们已经掌握了if语句

if(条件)

        语句;

当条件妈祖的情况下,if语句后的语句执行,否则不执行,但是这个语句只能执行一次。

但是,我们生活中很多例子是:一件事需要做很多次。

c语言给我们引入了循环语句,其中while语句,可以实现循环。

while语法结构

while(表达式)

        循环语句;

比如我们实现:

在屏幕实现打印1~10的数字

#include<stdio.h>

int main()
{
    int i = 1;
    while (i <= 10)
    {
        printf("%d ", i);
        i++;
    }
    return 0;
}

这个代码已经帮我们了解了while语句的基本语法,下面我们了解一下

while语句中的break和continue

3.1.1break介绍

#include<stdio.h>

int main()
{
    int i = 1;
    while (i <= 10)
    {
        if (i == 5)
            break;
        printf("%d ", i);
        i++;
    }
    return 0;
}

这里代码输出1 2 3 4 

总结:break在while循环中的作用

        其实在循环中子要遇到break,就停止后面的所有操作,之间跳出循环,所有break是用于终止循环的。

3.1.2 continue介绍

#include<stdio.h>

int main()
{
    int i = 1;
    while (i <= 10)
    {
        if (i == 5)
            continue;
        printf("%d ", i);
        i++;
    }
    return 0;
}
    

 这里代码输出结果是什么?

输出 1 2 3 4 后,变成死循环

那我们改变一下,我们把while循环写成这样

#include<stdio.h>

int main()
{
    int i = 1;
    while (i <= 10)
    {
        i++;
        if (i == 5)
            continue;
        printf("%d ", i);
    }
    return 0;
}

我们的输出结果为:1 2 3 4 6 7 8 9 10

我们跳过了输出5的情况 

总结:continue在while循环中的作用就是:

continue适用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分,进行下一次循环的入口判断。

我们在这补充两点知识:EOF和getchar()(很重要!缓冲区问题)、putchar()

getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了,第一次调用getchar()时,确实需要人工的输入,但是如果你输了多个字符,以后的getchar()再执行时就会直接从缓冲区中读取了。返回值是char强制转换为int的形式返回读取的字符。

putchar()是输出字符

EOF-end of file值为-1,怎么打出来EOF呢,我们摁住CTRL+z就行了

大家可以拿这个代码测试一下EOF

#include<stdio.h>

int main()
{
    int ch = 0;
    while ((ch = getchar()) != EOF) 
    {                          
        putchar(ch);
    }
    return 0;
}

我们主要讲的是getchar() 

getchar有一个int型的返回值。当程序调用getchar时.程序就等着用户按键。用户输入的字符被存放在键盘缓冲区中。直到用户按回车为止(回车字符也放在缓冲区中)。什么意思呢,我们举个例子

#include<stdio.h>

int main()
{
    int ret = 0;
    char password[20] = { 0 };
    printf("请输入密码:");
    scanf("%s", password);
    printf("请确认(Y/N)");
    ret = getchar();
    if (ret == 'Y')
        printf("确认成功\n");
    else
        printf("放弃确认\n");
    return 0;
}

这里的输出结果就出现了问题 

当我们输完密码后,我们还没有输出字符就直接放弃确认了。 为什么会这样呢?

那这个'\n'是哪里来的,其实是我们输入密码时的回车进了缓冲区,在我们ret接受getchar()数据时'\n'直接从缓冲区给了getchar(),导致直接输出放弃确认。

 那我们应该怎么解决呢?

如果我们在使用getchar()的时候让缓冲区为空getchar()是不是就可以等待我们输入了。

我们从前面的例子找到灵感,我们在给ret赋值之前,先一步使用getchar()清空缓冲区的数据不就直接解决了吗。代码如下:

#include<stdio.h>

int main()
{
    int ret = 0;
    char password[20] = { 0 };
    printf("请输入密码:");
    scanf("%s", password);
    //缓冲区还有给'\n';
    getchar();
    printf("请确认(Y/N)");
    ret = getchar();
    if (ret == 'Y')
        printf("确认成功\n");
    else
        printf("放弃确认\n");
    return 0;
}

这时我们输入完密码后,就可以正常输入了。 

还有一点是scanf中要输入%s的话,空格和回车都会导致输入结束

如果我们用上个例子,我们输入的密码是123456 ABAA,这时,scanf中的%s只能接受到空格前面的123456,而后面的空格和ABCD则进入了缓冲区,而后面的getchar()这个缓冲区清理只读了一个空格也就结束了,所以最后我们给ret赋值时,赋值了一个A,所以我们再一次放弃确认了。

那怎么解决呢,我们可以用一个循环,把前面的缓存区不管是什么全都清空

代码如下:

#include<stdio.h>

int main()
{
    int ch;
    int ret = 0;
    char password[20] = { 0 };
    printf("请输入密码:");
    scanf("%s", password);
    //缓冲区还有' ABCD\n';
    while ((ch = getchar()) != '\n')//只要ch不是\n我们就一直循环
    {
        ;
    }
    printf("请确认(Y/N)");
    ret = getchar();
    if (ret == 'Y')
        printf("确认成功\n");
    else
        printf("放弃确认\n");
    return 0;
}

 这样,我们就可以完美解决getchar的缓冲区问题了,这个很重要!!!

3.2 for

我们已经知道了while循环,但是我们为什么还要一个for循环呢?首先来看看for循环的语法

语法

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

        循环语句;

表达式1初始化部分,用于初始化循环变量的。表达式2条件判断部分,用于判断循环什么时候终止。表达式3调整部分,用于循环条件的调整。

实际的问题:

        使用for循环在屏幕上打印1 ~ 10的数字

#include<stdio.h>

int main()
{
         //初始化   //判断  //调整
    for (int i = 1; i <= 10;i++)
    {
        printf("%d ", i);
    }
    return 0;
}

 for循环执行流程

 我们比较while和for两个语句可以发现在while循环中依然存在循环的三个必要条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。for循环使用的频率也最高

break和centinue在for循环中

我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的,但是还是有些差异。

#include<stdio.h>

int main()
{
   //while中的continue
    int i = 1;
    while (i <= 10)
    {
        if (i == 5)
            continue;
        printf("%d ", i);
        i++;
    }
    return 0;
}
    
#include<stdio.h>

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

 while会死循环,for不会。

for语句的循环控制变量

一些建议:

        1.不可再for循环体内修改循环变量,防止for循环失去控制。

        2.建议for语句的循环控制变量的取值采用铅笔后开区间写法。

for循环的变种(1)

#include<stdio.h>

int main()
{
         //初始化   //判断  //调整
    for (;;)
    {
        printf("hehe\n");
    }
    return 0;
}

 1.for循环的初始化、调整、判断都可以省略

但是,for循环的判断部分如果被省略,判断条件就是:恒为正

2.如果不是非常熟练,建议大家不要随便省略。

for循环的变种(2)

#include<stdio.h>

int main()
{
    int x, y;
    for (x = 0,y = 0;x < 2 && y < 5;x++,y++)
    {
        printf("hehe\n");
    }
    return 0;
}

for循环可以有两个变量。 

3.3 do while

do...while语句的语法

do

        循环语句;

while(表达式);

举个例子:打印1~10

#include<stdio.h>

int main()
{
    int i = 1;
    do
    {
        printf("%d ", i);
        i++;
    } while (i <= 10);
    return 0;
}

do...while在break和continue的运用上和while一样。

do...while语句的特点

循环至少执行一次,使用的场景有限,所以不是经常使用。

#include<stdio.h>

int main()
{
    int i = 10;
    do
    {
        printf("%d ", i);
        i++;
    } while (i <= 10);
    return 0;
}

这个循环是可以进的,但如果是while和for初始化i = 10的时候是无法进入循环的。

4.随机数怎么做

要想做猜数游戏,首先要会做随机数,这里stdlib.h头文件中给了rand的随机数函数,但这个函数,有些问题,就是每一次编译器执行这个随机数都会重复

 所以我们需要用srand()设置rand函数的随机起点。那怎么设置呢?

srand(整形),但我们如果括号里填的是固定的整数时,srand给rand函数定义的随机数是固定的,所以我们需要时间戳。

时间戳是什么?

当前计算机的时间-计算机的起始时间(1970.1.1.0:0:0) = (xxxx)秒。

时间戳是个随时改变的数,所以我们可以用它来做srand中的整数。

所以我们需要time.h头文件中的time变量(长整型),所以我们就可以用srand给rand定义随机数了

srand((unsigned int) time(NULL)),这时候的rand就可以每次得出的随机数都不一样了。

5.goto语句

c语言中提供了可以随意滥用的goto语句和标记跳转的符号。

从理论上goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码

但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,例如一次性跳出两层或多层循环。

这种清空使用break是达不到目的的。他只能从最内层循环退出到上一层循环。

但goto会影响代码的稳定性,除非必要,建议不要使用

goto语句的例子:

#include<stdio.h>
int main()
{
    printf("hello\n");
    goto again;
    printf("你好\n");
again:
    printf("hehe\n");
    return 0;
}

 这里因为goto跳转到again了,所以你好是不会被打印出来的

下期我们5.学习函数,持续更新,喜欢记得关注。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值