C learning_7

news2024/11/17 21:26:15

目录

1.for循环

1.虽然while循环和for循环本质上都可以实现循环,但是它们在使用方法和场合上还是有一些区别的。

2.while循环中存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样 查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

2.break和continue在for循环中

3.左值和右值

4.do...while()循环

5.do while循环中的break和continue

6.小练习锻炼一下

1. 计算 n的阶乘。

2. 计算 1!+2!+3!+……+10!

3. 在一个有序数组中查找具体的某个数字n。(讲解二分查找)

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

5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则 提示登录成,如果三次均输入错误,则退出程序。


1.for循环

我们已经知道了while循环,这次我们就来介绍for循环呢?

for循环是一种常见的循环结构,它可以重复执行一段代码多次,直到特定的条件满足为止。

它的语法如下:

for (初始化语句; 循环条件; 循环后操作)

{    

        //执行的代码块

}

其中,初始化语句用于初始化循环控制变量,循环条件是一个布尔表达式,如果为true,则继续执行循环,否则退出循环,循环后操作是在每次循环结束时执行的语句。

for循环的执行过程如下:

1. 执行初始化语句

2. 检查循环条件,如果为false,则退出循环,执行后续语句。

3. 执行代码块。

4. 执行循环后操作

5. 回到第2步,继续执行循环,直到循环条件为false。

for循环广泛应用于迭代数组、列表、集合等数据结构,以及重复执行固定次数的任务。

#define _CRT_SECURE_NO_WARNINGS 1

//for循环使用
#include<stdio.h>
int main()
{
	int i = 0;
	//打印一次i的值
	i++;
	printf("%d\n", i);
	
	//当我们要多次打印时,这时就需要用到循环
	//先用我们上次介绍的while
	i = 0;//1.初始化
	while (i < 10)//2.判断
	{
		i++;//3.调整
		printf("%d ", i);
	}

	//我们发现while循环中由三部分
	//1.初始化 2.判断 3.调整
	//而这是组成循环的必要条件
	//接下来我们看看for语句如何完成上面的while语句
	i = 0;
	for (i = 1; i <= 10; i++)
	//   初始化  判断   调整
	{
		printf("%d ", i);
	}
	//我们发现for也有1.初始化 2.判断 3.调整
	//所以for语句也具有while语句一样的循环功能
	return 0;
}

既然我们有了while语句可以实现循环,为什么还要推出一个功能相同的for语句呢?

1.虽然while循环和for循环本质上都可以实现循环,但是它们在使用方法和场合上还是有一些区别的。

        for循环主要用于对一定次数的重复操作,特别适用于遍历数组或集合,将数组或集合中的每一个元素作为一个循环变量使用。同时,for循环的代码结构非常紧凑,for()的括号中包含了循环变量的初始化、循环条件的判断和循环变量的更改,可以在一行代码中完成循环的控制,适用于代码简洁的场景。

        而while循环则主要适用于需要根据一定的条件来重复执行操作的场景,比如用户输入信息的验证和检查等。while循环的代码结构相对比较灵活,可以根据不同的需求设置不同的循环条件,灵活控制循环的执行。

2.while循环中存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样 查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

int i = 0; //实现相同的功能,使用while

i=1;//初始化部分

while(i<=10)//判断部分

{

        printf("hehe\n");

        .

        .(省略多行代码)

        .

        i = i+1;//调整部分

}

//实现相同的功能,使用for

for(i=1; i<=10; i++)

{

        printf("hehe\n");

}

2.break和continue在for循环中

//代码1
#include <stdio.h>
int main()
{
    int i = 0;
    for (i = 1; i <= 10; i++)
    {
        if (i == 5)
            break;//跳出循环
        printf("%d ", i);//1 2 3 4
    }
    return 0;
}


