初识C语言(6)猜数字游戏,二分查找,关机程序,函数,闰年

文章目录

  • 1.猜数字游戏
    • 开头
    • 菜单部分
    • 猜随机数的部分
    • 完整代码
  • 2.阶乘求和
  • 3.二分查找
  • 4.goto语句
  • 5.函数
    • 5.1函数的分类
    • 5.2函数的参数
      • 5.2.1实际参数(实参):
      • 5.2.2 形式参数(形参):
    • 5.3 函数的调用
      • 5.3.1传值调用
      • 5.3.2传址调用

1.猜数字游戏

开头

我们想要实现猜数字这个游戏,我们应该先理清思路,将这个复杂的过程分解成一个个小的部分。

菜单部分

首先我们来做这个菜单的部分。

初识C语言(6)猜数字游戏,二分查找,关机程序,函数,闰年_第1张图片

菜单做好了,我们想这个游戏不止玩一次,那么菜单应该重复出现,实现菜单这个函数的循环。用do while循环,先打印菜单,然后while判断是否继续打印。

初识C语言(6)猜数字游戏,二分查找,关机程序,函数,闰年_第2张图片

猜随机数的部分

我们想要生成一个随机的数,就要用到rand()这个函数

The rand function returns a pseudorandom integer in the range 0 to RAND_MAX
rand()生成随机数范围是0- RAND_MAX
RAND_MAX is defined as the value 0x7fff,0x7fff换算成10进制是32767。

我们想要生成的是1到100之间的随机数,可以将rand()%100+1.

而想要使用rand()这个函数,就要先用srand,而srand需要设置一个随机数作为起点,我们想到time函数,时间戳,时间是一直在变化的。

void srand( unsigned int seed );
time_t time( time_t *timer );

而srand函数需要的参数是无符号整形型,time返回值是time_t类型,所以需要强制类型转换。

srand起始点只用设置一次。

完整代码

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include
void menu()
{
	printf("****************************\n");
	printf("********** 1.play **********\n");
	printf("********** 0.exit **********\n");
	printf("****************************\n");
}
void game()
{
	int ret = rand() % 100 + 1;
	int guess = 0;
	while (1)
	{
		printf("请输入猜的数字\n");
		scanf("%d", &guess);
		if (guess > ret)
		{
			printf("猜大了\n");
		}
		else if (guess < ret)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("猜对了\n");
			break;
		}
	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
		{
			game();
			break;
		}
		case 0:
		{
			printf("退出游戏\n");
			break;
		}
		default:
		{
			printf("选择错误,请重新输入\n");
			break;
		}
	  }
	} while(input);

	return 0;
}

初识C语言(6)猜数字游戏,二分查找,关机程序,函数,闰年_第3张图片

2.阶乘求和

计算1!+2!+3!=?

初识C语言(6)猜数字游戏,二分查找,关机程序,函数,闰年_第4张图片

3.二分查找

利用函数调用实现二分查找

int main()
{
	int  arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 1;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//sz数组元素个数不能在函数内部计算,因为数组传参传递的是数组首元素的地址,相当于指针,指针的大小是4或8个字节,算出的sz结果不对。
	int ret = binary_search(arr, k, sz);
	if (ret == -1)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了,下标是:%d\n", ret);
	}
	return 0;
}
int binary_search(int arr[], int k, int s)
{
	int left = 0;
	int right = s- 1;
    while (left <= right)
	{
		int mid = left + (right - left) / 2;
		//这样求可以防止溢出,如果int mid=(left+right)/2,这样写当left和right非常大时算出的结果可能会丢失数据。
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}

4.goto语句

作用:终止程序在某些深度嵌套的结构的处理过
程。
例如:一次跳出两层或多层循环。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。

下面是使用goto语句的一个例子.

一个关机程序

#include 
int main()
{
    char input[10] = {0};
    system("shutdown -s -t 60");
again:
    printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
    scanf("%s", input);
     if(0 == strcmp(input, "我是猪"))
   {
        system("shutdown -a");
   }
    else
   {
        goto again;
   }
    return 0;
}

strcmp()函数 :比较两个字符串是否相等,相等返回值等于0,不相等返回值非0.

5.函数

5.1函数的分类

C语言中函数的分类:

  1. 库函数
  2. 自定义函数

简单的总结,C语言常用的库函数都有:
IO函数
字符串操作函数
字符操作函数
内存操作函数
时间/日期函数
数学函数
其他库函数

函数的组成:

ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数

举个例子:
写一个函数可以交换两个整形变量的内容。

//错误版本
void Swap1(int x, int y)
{
 int tmp = 0;
 tmp = x;
 x = y;
 y = tmp;
}
int main()
{
 int num1 = 1;
 int num2 = 2;
 Swap1(num1, num2);
 printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
 Swap2(&num1, &num2);
 printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
 return 0;
}

在这里插入图片描述

正确版本

void Swap2(int* px, int* py)
{
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
	int num1 = 1;
	int num2 = 2;
	printf("交换前num1=%d,num2=%d\n", num1, num2);
	Swap2(&num1, &num2);
	printf("交换后num1=%d,num2=%d\n", num1, num2);
	
	return 0;
}

在这里插入图片描述

错误写法传递的是值,正确写法传递的是地址

5.2函数的参数

5.2.1实际参数(实参):

真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形
参。

5.2.2 形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有
效。

上面 Swap1 和 Swap2 函数中的参数 x,y,px,py 都是形式参数。在main函数中传给 Swap1 的 num1 ,
num2 和传
给 Swap2 函数的 &num1 , &num2 是实际参数。

Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。

5.3 函数的调用

5.3.1传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

5.3.2传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量。

举例:打印1000-2000之间的闰年

int is_leap_year(int y)
{
	if (((y % 4 == 0) & (y % 100 != 0)) || (y % 400 == 0))
	{
		return 1;
	}
	return 0;
}
int main()
{
	int year = 0;
	for (year = 1000; year <= 2000; year++)
	{
		if (is_leap_year(year))
		{
			printf("%d ", year);
		}
	}
	return 0;
}

初识C语言(6)猜数字游戏,二分查找,关机程序,函数,闰年_第5张图片

看到这里,你应该有所收获吧!感谢你的了解,更感谢您的支持❤️,点赞收藏⭐留言都是我最大的动力。

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