C语言-第二章分支语句和循环语句

目录

1.C语言的三种结构

2.什么是语句

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

3.1 if语句

3.1.1 悬空else

3.1.2 if书写形式好的风格注意

3.1.3练习

3.2switch语句

3.2.1在switch语句中的 break  

 3.2.2default子句

 3.2.3练习

4.循环语句 

4.1while循环  

4.1.1 while语句中的break和continue

4.1.2多组输入

4.1.3关于getchaer 和putchar

4.2for循环

4.2.1 语法

4.2.2 break和continue在for循环中

4.2.3for语句的循环控制变量

4.2.3一些for循环的变种

4.2.5 一道笔试题: 

4.3 do...while()循环

4.3.1 do语句的语法:

 4.3.2 执行流程

 4.3.3 do语句的特点

4.3.4 do while循环中的break和continue

4.4 练习

4.4.1 计算 n的阶乘。

4.4.2 计算 1!+2!+3!+……+6!

4.4.3 二分查找

4.4.3.1 sizeof()函数用法补充

4.4.3.2 求平均值的方法

4.4.4 编写代码,演示多个字符从两端移动,向中间汇聚。

4.4.5 编写代码实现,模拟用户登录情景

4.4.5.1 strcmp()函数

4.4.6练习的参考代码

4.4.6.1折半查找算法

4.5猜数字游戏实现

4.6知识点,%   和  写一段调试一段的思路  和计算器

5. goto语句


1.C语言的三种结构

C语言是结构化的设计语言,支持以下三种结构

顺序结构、选择结构、循环结构

2.什么是语句

C语句可分为以下五类:

表达式语句 、函数调用语句 、 控制语句 、复合语句 、空语句
本章介绍的是控制语句。
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成。
C 语言有九种控制语句。 可分成以下三类:
条件判断语句也叫分支语句: if 语句、 switch 语句;
循环执行语句: do while 语句、 while 语句、 for 语句;
转向语句: break 语句、 goto 语句、 continue 语句、 return 语句。

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

3.1 if语句

if语句的语法结构:

语法结构:
//单分支
if(表达式)
    语句;


//双分支,注意else后面不要跟分号
if(表达式)
    语句1;
else
    语句2;



//多分支    
if(表达式1)
    语句1;
else if(表达式2)
    语句2;
else if(表达式3)
    语句3;
else
    语句4;

演示代码:

#include 
//代码1
int main()
{
 int age = 0;
    scanf("%d", &age);
    if(age<18)
   {
        printf("未成年\n");
   }
}


//代码2
#include 
int main()
{
 int age = 0;
    scanf("%d", &age);
    if(age<18)
   {
        printf("未成年\n");
   }
    else
   {
        printf("成年\n");
   }
}



//代码3
#include 
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");
   }
    
}

1.如果有很多分支,可以加多条的else  if 语句。

2.注意:在数学中写18<= age <30 ,但在C语言中,代码是从左到右判断会产生错误,要写3成age>=18 && age<30 的形式。

3.if、else  if、和else后面都是默认跟一条语句不用加{ },多条语句的时候要加{ }

4.如果表达式的结果为真,则语句执行。 在C 语言中如何表示真假?只有0是假,即使-1也是  真

3.1.1 悬空else

当你写了这个代码:(注意这段代码的分风格不好)
#include 
int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
        if(b == 2)
            printf("hehe\n");
    else
        printf("haha\n");
    return 0;
}

1.else总是和离他最近的if进行匹配。

2.为啥第一个if后没加{ },跟多条代码?因为后面的if和else算一条语句,但为了误解最好加上{}

3.上段代码的if和else没有对齐,容易产生视觉误导,所以代码风格很重要。可以看《高质量C++/C编程指南》提高自己的代码质量。

改正:
//适当的使用{}可以使代码的逻辑更加清楚。
//代码风格很重要
//加上{} 后if和else匹配的不同
#include 
int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
   {
        if(b == 2)
       {
            printf("hehe\n");
       }
   }
    else
   {
         printf("haha\n");
   }       
    return 0;
}

