C语言 详解如何编写闪烁显示字符串的函数

         如果要实现指定字符串在标准输出流(一般为显示器)上闪烁,可以定义如下函数:

void bput(const char*s,int appe,int disa,int repe)

        字符串s出现appe秒后,消失disa秒,重复以上操作repe次返回到调用方。

一、具体代码

#include<time.h>
#include<stdio.h>
#include<string.h>

void bput(char*s,int appe,int disa,int repe)
{
	int char_len = strlen(s);
	for(int i = 0;i < repe;i++)
	{
		printf("\r%s",s);
		clock_t t1 = clock();
		clock_t t2 = 0;
		while(1000*(t2-t1)/CLOCKS_PER_SEC<appe)
		{
			t2 = clock();
		}
		printf("\r%*s",char_len,"");
		clock_t t3 = clock();
		clock_t t4 = 0;
		while(1000*(t4-t3)/CLOCKS_PER_SEC<disa)
		{
			t4 = clock();
		}
	}
}

int main()
{
	int appe = 0;
	int disa = 0;
	int repe = 0; 
	char s[20] = "";
	printf("输入一个长度20以内的字符串:>");
	gets(s);
	printf("输入显示的毫秒数,消失的毫秒数,反复执行的次数(以空格隔开)");
	scanf("%d %d %d",&appe,&disa,&repe);
	bput(s,appe,disa,repe);
	return 0;
}

        让我们来具体解读一下bput函数的内容。

二、strlen函数:查询字符串的长度

                  strlen

头文件        #include<string.h>
格式           size_t  strlen(const  char *s)
功能           计算s所指定的字符串长度(不包含空字符的字符数)
返回值       返回值size_t表示末尾的空字符前面的字符的个数

        函数接受的参数为字符指针或字符数组,不要随意改动字符串,改动后地址将会发生变化,所以用const修饰。

#include<stdio.h>
#include<string.h>
int main()
{
	const char*a = "ABCDEF";
	const char b[] = "ABCDEF";
	int a_len = strlen(a);
	int b_len = strlen(b);
	printf("%d %d",a_len,b_len);//运行结果为6 6
	return 0;
}

三、clock函数

                  clock
头文件        #include<time.h>
格式           clock_t   clock()
功能           求处理器调用某个进程所花费的时间

返回值        从定义与程序启动相关的编程环境的时间点起,用处理系统的最佳逼近返回程序占用处理

                   器的时间。默认返回为clock_t型时钟周期的总数,为了以秒为计量单位,必须用本函数除

                   以CLOCKS_PER_SEC宏的值。如果无法获取处理器调用该进程所花费的时间,或无法显

                   示数值,就返回值(clock_t)-1。(加粗的字体后面会解释)

        这里可以具体化为下图

        得到时钟数后除以CLOCKS_PER_SEC宏的值(该编译环境下为1000)即可得到该次调用clock函数时,程序历经的时间(秒)

        clock_t型:该编译环境下将clock_t等同于unsigned型。clock_t等同于哪种类型(unsigned、unsigned long……)由编译环境决定。

        CLOCKS_PER_SEC宏:由头文件<time.h>定义。直译为“每秒的时钟数”,如果时钟的精确度为0.001秒,那么一秒内就有1000个时钟,这个宏的值就定义为1000。不同的硬件和OS会导致时钟的精确度也不同,所以clock_t型表示数值的单位也取决于编程环境。

        (clock_t)-1:指将-1强制转换成clock_t型,而不是指clock_t的值减1。

       

        我们可以使用clock函数求两个时间点的差值以计算两次clock函数的时间点之间的时钟差:

#include<stdio.h>
#include<time.h>
int main()
{
	clock_t t1 = clock();//计时起点 
	clock_t t2 = 0;
	/*
	一
	段
	程
	序 
	*/
	t2 = clock();//计时终点 
	double t = (t2 - t1)/CLOCKS_PER_SEC;//时钟差除以每秒时钟数,计算时间差(秒) 
	printf("运行这段程序用了%lf秒",t);
	return 0;
}

         如果我们先定义t1,再在一个循环内不断更新t2的值,并将(t2-t1)/CLOCKS_PER_SEC<x(x为指定秒数)作为循环的判断条件,即可达到使程序暂停x秒后再运行(在此时间段内运行循环)的效果:

#include<stdio.h>
#include<time.h>
int main()
{
	clock_t t1 = clock();//计时起点 
	clock_t t2 = 0;
	int x = 0;
	scanf("%d",&x);
	while((t2-t1)/CLOCKS_PER_SEC<x)
	{
		t2 = clock();//更新t2的时钟数
	}
	return 0;
}

        综上易知,如果将(t2-t1)/CLOCKS_PER_SEC的分母乘1000,就可以得到程序运行的毫秒数。

#include<stdio.h>
#include<time.h>
int main()
{
	clock_t t1 = clock();
	clock_t t2 = 0;
	int x = 0;//此时x为毫秒数
	scanf("%d",&x);
	while(1000*(t2-t1)/CLOCKS_PER_SEC<x)//分母乘1000,与毫秒作比较
	{
		t2 = clock();
	}
	return 0;
}

        当然,使用clock函数来使程序暂停运行的效果,Sleep函数也可以达到:

