《C和指针》读书笔记(第九章 字符串、字符和字节)

news2024/11/15 17:02:53

目录

  • 0 简介
  • 1 字符串基础
  • 2 字符串长度
  • 3 不受限制的字符串函数
    • 3.1 复制字符串
    • 3.2 连接字符串
    • 3.3 函数的返回值
    • 3.4 字符串比较
  • 4 长度受限的字符串函数
  • 5 字符串查找基础
    • 5.1 查找一个字符串
    • 5.2 查找任何几个字符
    • 5.3 查找一个子串
  • 6 高级字符串查找
    • 6.1 查找一个字符串前缀
    • 6.2 查找标记
  • 7 错误信息
  • 8 字符操作
    • 8.1 字符分类
    • 8.2 字符转换
  • 9 内存操作
    • 9.1 memcpy和memmove真的不一样吗?
    • 9.2 memcmp:简单的比较
    • 9.3 memchr:简单的查找
    • 9.4 memset:初始化的值只能是0和-1?
  • 10 总结

0 简介

在C语言中,字符串和数组有很多相似之处,且官方提供了很多的库函数可供调用。那么字符串和数组这对姐妹花,究竟有着什么样的亲密关系,而作为我们本期的重点角色,字符串又有何独特之处呢?

C语言并没有显式的字符串数据类型,因为字符串以字符串常量的形式出现或者存储于字符数组中。字符串常量很适用于那些程序不会对它们进行修改的字符串。所有其他字符串都必须存储于字符数组或动态分配的内存中

本篇着重介绍了一些字符串常用的库函数,使大家在不同的情况下去选择最适合的库函数。下面是本文的内容概览

在这里插入图片描述

1 字符串基础

字符串就是一串0个多个字符,并且以一个位模式全为0NUL字节结尾。
例如:

	char message[] = "hello word";

2 字符串长度

字符串的长度就是字符串所包含的字符个数,并不包括最后一个终止符。这个在面试中会经常考查。

可以通过库函数strlen()来自动计算字符串的长度。
例如:

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