3.1.2 if书写形式好的风格注意

当拿一个常量和变量判断是否相等时,把常量放在==的左边,是好的编程风格

//写成   5==mum

//万一不注意写成  5 = num 会报错

3.1.3练习

//用for循环输出1-100之间的奇数
#include
int main()
{
	int i = 0;
	for (i = 0; i < 101; i++)
	{
		if (i % 2 == 1)
		{
			printf("%d\n",i);
		}
	}

	return 0;
}





//用while循环输出1-100之间的奇数
#include
int main()
{
	int i = 0;
	while (i < 101)
	{
		if (i % 2 == 1)
		{
			printf("%d\n", i);
		}
		i++;
	}

	return 0;
}





//输出1-100之间的奇数(取巧方法,没有用循环但效率高)
#include      
int main()
{
	int i = 1;
	while (i < 101) 
	{
		printf("%d\n", i);
		i += 2;
	}

	return 0;
}

3.2switch语句

switch 语句也是一种分支语句。
常常用于多分支的情况。
比如:
输入 1 ,输出星期一
输入 2 ,输出星期二
输入 3 ,输出星期三
输入 4 ,输出星期四
输入 5 ,输出星期五
输入 6 ,输出星期六
输入 7 ,输出星期日
那我没写成 if...else if ...else if 的形式太复杂,那我们就得有不一样的语法形式。 这就是switch 语句。

语法结构:

switch(整型表达式)
{
    语句项;
}


//语句项是
//是一些case语句:
//如下:
case 1:      // case   1:  case 和  1中间加空格,1后加:
     break;
case 2:
     break;
case 3:
     break;

1.switch根据()中的整形表达式,选择进入那个case

2.分清switch 、case、break 、default

3.break要按需加入,没有特殊要求每条case后都加break

4.表达的选项没有对应的case匹配时,加入default,最好每个switch语句都加上default,在default后也加上break

5.default在switch语句中没有顺序要求,只要满足要求,放在哪都行

注意:  case   1:  case 和  1中间加空格,1后加:

3.2.1switch语句中的 break  

switch 语句中,我们没办法直接实现分支,搭配 break 使用才能实现真正的分支。
比如:
#include 
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;
   }
    return 0;
}

1.switch ()  ,括号中必须跟整型,浮点型不可以

2.switch ()  ,  括号中的数为程序的入口,break为程序的出口,跳出程序

3.break要按需加入

有时候我们的需求变了:
1. 输入 1-5 ,输出的是 “weekday”;
2. 输入 6-7 ,输出 “weekend”
所以我们的代码就应该这样实现了:
#include 
//switch代码演示
int main()
{
    int day = 0;
    switch(day)
   {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            printf("weekday\n");
            break;
        case 6:
        case 7:
            printf("weekend\n");
            break;
   }
    return 0;
}
break 语句 的实际效果是把语句列表划分为不同的分支部分。
编程好习惯
在最后一个 case 语句的后面加上一条 break 语句。
(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break 语句)。

 3.2.2default子句

如果表达的值与所有的 case 标签的值都不匹配怎么办?
其实也没什么,结构就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在 C 中并不认为是个错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条 default 子句,把下面的标签
default
写在任何一个 case 标签可以出现的位置。
switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个 switch 语句中只能出现一条 default 子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个 case 标签一样执行 default 子句。
编程好习惯
在每个 switch 语句中都放一条 default 子句是个好习惯,甚至可以在后边再加一个 break

 3.2.3练习

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

//执行结果m = 5  n =  3

switch允许被嵌套使用

4.循环语句 

while
for
do while

4.1while循环  

//while 语法结构
while(表达式)
 循环语句;

while后面给一个表达式,表达式如果为真---->进入循环语句,循环语句执行完之后--->再上来判断表达式是真或假,如果还是真再继续进入循环语句。直到表达式的结果被判定为假,停止