#include<stdio.h>
#include<windows.h>//头文件windows.h
int main()
{
    int x = 0;
    scanf("%d",&x);
    Sleep(x);//参数x为毫秒数
	return 0;
}
#include<stdio.h>
#include<windows.h>//头文件为windows.h
int main()
{
	int a = 300;
	for(int i = 0;i<10;i++)
	{
		printf("\rABC");
		Sleep(a);//参数可为变量
		printf("\r%*s",3,"");
		Sleep(300);//参数可为常量
	}
	return 0;
}

        Sleep(int)函数的头文件为windows.h,参数可以为变量或常量。

        使用如上的代码也可以实现字符串的闪烁显示,下面介绍\r%*s使标准输出流上的字符串"ABC"和三个""交替覆盖显示的原理。

四、\r  、%*.*

        回车符\r:输出回车符\r后,显示光标就会移动到本行开头。本行已显示字符串b的情况下,在\r后显示的内容a都将覆盖本行已有的内容b。如果a的长度大于b,那么将完全覆盖b的内容;如果a的长度小于b,那么a只从左往右数覆盖等于a长度的内容,其它内容不变。

#include<stdio.h>
#include<windows.h>
int main()
{
	char*b = "最开始bbbbb";
	printf("%s",b);
	Sleep(1000);
	char*a = "修改后aaaaa";
	printf("\r%s",a);
}

        输出内容:

        ****一秒后 

         如果修改后内容的长度比修改前的内容短,

#include<stdio.h>
#include<windows.h>
int main()
{
	char*b = "最开始bbbbb";
	printf("%s",b);
	Sleep(1000);
	char*a = "修改后aa";
	printf("\r%s",a);
}

        就会出现以下输出内容:

         如果在循环中反复在本行开头显示两个字符串,让空白字符串和要显示的字符串交替覆盖,两个字符串等长或是空白字符串大于要显示的字符串时,即可达到让字符串闪烁显示的效果:

#include<stdio.h>
#include<windows.h>
int main()
{
	char*b = "最开始bbbbb";
	char*a = "           ";
	for(int i = 0;i<10;i++)//闪烁10次 
	{
		printf("\r%s",b);
		Sleep(300);
		printf("\r%s",a);
		Sleep(300);
	}
}

        在自定义字符串内容的情况下,提前准备一个等长的空白字符串显然不现实,那么我们可以用printf函数中的%*.*来控制输出的空白数量。然而这些"*"都可以替换为数字来实现printf函数中输出内容外指定"*"的值而达到的效果。        

        

        先讨论句点(.)左边的"*"。左边的"*"可以控制输出内容的最小输出宽度,如果输出内容达不到最小输出宽度,则在左侧用空格补全至最小宽度(在左侧指定了"-"的情况下,在右侧补全空格至最小宽度)。这个"*"也可以替换为数字来实现相同效果:

include<stdio.h>
int main()
{
	int a = 20;
	printf("%*d",4,a);//输出结果为:  20(共有4个字节的长度)   
	printf("%4d",a);//输出结果与在内容外控制"*"的值的效果相同
}

        如果将printf函数要输出的内容改变成一个空字符串,并使用变量改变"*"的数值,以此输出内容的宽度,就可以输出自己指定长度的空白:

#include<stdio.h>
int main()
{
	int len= 0;
	scanf("%d",&len);
	printf("\r%*s",len,"");//""代表输出空字符串 
}

        这样就可以得到想要长度的空白了。

        句点(.)右侧的"*"(同时也可以是数字)在不同情况下的作用不同,总体概括为精度:

  • d、i、o、u、x、X(整形)情况下,代表最小输出位数。
  • e、E、f(浮点型)情况下,代表小数点后的输出位数。
  • g、G(指数型)情况下,代表有效位数。
  • s(字符串)情况下,代表从字符串中能输出的最大字符数。

五、总结

        有了这些基础知识之后,我们再来看开头的函数就轻松得多了:

#include<time.h>
#include<stdio.h>
#include<string.h>

void bput(char*s,int appe,int disa,int repe)//appe和disa为毫秒数,所以后边要*1000
{
	int char_len = strlen(s);//测得字符串数组s的长度
	for(int i = 0;i < repe;i++)//重复repe次循环
	{
		printf("\r%s",s);//将光标移动到开头,并输出字符内容
		clock_t t1 = clock();//初始化并开始记录此时的时钟数t1
		clock_t t2 = 0;//初始化t2
		while(1000*(t2-t1)/CLOCKS_PER_SEC<appe)//appe为毫秒数,所以前面乘1000
		{                                      //显示appe毫秒
			t2 = clock();//随时更新t2的时钟数
		}
		printf("\r%*s",char_len,"");//利用句点前的*输出和s等长的空白字符串(宽度相等的空字符串)
		clock_t t3 = clock();//同t1,记录此刻时钟数
		clock_t t4 = 0;
		while(1000*(t4-t3)/CLOCKS_PER_SEC<disa)//消失disa毫秒
		{
			t4 = clock();
		}
	}
}

int main()
{
	int appe = 0;
	int disa = 0;
	int repe = 0; 
	char s[20] = "";
	printf("输入一个长度20以内的字符串:>");
	gets(s);
	printf("输入显示的毫秒数,消失的毫秒数,反复执行的次数(以空格隔开)");
	scanf("%d %d %d",&appe,&disa,&repe);
	bput(s,appe,disa,repe);
	return 0;
}

        当然这里的两次停顿也可以在引入windows.h头文件后使用Sleep函数代替。

//本人是刚接触c语言不久的小白,如有错误和不足还请指正:)

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ioveCorp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值