int main()
{
	char message[] = "hello word";
	printf("字符串的长度为:%d\n",strlen(message));
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
需要注意的是,该函数返回的是无符号数,因此通过该函数比较两个字符串的长度的时候需要格外注意:

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

int main()
{
	char message1[] = "hello word";
	char message2[] = "hello Shanghai";
	//比较方式1 
	if(strlen(message1) >= strlen(message2))
		printf("字符串1更长\n");
	else
		printf("字符串2更长\n");
	//比较方式2 
	if (strlen(message1) - strlen(message2) >= 0)
		printf("字符串1更长\n");
	else
		printf("字符串2更长\n");
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
因为返回的是无符号数,所以比较方式2中,条件判断的结果永远为真,导致判断结果出现错误。

3 不受限制的字符串函数

所谓的不受限制的字符串函数,是指在使用的时候,不需要指定字符串(实参)的长度,函数即可顺利运行。

3.1 复制字符串

复制字符串在开发中经常会用到,但是在复制到新的字符串中时,会覆盖掉原来的部分,所以需要格外注意。
例如:

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

int main()
{
	char message1[] = "hello word";
	char message2[] = "hello Shanghai";

	int message2_len = strlen(message2);

	printf("字符串2的长度为:%d\n", strlen(message2));

	strcpy(message2,message1);

	printf("字符串2的长度为:%d\n",strlen(message2));
	for(int i = 0; i < message2_len; i++)
		printf("%c",message2[i]);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
可以看到,在将字符串message1复制到message2之后,message2的长度居然都不一样了,这是为什么呢?

这是因为,在复制字符串的时候,顺便也将终止符复制了过来,在strlen()函数进行处理的时候,肯定就会返回10,从打印结果来看,message2的其余部分仍然被保留了下来。

而将较长字符串复制到较短的字符串中时,常常会报错,这是因为没有足够的空间去容纳需要复制的字符。

3.2 连接字符串

连接字符串的时候,可以使用strcat()函数。它的原型如下:

char *strcat(char *dst, char const *src);

举个例子:

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

int main()
{
	char message1[] = "hello word";
	char message2[] = "hello Shanghai";

	strcat(message1,message2);
	printf("%s\n", message1);

	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
可以看到,直接将两个字符串进行了拼接。新字符串的长度值是原来两个字符串的长度之和

3.3 函数的返回值

这些函数的返回值有时候是第一个参数的一份拷贝,因此可以嵌套使用,因为当字符串做实参的时候,传递的也是第一个元素的地址。所以这些函数经常可以嵌套地调用。
例如:

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

int main()
{
	char message1[] = "hello ";
	char message2[] = "word ";
	char message3[] = "Shanghai";

	strcat(strcat(message1, message2), message3);
	printf("%s\n", message1);

	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
但是为了程序的可读性,不嵌套也可以。

3.4 字符串比较

字符串比较,常用的库函数只有一个,就是strcmp。它的原型如下:

int  strcmp(char  const  *s1,  char  const  *s2);

这个函数的比较规则比较 有意思,该函数对两个字符串的字符逐个进行比较,直到发现不匹配为止,这里有两种情况:

  1. 最先不匹配的字符中在ASCII中排名靠前的那个字符所在的字符串被认为是较小的字符串;
  2. 如果开始部分的两个字符串都相等,那么较短的字符串被认为是较小的字符串。

字符串发现有不匹配的某个字符,即可得到对比结果,而无须比较剩余部分。
如下图所示:
在这里插入图片描述
看看实际的代码:

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

int main()
{
	char temp1[] = "hello";
	char temp2[] = "hello world";
	char temp3[] = "hello worLd";
	//字符串temp1和temp2作比较
	if(strcmp(temp1,temp2) == 0)
	{
		printf("temp1 = temp2\n");
	}
	else if (strcmp(temp1, temp2) > 0)
	{
		printf("temp1 > temp2\n");
	}
	else if (strcmp(temp1, temp2) < 0)
	{
		printf("temp1 < temp2\n");
	}
	printf("------------------\n");
	//字符串temp2和temp3作比较
	if (strcmp(temp2, temp3) == 0)
	{
		printf("temp2 = temp3\n");
	}
	else if (strcmp(temp2, temp3) > 0)
	{
		printf("temp2 > temp3\n");
	}
	else if (strcmp(temp2, temp3) < 0)
	{
		printf("temp2 < temp3\n");
	}

	printf("\n");
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述

4 长度受限的字符串函数

有的库函数在调用的时候,需要传入待处理的字符串的长度,因此称为长度受限的字符串函数。

这些函数提供了一种方便的机制,可以防止难以预料的长字符串从它们的目标数组溢出。
常见的有一下几个函数:

char    *strncpy(char  *dst,  char  const  *src,  size_t  len);
char    *strncat(char  *dst,  char  const  *src,  size_t  len);
int    strncmp(char  const  *s1,  char  const  *s2,  size_t  len);

举个例子:

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

int main()
{
	char message1[] = "hello ";
	char message2[] = "hello Beijing ";
	char message3[] = "Shanghai";
	char message_all[] = "hello Beijing Shanghai";


	if(strncmp(strncpy(strncat(message2, message3, strlen(message3)), message1, strlen(message1)), message_all,strlen(message_all)) == 0)
		printf("二者相等\n");
	else
		printf("二者不相等\n");

	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
这个例子举得并不十分恰当。因为长度都是按最大进行传入的,但也可以说明问题。

5 字符串查找基础

标准库中存在很多函数,它们用各种不同的方法查找字符串。这些各种各样的工具给了C程序员很大的灵活性。

5.1 查找一个字符串

在一个字符串中查找特定字符有两个库函数可用。

char *strchr(char const *str, int ch);
char **strrchr(char const *str, int ch);

前者用来查找某字符第一次出现的位置(返回指向该地址的指针),后者用来查找某字符最后一次出现的位置(返回指向该地址的指针)。

这两个函数可以这样用:

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

int main()
{
	char message1[] = "hello ";
	char message2[] = "hello Beijing ";
	char message3[] = "Shanghai";
	char message_all[] = "hello Beijing Shanghai";

	char *first_site, *last_site;

	first_site = strchr(message_all, 'h');
	last_site = strrchr(message_all, 'h');

	printf("字符串的长度是:%d\n",strlen(message_all));
	printf("h第一次出现的位置是:%d\n", first_site - message_all);
	printf("h最后一次出现的位置是:%d\n", last_site - message_all);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
需要注意的是,该函数返回的并不是目标元素位置的值,而是指针,所以需要与该字符串的第一个元素指针作差,才可以得出结果。

注意:在查找的时候是区分大小写的。

5.2 查找任何几个字符

strpbrk是一个更为常见的函数,用来查找某个字符串中任意字符第一次在目标字符串中出现的位置。它的原型如下:

char *strpbrk(char  const *str,   char  const  *group);

可以这样用:

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

int main()
{
	char message_all[] = "hello Beijing Shanghai";
	char *first_site;

	first_site = strpbrk(message_all, "abcde");

	printf("字符串的长度是:%d\n",strlen(message_all));
	printf("abcde第一次出现匹配字符的位置是:%d\n", first_site - message_all);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
容易看出,第一个匹配到的字符是e,位置是1

5.3 查找一个子串

为了在字符串中查找一个子串,我们可以使用strstr函数,它的原型如下:

char  *strstr(char  const  *s1,  char  const  *s2);

举个实际使用中的例子:

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

int main()
{
	char message_all[] = "hello Beijing Shanghai";
	char *first_site;

	first_site = strstr(message_all, "Beijing");

	printf("字符串的长度是:%d\n",strlen(message_all));
	printf("Beijing第一次出现的位置是:%d\n", first_site - message_all);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
可以看到,在此次查找中,需要匹配到所有的字符,而不是某个或者局部。

6 高级字符串查找

接下来的一组函数简化了从一个字符串的起始位置中查找和抽取一个子串的过程。

6.1 查找一个字符串前缀

strspnstrcspn函数用于在字符串中的起始位置对字符串计数,它们的原型如下所示:

size_t  strspn(  char  const   *str,  char const  *group);
size_t  strcspn(  char  const   *str,  char const  *group);

需要注意的是,这两个函数返回的 并不是元素指针,而是实际匹配字符的数量。

具体的使用方法可以来看个例子:

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

int main()
{
	int len1, len2;
	char buffer[] = "25,142,330,smith,J,239-4123";

	len1 = strspn(buffer, "0123456789");
	len2 = strcspn(buffer, ",");

	printf("0123456789的起始匹配数是:%d\n", len1);
	printf(",的起始不匹配数是:%d\n", len2);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
从上面例子中可以看出,strspn函数是从头开始找符合所找字符串的字符,直到找不到为止。在该例中,,已经不合适了,所以连续查找的情况下,合适的只有2个。

strcspn函数却恰好相反,找的是不符合的,开头的2和5显然都不符合,,是符合的,所以连续查找的情况下,合适的有2个。

6.2 查找标记

一个字符串常常包含好几个单独的部分,他们彼此被分隔开。每次为了处理这些部分,首先必须把它们从字符串中抽取出来。
strtok函数就可以实现这样的功能。它从字符串中隔离各个单独的称为标记的部分。并丢弃分隔符。它的原型如下:

char  *strtok(  char  *str,  char const  *sep);

注意:

  1. 当strtok函数执行任务时,它会修改它所处理的字符串。如果源字符串不能被修改,那就复制一份,将这份拷贝传递给strtok函数。
  2. 如果strtok函数的第1个参数不是NULL,函数将找到字符串的第1个标记。strtok同时将保存它在字符串中的位置。如果strtok函数的第1个参数是NULL,函数就在同一个字符串中从这个被保存的位置开始像前面一样查找下一个标记。

举个例子:

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

int main()
{
	int add = 0;
	char buffer[] = "25,142,330,smith,J,239-4123";
	char *token = NULL;
	for (token = strtok(buffer, ","); token != NULL; token = strtok(NULL, ","))
	{
		printf("%s\n", token);
		add++;
	}
	printf("--------------------------\n");
	printf("add的值为:%d\n",add);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
从上面的例子中可以看出,以我们需要寻找的标记为分界,每循环一次,得到一个分割的子串,直到全部分割完毕。共分割6次。

7 错误信息

C语言的库函数在执行失败时,都会有一个错误码(0 1 2 3 4 5 6 7 8 9 …),操作系统是通过设置一个外部的整型变量errno进行错误代码报告的。也就是说,一个错误码,对应了一种错误类型,strerror函数把其中一个错误代码作为参数并返回一个指向用于描述错误的字符串的指针。这个函数的原型如下:

char  *strerror(int error_number);

举个例子:

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

int main()
{
	for(int i = 0; i < 10; i++)
		printf("%s\n",strerror(i));
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
可以看到,不同的操作码,对应着不同的错误类型,而错误码0表示没有错误。其他均表示各种各样的错误。这部分内容了解即可。不需要掌握。也不需要知道每个操作码究竟代表哪种错误。

8 字符操作

标准库包含了两组函数,用于操作单独的字符,它们的原型位于头文件ctype.h。第1组函数用于对字符串分类,而第2组函数用于字符转换。

8.1 字符分类

每个分类函数接受一个包含字符值的整形参数。函数测试这个字符并返回一个整形值,表示真或假。下面的表格列出了每个函数以及返回真所需要的条件。

函数返回真所需要的条件
iscntrl控制字符
isspace空白字符:空格,换页’\f’,换行’\n’,回车’\r’,制表符’t’或垂直制表符’\v’
isdigit十进制数字
isxdigit十六进制数字,包含大小写形式的a~f
islower小写字母
isupper大写字母
isalpha字母(大小写皆可)
isalnum字母或数字
ispunct任何不属于数字或字母的图形字符(可打印符号)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

所以这些函数是用来判定字符串元素的, 举个例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main()
{
	char temp[] = "To carry things with great virtue";

	for (int i = 0; i < strlen(temp); i++)
	{
		if (islower(temp[i]))
			printf("temp[%d] : %c是小写字母\n", i, temp[i]);
		else if (isupper(temp[i]))
			printf("temp[%d] : %c是大写字母\n", i, temp[i]);
		else if(isspace(temp[i]))
			printf("temp[%d] : %c是空格\n", i, temp[i]);
	}

	printf("\n");
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
可以看到,此时已经将temp每个元素究竟是大写字母还是小写字母,或者是空格进行了判定。

8.2 字符转换

转换函数白大写字母转换为小写字母或者把小写字母转换为大写字母。有两个函数可供调用。toupper函数返回其参数对应的大写形式tolower函数返回其参数对应的小写形式

int tolower(int  ch);
int toupper(int  ch);

举个实际的例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main()
{
	char temp1[] = "To carry things with great virtue";
	char temp2[] = "To carry things with great virtue";
	//全转换为大写
	for (int i = 0; i < strlen(temp1); i++)
	{
		if (islower(temp1[i]))
			temp1[i] = toupper(temp1[i]);
		printf("%c",temp1[i]);
	}
	printf("\n-----------------------------\n");
	//全转换为小写
	for (int i = 0; i < strlen(temp2); i++)
	{
		if (isupper(temp2[i]))
			temp2[i] = tolower(temp2[i]);
		printf("%c", temp2[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述
可以看到,我们可以按照自己的意愿去调整字符串中字母的大小写。

9 内存操作

字符串一般以NUL结尾,但是如果我们想要处理中间包含NUL的字符串,或者任意长度的字节序列的时候,前面的函数就显得比较乏力,或者说根本没法用。不过我们可以有另外一组函数,供我们使用,去完成实际开发中的一些需求。下面是它们的原型。

注意:这些函数能够处理的不仅仅是字符串,还可以是结构体数组等数据类型,具体可以处理的数据类型要根据具体函数来定。

void  *memcpy(void  *dst,  void  const  *src,  size_t  length);
void  *memmove(void  *dst,  void  const  *src,  size_t  length);
void  *memcmp(void  const  *a,  void  const  *b,  size_t  length);
void  *memchr(void  const  *a,  int  ch,  size_t  length);
void  *memset(void  *a,  int  ch,  size_t  length);

举个例子:

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

#define SIZE 10

int main()
{

	char temp1[] = "hello world";
	char temp2[] = "hello world";
	char temp3[] = "hello world";
	char temp4[] = "hello world";
	unsigned int int_array[SIZE];
	char *p = NULL;

	//复制字符串
	memcpy(temp1 + 2, temp1, 5);
	memmove(temp2 + 2, temp2, 5);

	printf("temp1 = %s\n", temp1);
	printf("temp2 = %s\n", temp2);
	printf("---------------------------------------\n");
	//比较字符串
	if(!memcmp(temp1, temp2, 6))
		printf("temp1 = temp2\n");
	else
		printf("temp1 != temp2\n");
	printf("---------------------------------------\n");
	//查找字符
	p = (char *)memchr(temp3, 'e', strlen(temp3));
	if(p != NULL)
		printf("字符e在temp3中的位置是:%d\n", p - &temp3[0]);
	printf("---------------------------------------\n");
	//初始化数组
	memset(int_array, 0, sizeof(int_array));
	for (int i = 0; i < SIZE; i++)
		printf("int_array[%d]的值为:%d\t", i, int_array[i]);
	printf("\n", sizeof(int));
	printf("---------------------------------------\n");
	//初始化数组
	memset(temp4, 'a', sizeof(temp4) - 1);
	printf("字符串temp4为:%s\n", temp4);
	system("pause");
	return 0;
}

打印输出:
在这里插入图片描述

9.1 memcpy和memmove真的不一样吗?

有一个很值得探讨的问题:
memcpy和memmove函数真的一样吗?《C和指针》以及网上的很多说法都是:两者不一样,如果src和dst出现了重叠,则memcpy会出现问题,而memmove总能按照理想的情况去运行,但我们的程序运行结果却是,这两个函数都可以按照理想情况运行,这是为什么呢?

唯一的解释就是,软件的运行环境不一样,程序的底层库出现了差异,所以会出现这样的情况。但这并不影响我们对以前版本的(也就是两者不同)的memcpy和memmove进行一番研究!

先来看看所谓的重叠是什么意思,为什么重叠的时候,字符串复制会出现问题。
在这里插入图片描述
以上就是我们程序中复制字符串操作的示意图。可以看到src子串和dst子串有三个字母出现了重叠,如果我们按照常规的操作方法,复制之后就会出现下面这样的结果。
在这里插入图片描述
若区域重叠,就会导致复制出错,也就是说,想要取的值被新值所覆盖,导致无法顺利取值,复制后temp1变成了hehehehorld。这就是之前memcpy字符串的复制方法。

然后让我们来看看memmove(以及优化后的memcpy)是如何巧妙地解决这个问题的。
在这里插入图片描述
可以看到,复制的顺序出现了变化,这次是从后往前复制的,很好地避免了这个问题。

那么问题来了,这次是要复制的目的位置在后面,如果在前面又该如何处理呢?答案是复制顺序也反过来。看看执行过程:
在这里插入图片描述
这个时候,也不会出现将要取的值被原来的值覆盖的情况,会按照预想的结果去执行,结果是:llo w world

9.2 memcmp:简单的比较

memcmp比较内存区域a和的前length个字节。比较方法,返回值都和strcmp基本一致,详情可以参考本文的strcmp部分。

9.3 memchr:简单的查找

memchr从a的起始位置开始查找字符ch的第一次出现的位置,并返回一个指向该位置的指针。查找方法,返回值都和strchr基本一致,详情可以参考本文的strchr部分。

9.4 memset:初始化的值只能是0和-1?

从该函数的介绍来看,该函数可以对某连续的内存区域设置相同的任何值(理论上),但在实际的开发中,基本都设置为0或者-1,这是为什么呢?

这是因为,这个函数对于内存的赋值,是以字节为单位的,一般用来对字符串进行赋值没有任何问题,因为字符串的元素只占一个字节,而数组则不同,常见的short,int,long类型的数组元素都不止一个字节,所以初始化才不会出现我们预想的结果。当我们设置为0的时候,各个字节都为0(若为-1,则各个位都为1),所以每个元素无论几个字节都会初始化为0,但是为其他值,结果就不一样了。参考以下程序:

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

#define SIZE 10

int main()
{
	unsigned int int_array[SIZE];

	//初始化数组
	printf("--------------初始化值设为0-------------------------\n");
	memset(int_array, 0, sizeof(int_array));
	for (int i = 0; i < SIZE; i++)
		printf("int_array[%d]的值为:%d\t", i, int_array[i]);
	printf("\n");
	printf("--------------初始化值设为1-------------------------\n");
	memset(int_array, 1, sizeof(int_array));
	
	for (int i = 0; i < SIZE; i++)
		printf("int_array[%d]的值为:%d\t", i, int_array[i]);
	printf("\n");
	system("pause");
	return 0;
}

打印输出:在这里插入图片描述
这是为什么呢?

这是因为,memset是按字节赋值的,而int类型的数据在内存中占了4个字节,所以该值应该以4个字节为单位,即:0x01010101,转换成十进制正好是16843009

所以,一般如果想用memse对一段内存区域设定相同的值,初始化为0或者-1是最好的选择。

10 总结

字符串本身并不是很复杂,为了方便开发,提供了很多的库函数,所以我们只需要掌握C语言的那些库函数即可。尤其是要注意,有的函数返回的并不是数值,而是指针;有的函数使用起来比较特殊,比方说strtok等。

------------------------------------------------------------------------end-------------------------------------------------------------------------

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

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

相关文章

饿补基础_1 |进位制、R进制之间转换及十进制编码

目录 数值数据的表示一.进位计数制理解1.你需要了解的概念2. 晦涩难懂的官方定义3 一看就会的例子4 值得收藏的进制对照表(二、八、十、十六进制)5 计算机为什么主要使用二进制 二.不同数制之间的转换1. 为什么会出现进制转换2. 各数制转十进制3. 十进制转二进制4. 二进制与八进…

java企业级信息系统开发学习笔记12 基于配置文件整合SSM框架实现用户登录

文章目录 一、学习目标&#xff08;一&#xff09;采用MVC架构 二、基于XML配置方式整合SSM框架实现用户登录&#xff08;一&#xff09;创建表&#xff08;二&#xff09;创建项目&#xff08;三&#xff09;添加相关依赖&#xff08;四&#xff09;创建日志属性文件&#xff…

leetcode51. N 皇后 (java)

leetcode 51 N 皇后 leetcode 51 N 皇后题目描述解题思路 代码演示leetcode52 N 皇后II leetcode 51 N 皇后 原题链接: https://leetcode.cn/problems/n-queens/ 题目描述 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研…

2023 华为 Datacom-HCIE 真题题库 07/12--含解析

多项选择题 1.[试题编号&#xff1a;190187] &#xff08;多选题&#xff09;如图所示的拓扑采用了VXLAN分布式网关&#xff0c;SW1上的VBDIF10配置了&#xff1a;arp-proxy local enable命令&#xff0c;则以下描述中正确的有哪些项&#xff1f; A、SW1收到PC1发往PC2的报文&…

【PHP】ThinkPhp6期末速通

目录 一、安装Composer二、设置Composer下载源三、Composer下载&#xff0c;安装TinkPHP6四、安装成功后 目录结构五、运行 ThinkPHP6 起步一、MVC二、单应用模式访问调试 三、安装视图四、模板渲染默认访问指定访问 五、模板变量默认赋值助手函数&#xff08;若不使用默认赋值…

K8s之Deployment控制器入门到深入详解

文章目录 一、Deployment 高级控制器理论1、Deployment控制器介绍2、Deployment工作原理 二、Deployment YAML编写及参数解释1、整体Deployment YAML资源清单内容&#xff1a;2、核心参数解释&#xff1a;3、Deployment更新策略&#xff1a;4、Deployment更新策略百分比方式计算…

内网穿透技术

文章目录 前言1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 转载自内…

测试必会 | 通过容器化 Python Web 应用掌握 Docker 容器核心技能

【摘要】 当多个窗口同时 attach 到同一个容器时&#xff0c;所有的窗口都会同步的显示&#xff0c;假如其中的一个窗口发生阻塞时&#xff0c;其它的窗口也会阻塞。attach 必须是登陆到一个已经运行的容器里&#xff0c;如果从这个容器中 exit 退出的话&#xff0c;会导致容器…

HNU-操作系统OS-实验Lab8

OS_Lab8_Experimental report 湖南大学信息科学与工程学院 计科 210X wolf (学号 202108010XXX) 实验目的 通过完成本次实验,希望能达到以下目标 了解基本的文件系统系统调用的实现方法;了解一个基于索引节点组织方式的Simple FS文件系统的设计与实现;了解文件系统抽…

Ace Admin前端框架笔记一概要与布局介绍

简要 Ace Admin官网 Dashboard - Ace Admin Ace Admin Git GitHub - bopoda/ace: Twitter bootstrap 3 admin template 下载地址&#xff1a;https://download.csdn.net/download/ok060/87843670 Ace是一款轻量且功能丰富的管理模板&#xff0c;干净且易于使用。 当前版本…

计组 第二章错题 2.2 运算方法和运算电路

选D 地址寄存器MAR是存储器部件 访存时暂存访存地址 符号位不变 附加位是符号位的扩展 选B A&#xff1a;检查加减 B&#xff1a;对 因为两个符号位一样 D&#xff1a;需要两个 存储单元把信号同时传给两个单元 用双符号位的方法 同0异1 符号相同 0 正 不同 为1 负 逻辑一样 原…

目标检测第三篇:基于SSD的目标检测算法

文章目录 SSD简介网络搭建卷积块下采样块主干网多层特征提起层输出头 数据处理形成训练TXTDatasetDataLoaderAnchors生成先验框匹配先验框位置 offset 损失函数训练代码及参考 SSD简介 SSD&#xff0c;全称Single Shot MultiBox Detector&#xff0c;是Wei Liu在ECCV 2016上提…

软件测试新人害怕不过试用期,教你几招使你安稳度过!!!

对于很多刚步入职场的新人来说&#xff0c;害怕自己试用期过不了&#xff0c;被辞退。别的行业我可能不知道该如何帮大家应对&#xff0c;但在测试行业我希望还是能给大家带俩一点帮助&#xff0c;希望大家能安稳度过试用期&#xff0c;并且成功入行。 保持初心&#xff0c;安稳…

零基础开发小程序第四课-查看功能开发

目录 1 创建页面2 搭建页面3 创建数据4 数据绑定5 页面传参6 预览发布总结 本篇是我们零基础入门课的第四篇&#xff0c;前三篇我们介绍了创建项目、列表功能、新增功能&#xff0c;本篇我们介绍一下查看详情功能的开发。 1 创建页面 打开Zion开发工具&#xff0c;点击已经创建…

Python Struct 库之 pack 和 unpack 详解

1. 官网解析 首先是官网对于 pack 、 unpack 、calcsize以及Format Strings的描述 1.1 pack、unpack、calcsize struct.pack返回一个bytes对象&#xff0c;其中包含根据格式字符串format打包的值v1, v2&#xff0c;…。参数必须与格式所要求的值完全匹配。 struct.unpack根据…

云原生 HTAP -- Cloud-Native Transactions and Analytics in SingleStore

文章目录 背景1 存算分离2. 统一的表存储 &#xff08;行列混存&#xff09;2.1 二级索引2.2 行锁 3. 自适应查询引擎3.1 Segment skipping 实现3.2 Filtering 选择 4 性能总结 背景 上篇看了 PolarDB-IMCI 在HTAP的实践&#xff0c;其中提到了其也有借鉴 SingleStore 的实现思…

openresty离线rpm升级至openresty-1.19.9.1版本

注意&#xff1a;此方法步骤仅本人验证通过&#xff0c;要升级的话&#xff0c;需要做备份 1。系统版本是centos7(Linux version 3.10.0-693.el7.x86_64) 2。默认openresty版本是1.15.8.1 3。本次升级到openresty-1.19.9.1 目前系统是没有连接外网&#xff0c;只能进行rpm离…

网络重置后无法上网,以太网和无线网全部丢失,网络适配器出现“56”错误码

文章目录 一、问题描述电脑系统&#xff1a;电脑问题&#xff1a;解决方案 二、问题过程1. IP问题2.网络重置问题3.电脑无法启动问题 三、解决方案1.卸载2.安全模式检查修复3.软件下载1.CCleaner2.驱动精灵万能网卡版 四、参考链接 一、问题描述 电脑系统&#xff1a; Window…

【MySQL高级篇笔记-索引的创建与设计原则 (中) 】

此笔记为尚硅谷MySQL高级篇部分内容 目录 一、索引的声明与使用 1、索引的分类 2、创建索引 1. 创建表的时候创建索引 2. 在已经存在的表上创建索引 3、删除索引 二、MySQL8.0索引新特性 1、支持降序索引 2、 隐藏索引 三、索引的设计原则 1、哪些情况适合创建索引…

Android 应用快捷ShortcutManager与ShortcutManagerCompat详解与实战(二)

一、介绍 之前我已通过一篇文章介绍了应用快捷的接入与Demo。如果还未看过上一篇的文章可以先了解入门。 传送门&#xff1a;Android 应用快捷(shortcut)功能的详解(一)_蜗牛、Z的博客-CSDN博客 有创建自然就会有管理&#xff0c;否则一个完美的方案不应该这么被推荐出来。如何…