C语言-第二章分支语句和循环语句_第1张图片

expr:判断表达式

!= 0 非0即真

break结束本次循环

continue停止本次循环之后的代码,跳到判断部分,执行下次循环入口进行判断

比如我们实现:
在屏幕上打印 1-10 的数字。
#include 
int main()
{
    int i = 1;  //初始化
    while(i<=10)//判断
    {
        printf("%d ", i);
        i++;     //调整
    }
    return 0;
}
上面的代码已经帮我了解了 while 语句的基本语法,那我们再了解一下:

4.1.1 while语句中的breakcontinue

break介绍
//break 代码实例
#include 
int main()
{
   int i = 1;
   while(i<=10)
   {
     if(i == 5)
     break;
     printf("%d ", i);
     i = i+1;
   }
   return 0;
}

//执行结果1234
breakwhile循环中的作用:
其实在循环中只要遇到 break ,就停止后期的所有的循环,直接终止循环。
所以: while 中的 break 是用于 永久 终止循环的。
continue 介绍
//continue 代码实例1
#include 
int main()
{
     int i = 1;
     while(i<=10)
     {
        if(i == 5)
        continue;
        printf("%d ", i);
     i = i+1;
     }
     return 0;
}

//执行结果1234死循环
//continue 代码实例2
#include 
int main()
{
     int i = 1;
     while(i<=10)
     {
         i = i+1;
         if(i == 5)
         continue;
         printf("%d ", i);
      }
      return 0;
}

//执行结果1 2 3 4 5 6 7 8 9 10
continuewhile循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中 continue 后边的代码不会再执行,
而是直接跳转到 while 语句的判断部分。进行下一次循环的入口判断

4.1.2多组输入

scanf在读取到文件结束符时,会返回标识EOF(end of life),EOF是一个预定义的常量,等于-1。通过判断scanf的返回值否为EOF决定是否退出循环。

scanf 函数是输入函数
函数的返回值是:int
如果读取成功,返回的就是实际读取到的数据的个数
如果函数读取失败,就返回EOF
非常简单的写法就是scanf == 1,scanf读取到一个数字,如果返回值=1,就证明读取正常,就进去判断.读到三个数字就返回3

多组输入,要按三次ctrl + z才能停下,
本来按一次ctrl + z就会触发文件结束标志EOF,
按三次是VS编译器的bug


#include 

int main()
{
	int n1 = 0;
	int n2 = 0;
	while (scanf("%d %d", &n1, &n2) == 2) 
	{              
		if (n1 == n2)
		{
			printf("%d = %d\n", n1, n2);
		}
		else if (n1 > n2)
		{
			printf("%d > %d\n", n1, n2);
		}
		else
		{
			printf("%d < %d\n", n1, n2);
		}
	}
	return 0;
}
//也可以写成while (scanf("%d %d", &n1, &n2) !=EOF) ,scanf读取到两个数,返回2

4.1.3关于getchaer 和putchar

 键盘输入的字符会放到缓冲区。

getchar()函数是是从缓冲区中每次读取一个字符。

putchar()函数是打印字符的。

EOF是文件结束标志,EOF就是-1,在MSDN上查。

在MSDN上查,getchar的返回值是字符的ASCII值,所以返回类型用int

//读取一个字符打印一个字符
#include
int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}

	return 0;
}
 //这是错误代码,不能清理缓存区
//读一个字符打印一个的实际例子 ,输入密码
#include
int main()
{
	char password[20] = {0};
	printf("请输入你的密码\n");
	scanf("%s",password);//假设为123
	printf("确定密码按Y\n");//这里只是相当于按确认件,不是判断密码是否正确
	int ch = getchar();
	if ('Y' == ch)
		printf("确认成功");
	else
		printf("确认失败");

	return 0;
}

//失败的原因:scanf只会读取到空格之前的字符(这里不抬杠说密码里有空格)
//并且getchar一次只能处理一个字符,万一有多个字符也处理不了