//代码2
#include <stdio.h>
int main()
{
    int i = 0;
    for (i = 1; i <= 10; i++)
    {
        if (i == 5)
            continue;//跳出本次循环
        printf("%d ", i);//1 2 3 4 6 7 8 9 10
    }
    return 0;
}

在for循环里,我们要注意两个问题:

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

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i = 5)
		//if(i=5)将5赋给i,使得if语句括号的内容恒为真,造成死循环
        //当i为1,进入循环,此时又将i=5,由于为真,执行continue,不执行打印,
          随后i++,i=6,进入循环
			continue;
		printf("%d ", i);
	}
	return 0;
}

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

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	for (i = 0; i < 10; i++)
	//前闭后开容易观察到循环的次数 - 10次
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

​

接下来,我们来看四个for相关的代码,看看为什么

代码1

#include <stdio.h>
int main()
{
    //代码1
    for (;;)
    {
        printf("hehe\n");
    }
    return 0;
}

        这个程序有一个无限循环,它会不停地输出"hehe",直到程序被手动停止或者出现了某些异常情况。其中的for(;;)这一行是一个无限循环的语法结构,相当于while(true)或者while(1),表示循环条件永远为真,因此永远不会退出循环。如果运行这个程序,它会一直输出"hehe",直到你手动停止它。所以在for语句中,我们一定不要省略判断条件,否则就会导致程序进入死循环。

代码2

#include<stdio.h>
int main()
{
    int i = 0;
    int j = 0;
    //这里打印多少个hehe?
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j < 10; j++)
        {
            printf("hehe\n");
        }
    }
    return 0;
}

        这个程序会打印100次"hehe",因为它有两个嵌套的for循环。外层的循环从i=0开始,每次循环增加1,当i<10时继续执行。内层的循环从j=0开始,每次循环增加1,当j<10时继续执行。因此,内层循环每循环一次,都会输出一次"hehe",外层循环控制内层循环的执行次数,因此内层循环总共会执行10次,输出10次"hehe",而外层循环也会循环10次,因此总共会输出100个"hehe"。

代码3

#include<stdio.h>
int main()
{
    int i = 0;
    int j = 0;
    //如果省略掉初始化部分,这里打印多少个hehe?
    for (; i < 10; i++)
    {
        for (; j < 10; j++)
        {
            printf("hehe\n");
        }
    }
    return 0;
}

这个程序会打印10次"hehe",当第一次循环时,i = 0,内循环开始第一次执行进入内循环中,j的值从0到9共10次,会打印10次"hehe",当j<10不满足时,跳到外循环,然后执行i++;i=1,进入内循环,但是此时内循环的j的值已经是10了,j的值没有重新赋值为零,所以j<10不满足,就不打印"hehe",之后随着进行i<10和i++,程序j<10还是不满足,始终不能打印"hehe"。

代码4

#include<stdio.h>
int main()
{
    int x, y;
    //使用多余一个变量控制循环
    for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
    {
        printf("hehe\n");
    }
    return 0;
}

在这个程序中,使用了两个变量`x`和`y`来控制循环。其中,变量`x`初始化为0,变量`y`也初始化为0,它们分别作为两个测试条件。在每次循环开始前,表达式`++x`和`y++`会分别对它们进行自增1的操作。 循环的循环条件是`x < 2 && y < 5`,也就是当`x`小于2且`y`小于5时,循环继续执行。在每次循环体中,都会输出一次字符串"hehe"。当`x`自增到2时,循环条件`x<2`不再成立,循环退出,本程序就结束打印"hehe"了。

接下来我们就练习一下,看看你有没有掌握

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

在这个程序中,循环的循环条件是`k = 0`,每次循环都会将变量`k`赋值为0并判断赋值结果的真假,因为0被认为是“假”,所以循环条件的结果永远为假,循环不会进入。因此,这个程序不会循环一次,直接返回0。上面的k=0,就是那个循环条件就变为0了,0为假,程序的循环条件i就不会满足。下面举个例子看看这种写法的值

 可以看出b=7结果就是7,所以k=0结果就是0。

