• 【编程DIY】一.几个有趣的小程序


    系列前言
    兴趣是最好的老师。本系列介绍一些非常容易上手编写的小程序,这些小程序给博主的学习之路带来了许多欢乐,特记录分享!

    编程语言:C语言
    编程环境:Visual Studio 2019

    本篇预备知识

    【C语言从青铜到王者】第零篇·与C语言来个约会

    【C语言从青铜到王者】第一篇·详解分支与循环



    让程序“动起来”:标题浮现小程序

    C语言还可以做动画?相信读到这的你会有点不可思议。今天就让我们来编写一个让标题逐渐浮现的小程序吧


    思路分析:
    程序的思路是让标题逐渐出现,那我们就需要一行“***************”作为幕布,来遮掩我们的标题,然后把幕布的前后元素依次与标题的字符做交换,直至标题完全显现。
    思路转化成代码:
    我们需要两个等长的字符串,一个是我们的标题,一个是“幕布”,所以需要定义的变量就是两个字符串数组。由于需要使用数组,为了明确数组下标,我们先计算出数组元素个数,然后就可以确定左下标和右下标。再让两字符串最左和最右的元素分别交换。这样我们就打印出了这个动画的“每一帧”

    然后我们介绍两个知识:一个是Sleep()函数,它的作用是让内容在屏幕上停留一段时间,括号内可以填数字代表停留的时间,单位是ms;另一个是系统命令system(“cls”),cls是clean screen,意思是清空屏幕。Sleep函数的头文件是windows.h,system函数的头文件是stdlib.h,使用它们前都得先引用头文件

    我们在每次打印出“一帧”的语句后使用sleep函数来让它停留一段时间和system(“cls”)来清空屏幕,这样就实现了动画的效果
    给出原码:

    #include
    #include
    #include
    #include
    int main()
    {
    	char arr1[] = "welcome to the world of C !";
    	char arr2[] = "###########################";
    	int left = 0;
    	int right = strlen(arr1) - 1;
    	while (left <= right)
    	{
    		arr2[left] = arr1[left];
    		arr2[right] = arr1[right];
    		printf("%s\n", arr2);
    		Sleep(200);
    		system("cls");
    		left++;
    		right--;
    	}
    	printf("%s\n", arr2);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    模拟密码输入:输密码小程序

    我们每天需要登录游戏,登录社交软件,登录银行账户…生活中输入密码的情况无处不在。今天就让我们来编写一个输入密码的小程序吧


    知识补充一:getchar和putchar

    由于博主才疏学浅,在这里引用大佬的解释,真的是没有一句废话。我配了张图方便大家理解

    getchar()
    用于读取用户从键盘输入的单个字符,它有一个整型的返回值,当发生读取错误的时候,返回字符串EOF(整型值为-1),当读取正确的时候,它会返回用户从键盘输的第一个字符的ASCII码。
    当程序调用getchar运行程序时,getchar就等着用户从按键输入,用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符\n也会被放在缓冲区中),当用户键入回车之后,getchar才开始从输入流中每次读入一个字符,输入的字符不只一个的时候,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完之后,才等待用户按键。
    getchar函数输入数字也按字符处理。
    单个的getchar函数输入多于一个字符时,只接收第一个字符。
    putchar()
    向终端输出一个字符。其格式为putchar(ch),其中ch可以是被单引号(英文状态下)引起来的一个字符,可以是介于0~127之间的一个十进制整型数(包含0和127,超过127就不是ASCII码了),也可以是事先用char定义好的一个字符型变量。
    当c为一个被单引号(英文状态下)引起来的字符时,输出该字符(该字符也可为转义字符 )。
    当c为一个介于0~127(包括0及127)之间的十进制整型数时,它会被视为对应字符的ASCII代码,输出该ASCII代码对应的字符;
    当c为一个事先用char定义好的字符型变量时,输出该变量所指向的字符。
    当整型变量ch超出8位变量的范围时,ch则会变强制转化为8位变量(即取其低八位传过去输出),当为负数的时候,由于计算机存储负数是用补码表示的,所以传过去的二进制补码也被当做正数处理,也是取其低八位
    getchar()和putchar()函数包含在头文件stdio.h中,使用时需先声明此头文件
    在这里插入图片描述

    原文连接:详解getchar和putchar

    #include
    int main()
    {
    	int ch = 0;
    	ch = getchar();
    	putchar(ch);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行效果就是:输入一个字符,按下回车,屏幕上会在下一行打印这个字符

    • 小问题解答:为什么ch是整型变量却可以接收字符?
      我们可以看一下getchar函数到底长啥样的,右键getchar,选择转到定义
      在这里插入图片描述
      可以看到getchar()的返回值是int
      在这里插入图片描述

    使用代码清空缓冲区

    在这里引出getchar的目的其实来学习编写一个非常常用的清空缓冲区的小程序:

    	int tmp = 0;
    	while ((tmp = getchar()) != '\n')
    	{
    		;
    	}//清空缓冲区里的所有字符
    
    • 1
    • 2
    • 3
    • 4
    • 5

    while后的条件是getchar获取的字符不是“换行/回车”时,就跳出循环,其他所有字符都执行循环
    这个循环的循环体是一个“;”,这是啥?这表示的是一条空语句,也就是说我们啥都不干。所以这个循环的目的就是:getchar拉取缓冲区所有除了“回车”的字符,拉取到回车的时候跳出循环,由于回车是我们向缓冲区输入字符的终止命令,所以回车必然是缓冲区的最后一个字符。这样一来,就实现了清空缓冲区


    知识补充二:字符串比较函数strcmp

    使用函数需要引用头文件string.h
    语法是

    strcmp (字符串1,字符串2);

    结果会返回整型值,
    若字符串1和字符串2的每个字符都相等,则返回0;
    若字符串1与字符串2不相等:
    比较第一对不相等的字符的ASCII码值,谁的值大就代表哪个字符串大
    若字符串1>字符串2,则返回正数;
    若字符串1<字符串2,则返回负数。


    代码实现模拟输入密码

    我们来编写一个模拟我们日常输入密码的小程序
    程序的功能是这样的:我们先自己创建密码,然后确认密码,然后输入密码。有三次输入密码的机会,一次正确就跳出循环,如果都输错了就没有机会了。
    思路分析:
    我们需要进行三个步骤,一个是创建密码,一个是确认密码,一个是登录时输入密码
    思路转化成代码:
    首先考虑需要创建的变量,我们需要创建三个字符数组来存储这三次键入的密码。每次输入密码后需要比较密码,需要用到刚刚讲过的字符串比较函数,需要用到判断结构,字符串相等就说明密码正确,不等即错误。仅有三次输入密码的机会,需要用到循环结构,在次数为三的时候跳出循环。确认密码失败的时候要结束程序,使用goto语句直接跳转到程序末尾。每次输入密码时,为了保证读取的就是当前输入的东西,要使用刚刚讲的技巧清空缓冲区的字符。
    给出原码:

    #include
    #include
    int main()
    {
    	char password[20] = { 0 };
    	printf("请创建初始密码:\n");
    	scanf("%s", password);
    	int tmp = 0;
    	while ((tmp = getchar()) != '\n')
    	{
    		;
    	}//清空缓冲区里的所有字符
    	printf("请确认密码:\n");
    	char password1[20] = { 0 };
    	int i = 0;
    	for (i = 0; i < 3; i++)
    	{
    		scanf("%s", password1);
    		if (strcmp(password, password1) == 0)
    		{
    			printf("确认密码正确,已自动储存\n");
    			break;
    		}
    		else
    		{
    			printf("确认密码失败,请重新输入\n");
    		}
    	}
    	if (i == 3)
    	{
    		printf("确认密码错误,退出程序\n");
    		goto end;
    	}
    	int tmp1 = 0;
    	while ((tmp1 = getchar()) != '\n')
    	{
    		;
    	}
    	printf("请输入密码:\n");
    	char password2[20] = { 0 };
    	int j = 0;
    	for (j = 0; j < 3; j++)
    	{
    		scanf("%s", password2);
    		if (strcmp(password, password2) == 0)
    		{
    			printf("登录成功!\n");
    			break;
    		}
    		else
    		{
    			printf("密码错误,请重新输入:\n");
    		}
    	}
    	if (i == 3)
    	{
    		printf("三次密码均错误,退出程序\n");
    	}
    end:
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    在这里插入图片描述


    人生第一款小游戏:猜数字小游戏


    知识补充三:时间戳与生成随机数

    如何在C语言中生成一个随机数呢?我们可以直接调用库函数rand(),它的头文件是stdlib.h
    来看一下效果:

    #include
    #include
    int main()
    {
    	int a = rand();
    	printf("%d", a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    随机数是不是就生成成功了呢?并不是,当我们多次运行程序时,结果是:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这是为什么呢?
    原来C语言规定使用rand()函数前必须先调用函数srand()函数来设置随机数的生成器,查阅库函数表可知srand()有参数,是unsigned int(无符号整型),我们随便输一个100进去,来看一下效果:

    #include
    #include
    int main()
    {
    	srand(100);
    	int a = rand();
    	printf("%d", a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    结果是365,和上面的41不一样了
    当我们重复运行时
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    还是365?怎么又是一个确定的值了呢?我们试着改变一下srand的参数,比如输个200

    #include
    #include
    int main()
    {
    	srand(200);
    	int a = rand();
    	printf("%d", a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    结果是691,也就是说生成的数值会随着srand参数的变化而变化
    那我们现在就需要一个不受人为控制的,不断的变化的数,来充当srand()的参数,这样就可以生成随机数了
    在此引入时间戳的概念。时间戳是我们系统的时间转换出来的一个数字
    给出网页链接,大家可以看看自己系统的时间是怎么转换成一个常数的(其实是现在的时间相较于你这台计算机出生的时间的差值,可以说是你这台计算机的年龄)

    在线时间戳转换

    那怎么用时间戳呢?时间戳的函数是time(),返回值是一个有符号整型,为了配合srand函数我们使用一下强制类型转换;time()有参数,但是我们这里不需要用,所以参数写NULL;time()有头文件,名为time.h

    #include
    #include
    #include
    int main()
    {
    	srand((unsigned int)time(NULL));
    	int a = rand();
    	printf("%d", a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    看一下结果:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我们终于生成了随机数!


    代码实现猜数字小游戏

    游戏规则是这样的:
    我们在程序中产生一个0-100之间的随机数,然后我们来不断猜它,猜大了就输出猜大了,猜小了就输出猜小了,最后看看谁猜的次数最少
    思路分析:
    我们刚刚已经知道了怎么产生随机数,现在要做的就只需要读取玩家输入的数字,和这个随机数不断作比较,我们再给出比较的结果提示就好了
    思路转化成代码:
    刚刚产生的随机数过大,我们需要的是生成1-100的随机数,我们将上面用时间戳生成的随机数对100取模,这样生成的随机数就是0-99了,然后再+1,这样范围就是1-100了:

    #include
    #include
    #include
    int main()
    {
    	srand((unsigned int)time(NULL));
    	int a = rand();
    	int b = a % 100 + 1;
    	printf("%d", b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在主程序里,为了让我们的游戏更有模有样,我们来打印一个菜单,使用函数来写放在主程序外部,这样主程序比较清晰。打印出菜单以后我们需要赋予菜单功能,所以需要定义一个变量存储玩家输入的1/0的指令,判断是否游玩需要用到选择结构,不断游玩需要用到循环结构。然后整个游戏的程序我们再定义一个函数game放在主程序外部
    在game函数中,变量定义上,我们需要用刚刚产生随机数的方法来产生随机数,需要一个guess变量来存储玩家输入的数,比较玩家的数和随机数的大小需要用到选择结构,给出提示需要在每次判断后打印出提示语句。再一次游玩中,还需要定义一个变量num来记录猜数字的次数,每次猜错都要+1,加上最终猜对的那一次,一共需要(猜错次数+1次),所以变量初始化为1.每一次游玩结束,为了使用户体验更好,还可以穿插system(“cls”)语句来清空屏幕。
    给出原码:

    #include
    #include
    #include
    #include
    #include
    void menu()
    {
    	printf("******************************\n");
    	printf("********   1: play    ********\n");
    	printf("******************************\n");
    	printf("******************************\n");
    	printf("********   0: exit    ********\n");
    	printf("******************************\n");
    
    }
    
    void game()
    {
    	srand((unsigned int)time(NULL));
    	int a = rand();
    	int b = a % 100 + 1;
    	int guess = 0;
    	int num = 1;
    	while (1)
    	{
    		printf("请猜数字(1-100):");
    		scanf("%d", &guess);
    		if (guess < b)
    		{
    			printf("猜小了\n");
    			num++;
    		}
    		else if (guess > b)
    		{
    			printf("猜大了\n");
    			num++;
    		}
    		else
    		{
    			printf("恭喜你,猜中啦!\n");
    			printf("你一共用了%d次\n", num);
    			break;
    		}
    	}
    }
    int main()
    {
    	int input = 0;
    	menu();
    	do
    	{
    		printf("请选择是否玩耍(1/0):");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			system("cls");
    			printf("猜数字游戏开始!\n");
    			Sleep(2000);
    			system("cls");
    			game();
    
    			break;
    		case 0:
    			Sleep(200);
    			system("cls");
    			printf("已退出游戏\n");
    			break;
    		default:
    			printf("选择错误,请重新选择\n");
    			break;
    
    		}
    	} while (input);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    下面是游玩截图
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    人生第一款“黑客”软件:强制关机小程序

    知识补充四:调用系统命令行

    我们的电脑(windows系统)有一个应用程序叫cmd——命令提示符。我们在这个提示符里输入一些指令,电脑就会自动的根据指令做出行动。
    在程序中调用的语法是

    system(“命令行内容”);

    system函数的头文件是stdlib.h
    关机的命令行是shutdown -s -t 60
    shutdown -s是设置关机,-t是倒计时,60是60秒
    取消关机的命令行是shutdown -a

    代码实现强制关机小程序

    这个程序的要求是可以让电脑自动进入倒计时为一分钟的关机程序,如果用户输入“我是猪”,就可以结束关机
    思路分析:
    我们既然直接进入关机,那么就直接调用系统命令行输入命令即可。然后再用选择语句判断一下,如果用户很乖,确实输入的是“我是猪”,那就再次调用系统命令行输入终止关机的命令
    思路转化成代码:
    变量定义部分只需要一个变量来存储用户输入的内容,这个内容是汉字,我们需要使用字符串数组,数组长度给一个大一点的数(20就够了)。判断字符串是否是“我是猪”需要用到字符串比较函数strcmp()。如果用户不输入“我是猪”,就用goto跳转到scanf语句继续接受内容。

    #include
    #include
    #include
    int main()
    {
    	char input[20] = { 0 };
    	system("shutdown -s -t 100");
    	printf("同学,你的电脑将在100秒内关机\n");
    again:
    	printf("如果你输入:我是猪,就取消关机\n");
    	scanf("%s", input);
    	if (strcmp(input,"我是猪") == 0)
    	{
    		system("shutdown -a");
    	}
    	else
    	{
    		printf("不乖的话你的电脑就要关机了哦");
    		goto again;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    同学们可以自己和好朋友之间玩玩,也可以自己修改强制输入的内容。但是一定不要过火,分寸很重要哦!

  • 相关阅读:
    【MySQL数据库原理】在MySQL Workbench界面运行SQL代码——学生管理系统
    autojs(意图篇之startActivity)
    【数据结构练习题】二叉树(1)——1.相同的树2.另一颗树的子树3.翻转二叉树4.平衡二叉树5.对称二叉树
    【stack题解】最小栈 | 栈的压入、弹出序列
    硬件电子基础 -单片机信号转换
    【JavaEE进阶系列 | 从小白到工程师】Date类的构造方法以及SimpleDateFormat构造方法与日期转换详解上篇
    TCP流套接字编程
    NSSCTF第十页(2)
    LVS keepalived实现高可用负载群集
    微信小程序授权登录?
  • 原文地址:https://blog.csdn.net/qq_51379868/article/details/126553722