//正确代码
//读一个字符打印一个的实际例子,输入密码

#include
int main()
{
	char password[20] = {0};
	printf("请输入你的密码\n");
	scanf("%s",password);//假设为123456 abcd,
	int tmp = 0;
	while ((tmp = getchar() != '\n'))
	{
		;
	}
	printf("确定密码按Y\n");//这里只是相当于按确认件,不是判断密码是否正确
	int ch = getchar();
	if ('Y' == ch)
		printf("确认成功");
	else
		printf("确认失败");

	return 0;
}  


上段代码的解释

建设键盘输入123  abc然后回车确认,scanf读取到是空格之前的123 ,然后缓冲区还有abc\n。
然后while循环,把abc都变成空语句,然后循环到最后剩了\n也也被getcher()读取到了,放进tmp里了
然后\n   !=   \n    结束循环,就是getchar()读取了\n了,然后缓冲区就啥也没有了

程序调用 getchar 时,程序就等着用户按键。用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符 \n 也放在缓冲区中),
当用户键入回车之后,getchar() 函数才开始从输入缓冲区中每次读取一个字符,getchar 函数的返回值是用户输入的字符的 ASCII 码,
若遇到文件结尾 (End-Of-File) 则返回 -1 (EOF),并将用户输入的字符回显到屏幕,如果用户在按回车之前输入了不止一个字符,
其他字符会保留在键盘缓存区中,等待后续 getchar 调用读取。也就是说,后续的 getchar 调用不会等待用户按键,
而直接读取缓冲区中的字符,直到缓冲区中的字符读完后,才等待用户按键。程序中 while 循环工作时,
每一次循环 getchar() 就会从输入缓冲区读取一个字符,然后 putchar 输出,直到遇到了文件结束标志 EOF,循环判断条件为假,循环才结束


//读取字符,只打印数字字符,如输入12345,打印12345
//如输入1q2w3e4r,只会打印1234
#include
int main()
{
	int ch = '\0';//只是赋值无特殊含义 
	while ((ch = getchar()) != EOF)
	{
		if (ch < '0' || ch > '9')
			continue;
		putchar(ch);
	}
	return 0;
}   //提问为啥输入1打印字符‘1’

上段代码的解释

因为getchar 函数的返回值是用户输入的字符的 ASCII 码,即键盘输入的是1,getchar看到的是1的ASCII码值


4.2for循环

4.2.1 语法

for(表达式1; 表达式2; 表达式3)
循环语句;
表达式 1
表达式 1 初始化部分 ,用于初始化循环变量的。
表达式 2
表达式 2 条件判断部分 ,用于判断循环时候终止。
表达式 3
表达式 3 调整部分 ,用于循环条件的调整。
三个合起来叫做循环变量
for循环相较于while循环的好处是,初始化、条件判断、调整部分是写在一起的,在写代码时容易调整,不容易遗漏。

C语言-第二章分支语句和循环语句_第2张图片

实际的问题:

//使用for循环 在屏幕上打印1-10的数字。
#include 
int main()
{
  int i = 0;
  //for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
  for(i=1; i<=10; i++)
  {
    printf("%d ", i);
  }
  return 0;
}

现在我们对比一下for循环和while循环。

int i = 0;
//实现相同的功能,使用while
i=1;//初始化部分
while(i<=10)//判断部分
{
  printf("hehe\n");
  i = i+1;//调整部分
}
//实现相同的功能,使用while
for(i=1; i<=10; i++)
{
  printf("hehe\n");
}
可以发现在 while 循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较 远,这样 查找修改就不够集中和方便。所以,for循环的风格更胜一筹; for 循环使用的频率也最高。

4.2.2 breakcontinuefor循环中