3.左值和右值

在计算机编程中,每一个变量都有一个存储它的内存位置,我们称之为左值(L-value)。左值可以出现在赋值语句的左边或右边。当左值出现在赋值语句的左边时,我们可以把它看做一个存储值的容器,我们可以给它赋一个新的值,或者修改它的值。

在赋值语句中,右边的值叫做右值(R-value),它是一个可以被赋给左值的值。右值可以是常量、变量、表达式或函数调用的返回值。当右值出现在赋值语句的左边时,它是无效的。

例如,如果我们定义一个变量`a`,那么`a`就是其内存位置的左值。当我们对`a`进行赋值操作时,`a=10`这个赋值语句中的`10`就是右值,它被赋给了变量`a`,`a`的值变成了`10`。

总之,左值是一个标识符,它表示一个存储值的对象或容器,而右值是一个可以被赋给左值的值。

#include<stdio.h>
int main()
{
	int a = 10;
	// a - 左值
	a = 20;//其实是把20放到a的这块空间,这里使用的是a的空间

	// a - 右值
	int b = a;//其实是使用了a中存放的值,把a中的20存到b中

	return 0;
}

接下来我们在介绍一个循环

4.do...while()循环

        do...while()循环是一种循环结构,在循环体至少执行一次后才判断循环条件是否为真。它的语法结构如下:

do {

        循环体语句块

} while (循环条件);