我们发现在 for 循环中也可以出现 break continue ,他们的意义和在 while 循环中是一样的。
但是还是有些差异:
//代码1  执行结果1 2 3 4
#include 
int main()
{
  int i = 0;
  for(i=1; i<=10; i++)
  {
     if(i == 5)
       break;
     printf("%d ",i);
  }
  return 0;
}





//代码2   执行结果1 2 3 4  6 7 8 9 10
#include 
int main()
{
  int i = 0;
  for(i=1; i<=10; i++)
  {
    if(i == 5)
      continue;
  printf("%d ",i);
  }
  return 0;
}

4.2.3for语句的循环控制变量

建议:只是建议,灵活运用

1. 不可在 for 循环体内修改循环变量,防止 for 循环失去控制。就严格遵守for循环的语法
for(i = 1; i < 10; i++ );新手不要漏任何一个语句。
2. 建议 for 语句的循环控制变量的取值采用 前闭后开区间 写法。
int i = 0;
//前闭后开的写法  [0 , 10)这是左闭右开
for(i=0; i<10; i++)
{

}



//两边都是闭区间   [0 , 9]这是闭区间,左闭右闭
for(i=0; i<=9; i++)
{

}

4.2.3一些for循环的变种

#include 
int main()
{
    //代码1
    for (;;) 
    {
      printf("hehe\n");
    }
//for循环中的初始化部分,判断部分,调整部分是可以省略的,
//但是不建议初学时省略,容易导致问题。



        //代码2
    int i = 0;
    int j = 0;
    //这里打印100个hehe
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j < 10; j++)
        {
            printf("hehe\n");
        }
    }




    //代码3
    int i = 0;
    int j = 0;
    //如果省略掉初始化部分,这里打印10个hehe
    for (; i < 10; i++)
    {
        for (; j < 10; j++)
        {
            printf("hehe\n");
        }
    }



    //代码4  使用多余一个变量控制循环
    int x, y;
    for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
    {
        printf("hehe\n");
    }
    return 0;
}

for循环的判断部分如果省略,意味着判断恒为真

4.2.5 一道笔试题: 

//请问循环要循环多少次?
#include 
int main()
{
	int i = 0;
	int k = 0;
	for (i = 0, k = 0; k = 0; i++, k++)
		k++;
	return 0;
}


//for (i = 0, k = 0; k = 0; i++, k++)
//i = 0, k = 0;初始化
//k = 0;  判断语句(在这里是每次都赋值为0)
// i++, k++ 调整
//判断K=0为假,不会进入循环,循环次数为0

4.3 do...while()循环

4.3.1 do语句的语法:

do
   循环语句;
while(表达式);

do,程序上来就循环一次,再判断条件,符合条件再循环。

 4.3.2 执行流程

C语言-第二章分支语句和循环语句_第3张图片

 4.3.3 do语句的特点

循环至少执行一次,使用的场景有限,所以不是经常使用。
#include 
int main()
{
    int i = 10;
    do
    {
        printf("%d\n", i);
        i++;
    }while(i<10);
    return 0;
}

4.3.4 do while循环中的breakcontinue

#include 
int main()
{
	int i = 10;

	do
	{
		if (5 == i)
			break;
		printf("%d\n", i);
		i++;
	} while (i < 10);

	return 0;
}

//执行结果,1234

#include 
int main()
{
	int i = 10;

	do
	{
		if (5 == i)
			continue;
		printf("%d\n", i);
		i++;
	} while (i < 10);

	return 0;
}
//执行结果1234死循环

4.4 练习

(用for   while   do while循环都可以)

4.4.1 计算 n的阶乘。

//纯代码版本
//1.计算n的阶乘,假设n是5,太大的数字可能超过int的最大范围

#include
int main()
{
	int n = 0;
	int sum = 1;
	scanf("%d",&n);
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		sum = sum * i;//注意这里别写错成×n
	}
    printf("sum = %d\n",sum);

	return 0;
}



//带注释版本
//1.计算n的阶乘,假设n是5,太大的数字可能超过int的最大范围
//纯代码版本
#include
int main()
{
	int n = 0;
	int sum = 1;  //这里不能赋值为0,0乘0还是0
	scanf("%d",&n);
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		sum = sum * i;//注意这里别写错成×n,不要用数学的思维
	}
    printf("sum = %d\n",sum);

	return 0;
}


注意,这个题不要写很大的数字,太大的数字的计算结果会超过C中
int MAX的上限,是2147483647,如果太大数字会溢出存不下,得不
到想要的结果

4.4.2 计算 1!+2!+3!+……+6!

//2.计算1!+2!+3!+4!+5!+6!
#include
int main()
{
	int n = 0;
	scanf("%d",&n);
	int fac = 1;
	int sum = 0;
	int i = 1;
	for (i = 1; i <= n; i++)
	{
		fac = fac * i;
		sum += fac;
	}
	printf("sum = %d\n", sum);

	return 0;
}

4.4.3 二分查找

在一个有序数组中查找具体的某个数字n。
二分查找的步骤:
假如在1  2  3  4  5  6  7  8  9  10 中找7
下标为0  1  2  3  4  5  6  7  8   9
找中间下标的元素,与之比较,一次找一半就很快
定义左下标:left
定义右下标:right
定义中间下标:mid
(0+9)/2=4(int型计算留整数)
第一次二分查找,找到5,然后left = mid + 1
再从5-10中二分查找
新的mid = (5+9)/2 = 7 ,这里的579都是下标
找到的数字比7大
新的right = mid - 1
然后循环几次,最后left和right都指向要找的7对应的下标
代码:第一遍写的时候出的错误
//3.在有序数组中具体查找某个数字(二分查找)
 //错误代码
//当时写代码犯的错误应该是arr[mid]
#include
int main()
{
	int arr[] = { 2,4,6,8,10,12,14,16,18,20 };
	int k = sizeof(arr) / sizeof(arr[0]);
	int n = 14;//假设要找的数字
	int left = 0;
	int right = k - 1;
	while (right >= left)
	{
		int mid = left + (right - left) / 2;
		if (n  > mid )   //应该是arr[mid]
		{
			left = mid + 1;
		}
		else if (n < mid)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是%d",mid);
			break;
		}
	}
	if (left > right)
	{
		printf("没有这个数字");
	}

	return 0;
}

正确代码:

//3.在有序数组中具体查找某个数字(二分查找)
 //正确代码
//当时写代码犯的错误应该是arr[mid]
#include
int main()
{
	int arr[] = { 2,4,6,8,10,12,14,16,18,20 };
	int k = sizeof(arr) / sizeof(arr[0]);
	int n = 20;//假设要找的数字是20
	int left = 0;
	int right = k - 1;
	while (right >= left)
	{
		int mid = left + (right - left) / 2;  //计算中间元素的下标
        //注意,求中间下标的代码一定放在循环里,每次循环都要重新找中间元素的下标
		if (n  > arr[mid])   //应该是arr[mid]
		{
			left = mid + 1;
		}
		else if (n < arr[mid])
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是%d",mid);
			break;
		}
	}
	if (left > right)
	{
		printf("没有这个数字");
	}

	return 0;
}
4.4.3.1 sizeof()函数用法补充

sizeof()是用来计算数组占字节大小,在这题中sizeof(arr)计算的是整个数组占多少个字节,sizeof(arr[0])就是计算数组第一个元素的大小。

4.4.3.2 求平均值的方法

如果直接加起来除2,可能会超过int MAX的最大范围。这样就不会超

C语言-第二章分支语句和循环语句_第4张图片

int mid = left + (right - left)/2 

4.4.4 编写代码,演示多个字符从两端移动,向中间汇聚。