do...while()`循环先执行一次循环体语句块,然后判断循环条件是否为真,如果循环条件为真,则继续执行循环体语句块,直到循环条件为假时退出循环。

和`while`循环和`for`循环不同,`do...while()`循环的循环条件在循环体语句块后面,因此无论循环条件是否为真,循环体至少会被执行一次。

//使用do - while()语句打印1-10
#include <stdio.h>
int main()
{
    int i = 1;//初始化
    do
    {
        printf("%d ", i);
        i = i + 1;//调整
    } while (i <= 10);//判断
    return 0;
}

5.do while循环中的break和continue

#include <stdio.h>
int main()
{
    int i = 1;
    do
    {
        if (5 == i)
            break;
        printf("%d ", i);//1 2 3 4
        i = i + 1;
    } while (i <= 10);

    return 0;
}


#include <stdio.h>
int main()
{
    int i = 1;

    do
    {
        if (5 == i)
            continue;
        printf("%d ", i);//1 2 3 4 死循环
        i = i + 1;
    } while (i <= 10);

    return 0;
}

6.小练习锻炼一下

1. 计算 n的阶乘。

/*
	1. 计算 n的阶乘。
	5! = 1*2*3*4*5
	n! = 1-n 累积相乘
*/
#include<stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);//不考虑溢出
	int i = 0;
	int num = 1;
	//产生1-n的数字然后进行累积相乘
	for (i = 1; i <= n; i++)
	{
		num *= i;
	}
	printf("%d\n", num);
	return 0;
}

        该程序实现了计算输入的正整数n的阶乘。 程序从标准输入中读入一个整数n,然后使用for循环计算1到n的乘积,并将结果存储在变量num中。for循环中的变量i从1开始,每次循环将i乘以num,最后num就是1到n所有数字的乘积,即n的阶乘。 最后,程序使用printf函数将计算结果打印到标准输出中,并返回0表示程序正常结束。 需要注意的是,该程序没有对计算结果进行溢出检查和处理,当n比较大时,计算结果可能会超过int类型的取值范围。需要使用高精度计算或其他方法来避免溢出。

2. 计算 1!+2!+3!+……+10!

//写法一
#include<stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	int i = 0;
	int sum = 0;
	int num = 1;
	for (i = 1; i <= n; i++)
	{
		num *= i;
		sum += num;
	}
	printf("%d\n", sum);
	return 0;
}


//写法二
#include<stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	int sum = 0;
	int num = 1;
	for(n=1;n<=3;n++)
	{
		for (i = 1; i <= n; i++)
		{
			num *= i;
		}
		sum += num;
	}
	printf("%d\n", sum);//15
	//结果不对,1!+2!+3!=9
	//?
	return 0;
}

        该程序的目标是计算1到3的所有数字的阶乘之和。程序使用两个嵌套的for循环实现了该目标。

        内层循环计算一个数字的阶乘并将其累加到sum中,外层循环控制计算1到3的所有数字。然而,在计算阶乘时,程序没有将变量num重置为1,导致计算每个数字的阶乘时都是在上一个数字的阶乘的基础上进行乘法运算,所以程序计算的结果是错误的。

        例如,第一次循环时,计算n=1时的阶乘,num的值为1,计算1的阶乘时sum加上了1。但是在计算n=2时的阶乘时,num的值已经是1的阶乘结果,即num=1,而不是重新开始计算2的阶乘,导致程序计算的结果错误。

        解决该问题的方法是,在内层循环中,每次计算阶乘之前都将num重置为1。

修改后的程序如下:

#include <stdio.h>

int main() {
    int n = 0;
    int i = 0;
    int sum = 0;
    int num = 1;
    for (n = 1; n <= 3; n++) {
        num = 1; // 重置num的值为1
        for (i = 1; i <= n; i++) {
            num *= i;
        }
        sum += num;
    }
    printf("%d\n", sum); // 输出结果:9
    return 0;
}

现在程序输出的结果是正确的,即1的阶乘+2的阶乘+3的阶乘=1+2+6=9。

3. 在一个有序数组中查找具体的某个数字n。(讲解二分查找)

//这种写法是遍历数组寻找数字,虽然能找到,但是浪费了数字有序这个条件
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//升序的10个数字
	int k = 7;//要查找的数字
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		if (arr[i] == k)
		{
			printf("找到了,下标是:%d\n", i);
			break;
		}
	}
	if (i == 10)
		printf("找不到!\n");
	return 0;
}
//二分查找法
/*
	1.确定数组的范围的前后下标begin和end
	2.根据begin和end,确定中间的元素的下标end
	3.根据mid锁定的元素,和查找的元素比较,确定新的查找范围
	4.循环上面步骤,逐渐缩小begin和end的范围,确定能否找到k
*/
#include<stdio.h>
int main()
{
	int arr[] = { 8, 17, 26, 32, 40, 72, 87, 99 };//升序的8个数字
	int k = 40;//要查找的数字
	int length = sizeof(arr) / sizeof(arr[0]);//确定数组的元素个数
	int begin = 0;
	int end = length - 1;
	int flag = 0;
	while (begin <= end)
	{
		int mid = (begin + end) / 2;
		if (arr[mid] < k)
		{
			begin = mid + 1;
		}
		else if (arr[mid] > k)
		{
			end = mid - 1;
		}
		else
		{
			printf("找到了,下标是:%d\n", mid);
			flag = 1;
			break;
		}
	}
	if(flag == 0)
		printf("找不到!\n");
	return 0;
}

         该程序实现了二分查找法,用于在一个已知的升序数组中查找一个特定的数k。 程序的基本思路是将查找范围不断缩小,直到找到k或者查找范围变为空。 程序首先定义了一个有序的整型数组arr,并确定数组的元素个数length,以及要查找的数字k。然后定义begin和end表示查找的范围,一开始为数组的第一个和最后一个元素的下标。 程序使用while循环进行查找,每次循环将查找范围缩小一半。在每次循环中,程序使用mid表示查找范围中间元素的下标,并将k与arr[mid]进行比较。如果k小于arr[mid],则说明要查找的数字在mid的左边,将end赋值为mid-1;如果k大于arr[mid],则说明要查找的数字在mid的右边,将begin赋值为mid+1;如果k等于arr[mid],则说明找到了k,打印出mid的值,并设置flag为1表示找到了k。 当查找结束时,程序判断flag的值,如果为0,则说明没有找到k,输出“找不到!”。 需要注意的是,程序的正确性要求数组是有序的,并且每次循环都将查找范围缩小一半,所以时间复杂度为O(log n)

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

/*
	输出格式:
	w##########################!
	we########################!!
	wel######################!!!
	welc####################a!!!
	welco##################ba!!!
	welcom################oba!!!
	welcome##############aoba!!!
	welcome ############iaoba!!!
	welcome t##########xiaoba!!!
	welcome to########uxiaoba!!!
	welcome to ######huxiaoba!!!
	welcome to b####nhuxiaoba!!!
	welcome to be##enhuxiaoba!!!
	welcome to benbenhuxiaoba!!!

	两组数据
	welcome to benbenhuxiaoba!!!
	############################
	left                   right
*/

#include<stdio.h>
#include<string.h>
#include<windows.h>
int main()
{
	char arr1[] = "welcome to benbenhuxiaoba!!!";
	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(1000);//休息1000毫秒
		left++;
		right--;
	}
	return 0;
}

        这段程序的功能是:输出一个类似于悬挂字的效果,将一段字符串从两端向中间逐步显示。 程序首先定义了两个字符数组arr1和arr2,分别为原始字符串和显示效果。同时定义了两个索引left和right,分别表示显示效果的左侧和右侧位置。初始时左侧位置为0,右侧位置为原始字符串长度减一。 然后进入while循环,循环条件是左侧位小置于等于右侧位置。在每次循环中,将arr1的左侧和右侧字符分别赋值给arr2的左侧和右侧位置,输出arr2,并使用Sleep函数暂停1000毫秒(即1秒),使效果更明显。然后分别将左侧位置和右侧位置向中间移动一个位置。由于每次循环都会将显示效果向中间显示一位,所以最终输出的结果为原始字符串从两侧向中间逐渐显示的效果。 需要注意的是,Sleep函数是Windows API提供的函数,可以让程序暂停一定的时间,单位是毫秒。在这段程序中,使用Sleep函数可以让效果看起来更加流畅自然。

5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则 提示登录成,如果三次均输入错误,则退出程序。

#include<stdio.h>
int main()
{
	char password[20] = { 0 };
	int i = 0;
	do
	{
		printf("请输入密码:>");
		scanf("%s", password);
		//两个字符串比较不能使用等号
		//需要使用库函数strcmp
		//strcmp返回值 = 0,表示字符串1 = 字符串2
		//strcmp返回值 > 0,表示字符串1 > 字符串2
		//strcmp返回值 < 0,表示字符串1 < 字符串2
		if (strcmp(password, "123456") == 0)
		{
			printf("密码正确\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
		i++;
	} while (i < 3);
	if (i == 3)
	{
		printf("登录失败\n");
	}
	return 0;
}

        这段程序的功能是:让用户输入密码,如果输入的密码是123456,则认为密码正确,程序结束;否则,提示密码错误并要求重新输入。当用户连续输入密码错误超过3次时,程序将退出。

        程序首先定义了一个长度为20的字符数组password,用于存储用户输入的密码。然后使用do-while循环,循环条件为i<3,即用户最多可以输入3次密码。在每次循环中,程序会提示用户输入密码,并使用scanf函数将输入的密码保存到password数组中。接着使用strcmp函数比较用户输入的密码和正确的密码是否相同,如果相同则输出"密码正确"并跳出循环;否则输出"密码错误"。

        在每次循环结束后,程序会将i加1。当i等于3时,表示用户已经连续输入3次密码错误,此时程序将输出"登录失败"并结束运行。如果用户在前3次内输入了正确的密码,则程序会在循环中使用break语句跳出循环,然后输出"密码正确"。

        需要注意的是,字符串比较时不能使用等号,需要使用库函数strcmp。strcmp函数的返回值为0表示两个字符串相同,返回值大于0表示第一个字符串大于第二个字符串,返回值小于0表示第一个字符串小于第二个字符串。在本程序中,如果strcmp函数的返回值为0,则表示用户输入的密码是正确的,程序将输出"密码正确"并结束运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/442101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2-黑马(十四)

目录&#xff1a; &#xff08;1&#xff09;实战-crud &#xff08;2&#xff09;实战--crud查询和删除 &#xff08;3&#xff09; 实战-crud-修改 &#xff08;1&#xff09;实战-crud 服务端的接口&#xff1a; 前端需要修改的地方&#xff1a;业务简单的一半需要改3个…

Vue 组件

文章目录 Vue 组件全局组件局部组件Prop动态 PropProp 验证 自定义事件 Vue 组件 组件&#xff08;Component&#xff09;是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素&#xff0c;封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用&#x…

Go程序开发快速入门

当进行Go程序开发时&#xff0c;需要注意以下几点&#xff1a; 1、代码可读性&#xff1a;尽可能使用有意义的变量名和注释&#xff0c;确保代码易于理解和维护。 2、错误处理&#xff1a;Go语言有很好的错误处理机制&#xff0c;应该合理地处理错误&#xff0c;以便于排除错…

【运动规划算法项目实战】路径规划中常用的插值方法

文章目录 简介一、线性插值代码实现二、三次样条插值三、B样条插值四、贝塞尔曲线插值总结简介 常见用于处理路径平滑的插值算法主要包括线性插值、三次样条插值、B样条插值和贝塞尔曲线插值等,下面分别介绍它们的优缺点和使用场景。 一、线性插值 线性插值是最简单的插值方…

ROS——Teb算法的优化

一、简介 “TEB”全称Time Elastic Band&#xff08;时间弹性带&#xff09;Local Planner&#xff0c;该方法针对全局路径规划器生成的初始轨迹进行后续修正(modification)&#xff0c;从而优化机器人的运动轨迹&#xff0c;属于局部路径规划。 关于eletic band&#xff08;橡…

Java 依赖注入(DI)

只要做过 Java 一段时间&#xff0c;基本上都会遇到这个问题。 Dependency Injection &#xff08;DI&#xff09;中文称之为依赖注入。 都说了 Spring 的关键部分就是 Dependency Injection &#xff08;DI&#xff09;&#xff0c;但是什么是依赖&#xff0c;为什么要注入&…

AirServer2023最新免费苹果电脑投屏工具

AirServer是一个Mac专用投屏工具&#xff0c;功能强大&#xff0c;并且可以通过网络和其他平台同步视频内容。可以使用多个设备进行投屏&#xff0c;快速查看同一局域网内的视频。支持的设备&#xff1a;苹果系统。支持 Windows、 Mac、 Android、 iOS、 windows平台。 1、支持…

用腾讯轻联,打通草料二维码与其他应用的连接

一、功能介绍 腾讯轻联是腾讯云推出的“应用连接器”&#xff0c;无需编程&#xff0c;实现多应用的连接。草料二维码作为首批入驻腾讯轻联的合作伙伴和腾讯团队进行了深度协同&#xff0c;提供给用户以下能力&#xff1a; 1.快速对接主流应用 实现企业微信、钉钉、腾讯文档…

基于AT89C52单片机的电子密码锁设计

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87688544?spm=1001.2014.3001.5503 源码获取 主要内容: 设计一个简易的电子密码锁,并进行仿真实验,该系统能够进行密码输入功能、上锁功能、在锁合状态下通过输入密码进行…

Java并发编程 —— 延迟队列DelayQueue源码解析

一、什么是DelayQueue DelayQueue是一个支持并发的无界延迟队列&#xff0c;队列中的每个元素都有个预定时间&#xff0c;当线程从队列获取元素时&#xff0c;只有到期元素才会出队列&#xff0c;没有到期元素则阻塞等待。队列头元素是最快要到期的元素。因此DelayQueue可用于…

[java聊天室]多个客户端与服务器说话多线程(二)

多客户端链接 之前(java聊天室一)只有第一个连接的客户端可以与服务端说话。 原因: 服务端只调用过一次accept方法&#xff0c;因此只有第一个客户端链接时服务端接受了链接并返回了Socket,此时可以与其交互。 而第二个客户端建立链接时&#xff0c;由于服务端没有再次调用…

【Hello Linux】线程池

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步 本篇博客简介&#xff1a;简单介绍linux中线程池概念 线程池 Linux线程池线程池的概念线程池的优点线程池的应用场景线程池实现 Linux线程池 线程池的概念 线程池是一种线程…

PyTorch深度学习实战 | 高斯混合模型聚类原理分析

01、问题描述 为理解高斯混合模型解决聚类问题的原理&#xff0c;本实例采用三个一元高斯函数混合构成原始数据&#xff0c;再采用GMM来聚类。 1) 数据 三个一元高斯组件函数可以采用均值和协方差表示如表1所示&#xff1a; ▍表1 三个一元高斯组件函数的均值和协方差 每个高斯…

git的使用——操作流程

一、什么是git git是一个开源的分布式版本控制软件&#xff0c;能够有效并高效的处理很小到非常大的项目。 二、添加SSH公钥 安装下载后&#xff0c;会发现鼠标右击&#xff0c;会出现 Git Bash Here 这个选项&#xff0c;如图所示&#xff0c;点击进入 1.打开git窗口后&…

018:Mapbox GL加载Google地图(影像瓦片图)

第018个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中加载google地图。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共80行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://xia…

鉴智机器人重磅发布双目智驾解决方案,新一代全系智驾产品线亮相上海车展

4月18日&#xff0c;以「拥抱汽车行业新时代」为主题的2023上海车展正式拉开帷幕。以视觉3D理解为核心的下一代自动驾驶系统提供商鉴智机器人&#xff0c;携全新升级的智驾产品线首次亮相车展&#xff0c;重磅发布基于AI的双目立体视觉智驾方案。 凭借双目立体视觉系统的差异化…

智能洗地机好用吗?值得入手的洗地机推荐

洗地机是一款高效的地面清洁设备&#xff0c;不仅可以很好清理地面不同形态的干湿垃圾&#xff0c;还减少了人工和水资源的浪费&#xff0c;是我们日常生活中必不可少的清洁工具。作为以一位评测博主&#xff0c;很多朋友咨询我在选购洗地机时应该注意哪些要点&#xff0c;有哪…

记一次生产要我狗命的问题

问题起因&#xff1a;引入disruptor框架 简单理解就是生产消费者模式 用来支持高并发 先说问题和改正 再展开 问题&#xff1a;没有当时的截图了 直接描述吧 问题就是cpu占用过高 居高不下的那种 排查&#xff1a;就是看线程名字和占用的大概 再根据近期发布的东西 再根据本地…

学系统集成项目管理工程师(中项)系列08b_合同管理(下)

1. 项目变更约定 1.1. 合同生效后&#xff0c;当事人不得因姓名、名称的变更或者法定代表人、负责人、承办人的变动而不履行合同义务 2. 违约责任的承担方式 2.1. 继续履行 2.2. 采取补救措施 2.3. 赔偿损失 2.4. 支付约定违约金或定金 3. 注意事项 3.1. 当事人的法律资…

Linux FTP服务

FTP服务 作用 传输文件 端口 FTP服务器默认使用TCP协议的20、21端口与客户端进行通信 20端口用于建立数据连接&#xff0c;并传输文件数据 21端口用于建立控制连接&#xff0c;并传输FTP控制命令 模式 FTP数据连接分为主动模式和被动模式 主动模式&#xff1a;客户端告诉服务端…