// 4.编写代码,演示多个字符从两端移动,向中间汇聚
#include
#include//strlen的头文件
#include//Sleep的头文件,这个只能在windows环境中运行
#include//system的头文件
int main()
{
	char arr1[] = "welcome  to weihai";
	char arr2[] = "##################";
	int left = 0;
	int right = strlen(arr1) - 1;//求的是\0之前的字符个数,所以右下标是-1
  //int right = sizeof(arr)/sizeof(arr[0]) -2 ; 求字符串的长度,包括\0,所以要-2
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n",arr2);
		Sleep(1000);//Sleep想要动态效果,等几秒出现一行,S大写,1000毫秒=1秒
		system("cls");//清屏,让打印出来的东西显示在第一行
		left++;
		right--;
	}
	printf("%s\n", arr2);//最后保留在屏幕上
	return 0;
}

4.4.5 编写代码实现,模拟用户登录情景

编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则 提示登录成,如果三次均输入错误,则退出程序。
//我自己写错的代码
// 5编写代码,模拟用户登录场景,并且只能有三次机会(只允许输入三次,
密码正确提示登录成功,三次均失败则退出程序)

#include
#
int main()
{
	char password[] = { 0 };// 数组赋初值不对  
	printf("请输入密码\n");
	scanf("%s",password);//应该在循环里面,要输入三次密码
	int i = 0;
	for( i = 1; i <= 3; i++)
	{
		if ( == 0)
		{
			printf("密码输入正确\n");
			break;
		}
		else
		{
			printf("密码输入错误,请重新输入\n");
		}
	}
	if (i > 3)
	{
		printf("三次密码均错误\n");
	}

	return 0;
}

正确代码:

// 5编写代码,模拟用户登录场景,并且只能有三次机会(只允许输入三次,
密码正确提示登录成功,三次均失败则退出程序)
//修改后正确的代码
#include
#include
int main()
{
	char password[10] = { 0 };
	printf("请输入密码\n");
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		scanf("%s", password);//假设密码是qwer1234
		if (strcmp(password, "qwer1234") == 0)
		{
			printf("密码输入正确\n");
			break;
		}
		else
		{
			printf("密码输入错误,请重新输入\n");
		}
	}
	if (i ==  3)
	{
		printf("三次密码均错误\n");
	}

	return 0;
}

字符串之间的比较不能用 == ,应该用库函数strcmp,是专门用来比较字符串的

4.4.5.1 strcmp()函数

在MSDN上查用法

C语言-第二章分支语句和循环语句_第5张图片

4.4.6练习的参考代码

//代码1
//编写代码,演示多个字符从两端移动,向中间汇聚
#include 
int main()
{
	char arr1[] = "welcome to bit...";
	char arr2[] = "#################";
	int left = 0;
	int right = strlen(arr1) - 1;
	printf("%s\n", arr2);
	//while循环实现
	while (left <= right)
	{
		Sleep(1000);
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		left++;
		right--;
		printf("%s\n", arr2);
	}
	//for循环实现
	for (left = 0, right = strlen(src) - 1;
		left <= right;
		left++, right--)
	{
		Sleep(1000);
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", target);
	}
	retutn 0;
}


//代码2
int main()
{
	char psw[10] = "";
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; ++i)
	{
		printf("please input:");
		scanf("%s", psw);
		if (strcmp(psw, "password") == 0)
			break;
	}
	if (i == 3)
		printf("exit\n");
	else
		printf("log in\n");
}
4.4.6.1折半查找算法
比如我买了一双鞋,你好奇问我多少钱,我说不超过 300 元。你还是好奇,你想知道到底多少,我就让 你猜,你会怎么猜? 答案:你每次猜中间数。
代码实现:
//实现在主函数内:
#include
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]) - 1;
	int key = 7;
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else
			break;
	}
	if (left <= right)
		printf("找到了,下标是%d\n", mid);
	else
		printf("找不到\n");
}
//如果实现一个二分查找函数:
int bin_search(int arr[], int left, int right, int key)
{
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) >> 1;
		if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else
			return mid;//找到了,返回下标
	}
	return -1;//找不到
}

4.5猜数字游戏实现

//猜数字游戏
//电脑随机生成一个数字(定一个1-100)
//玩家猜数字,猜大猜小都要告知
//直到猜对为止,游戏可以一直玩


#include 
#include 
#include 


void menu()  //打印一个菜单,返回类型,void,无类型
{            //简易的游戏菜单, 输入1开始游戏,输入0退出游戏
	printf("**********************************\n");
	printf("*********** 1.play     **********\n");
	printf("*********** 0.exit     **********\n");
	printf("**********************************\n");
}
//RAND_MAX--rand函数能返回随机数的最大值。


//猜数字第一步生成一个随机的数字,用到新知识点rand()和srand,用MSDN查
void game()
{
	int random_num = rand() % 100 + 1;
	int input = 0;
	while (1)
	{
		printf("请输入猜的数字>:");
		scanf("%d", &input);
		if (input > random_num)
		{
			printf("猜大了\n");
		}
		else if (input < random_num)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}


int main()
{
	int input = 0;
	srand((unsigned)time(NULL));
//传进一个一直变化的值,引入时间戳的概念,时间是一直变化的,
//srand随机产生随机数(任何程序生成的随机都是伪随机,但不用管)
//利用C语言提供的time函数返回时间戳(新的知识点)
//srand和time的返回类型有差异,用(unsigned)强制类型转换
//NULL空指针

	do {
		menu();  //菜单函数
		printf("请选择>:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("选择错误,请重新输入!\n");
			break;
		}
	} while (input);
	return 0;
}

C语言-第二章分支语句和循环语句_第6张图片

 注:

在C代码上写上RANG-MAX然后包含一下头文件,右击RANG-MAX转到定义,就可以看到C语言中定义的内容

4.6知识点,%   和  写一段调试一段的思路  和计算器

1.任何数字%100,得到的都是0-99的数字,一个数%179,得到的就是0-178的数字

2.一个重要的点,先构思出大体框架,做一个独立的模块,写一段代码就测试一段,测试逻辑对错,如果全写完有错误再找就很麻烦。

3.    0X开头的是16进制的数字,0开头的是8进制的数字 。电脑带的计算器找到程序员计算器,HEX代表十六进制,DEC代表十进制,OTC代表八进制,BIN代表二进制

5. goto语句

C 语言中提供了可以随意滥用的 goto 语句和标记跳转的标号。
从理论上 goto 语句是没有必要的,实践中没有 goto 语句也可以很容易的写出代码。
但是某些场合下 goto 语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
多层循环这种情况使用 break 是达不到目的的。它只能从最内层循环退出到上一层的循环。
goto 语句不能跨函数跳转
goto 语言真正适合的场景如下
for (...)
for (...)
{
	for (...)
	{
		if (disaster)
			goto error;
	}
}
…
error :
if (disaster)
// 处理错误情况
下面是使用 goto 语句的一个例子,然后使用循环的实现方式替换 goto 语句:
一个关机程序
#include 
#include 
int main()
{
	char input[10] = { 0 };
	system("shutdown -s -t 60");  //system是一个库函数,用来执行系统命令
again:
	printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
	scanf("%s", input);
	if (0 == strcmp(input, "我是猪"))
	{
		system("shutdown -a");//意思是取消关机
	}
	else
	{
		goto again; //跳到again
	}
	return 0;
}
而如果不适用 goto 语句,则可以使用循环:
#include 
#include 
int main()
{
	char input[10] = { 0 };
	system("shutdown -s -t 60");
	while (1)
	{
		printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
		scanf("%s", input);
		if (0 == strcmp(input, "我是猪"))
		{
			system("shutdown -a");
			break;
		}
	}
	return 0;
}

Windows 系统自带一个名为Shutdown.exe的程序,可以用于关机操作(位置在Windows\System32下),一般情况下Windows系统的关机都可以通过调用程序 shutdown.exe来实现的,同时该程序也可以用于终止正在计划中的关机操作。

你可能感兴趣的:(c语言)