C语言之常用字符串函数总结、使用和模拟实现


文章目录

目录

一、strlen 的使用和模拟实现

二、strcpy 的使用及模拟实现

三、strcat 的使用和模拟实现

四、strcmp 的使用和模拟实现

五、strncpy 的使用和模拟实现

六、strncat 的使用和模拟实现

七、strncmp 的使用和模拟实现

八、strstr 的使用和模拟实现

九、strtok函数的使用

十、strerror 函数的使用

2.补充:perror 函数的使用



前言

        本文介绍和模拟实现的字符串函数有:strlen、strcpy、strcat、strcmp、strncpy、strncat、strncmp、strstr。另外详细介绍了 strtok 、strerror、perror函数的使用。基本囊括了所有常用的字符串函数。模拟实现有助于我们理解和记忆这些库函数,我们都能够自己实现这些库函数,使用时需要注意的细节我们肯定也更加清楚和深刻。最后,希望本文的内容能够帮助到大家更好的理解这些库函数


注意:字符串函数包含的头文件都为 <string.h>

一、strlen 的使用和模拟实现

1.使用:

功能:strlen 函数,其功能相信大家很熟悉了,就是计算字符串的长度

      

函数声明:size_t strlen ( const char * str );

      

用法:传入字符串首字符的地址,计算出的结果将以 size_t 类型返回

(size_t 是一种无符号整形,是为了代码的可移植性而定义的一种自定义类型,使用 %zd 打印)

使用演示:

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

int main()
{
	char ch1[] = { "abcdefg" };
	char* ch2 = "qwertyuiop";

	printf("%zd\n", strlen(ch1));
	printf("%zd\n", strlen(ch2));

	return 0;
}

运行结果:

解疑:上述ch1是数组名,表示数组首元素地址,ch2是字符指针,指向的是一个字符串字面量的首字符地址


2.模拟实现:

想要模拟实现 strlen ,我们就应该了解其机制,strlen 就是通过寻找字符串结尾处的 '\0' 字符来计算字符串的长度的,像我们平时写在双引号中的字符串,其末尾自动包含了一个'\0',我们也可以在定义字符数组的时候在其末尾手动添加 '\0',只有包含了 '\0'的字符串才能被strlen正确的计算长度

以下演示三种 strlen 的模拟实现

(以下所以代码中包含了 assert 函数,其为断言,用来检查指针是否为空,详细请移步主页指针基础知识,其中有详细讲解)

1:边寻找 '\0' 边统计字符

#include <stdio.h>
#include <assert.h>

size_t my_strlen(const char* str)
{
	assert(str != NULL);
 
	size_t count = 0;

	while (*str)
	{
		str++;
		count++;
	}

	return count;
}

2:通过指针相减算出元素个数

#include <stdio.h>
#include <assert.h>

size_t my_strlen(const char* str)
{
	const char* str1 = str;

	assert(str != NULL);

	while (*str1)
	{
		str1++;
	}

	return str1 - str;
}

3:使用递归实现

size_t my_strlen(const char* str)
{
	assert(str != NULL);

	if (*str == '\0')
	{
		return 0;
	}
	else
	{
		return 1 + my_strlen(str + 1);
	}
}


二、strcpy 的使用及模拟实现

1.使用:

功能:将源字符串拷贝到目标字符串之中,返回目标字符串首地址

    

函数声明:char * strcpy ( char * destination, const char * source );

    

用法:按顺序先传入目标字符串,再传入源字符串,最后 strcpy 返回的目标字符串首地址,另外,函数有以下几个要求和细节:

  • 源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。
  • 目标空间必须足够⼤,以确保能存放源字符串。
  • 目标空间必须可修改。因此目标字符串参数没有使用const修饰

使用演示:

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

int main()
{
	char ch1[20] = { "xxxxxxxxxxxxx" };
	char* ch2 = "abcdefg";

	char* ret = strcpy(ch1, ch2);

	printf("%s\n", ch1);
	printf("%s\n", ret);

	return 0;
}

运行结果

解疑:值得注意的是,ch2中的'\0'也会被拷贝到ch1中我们可以通过调试观察到

另外,目标字符串小于原字符串将导致报错


2.模拟实现:

#include <stdio.h>
#include <assert.h>

char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);

	char* ret = dest;

	while (*dest++ = *src++)
	{
		;
	}

	return ret;
}

解疑:这里面比较难理解的估计就是这个while循环,*dest++ = *src++,首先 ++ 的优先级高于 *,因此先执行++,但因为是后置++,先使用后++,因此会先解引用,将src的值赋给dest,然后++,两字符串地址向后走一个字节长度,来到下一个字符的地址,依次循环下去,最后 src 解引用遇到'\0'赋值给dest后,整个表达式值为0,循环停止,注意循环体为空语句。最后包括'\0'在内的所有字符都从src中拷贝到了dest中,最后的最后返回目标字符串首地址


三、strcat 的使用和模拟实现

1.使用:

功能:将源字符串追加到目标字符串的末尾

    

函数声明:char * strcat ( char * destination, const char * source );

    

用法:先传入目标字符串首地址,再传入源字符串首地址,追加后返回目标字符串首地址

有以下需要注意的细节和要求:

  • 源字符串必须以 '\0' 结束。
  • 目标字符串中也得有 '\0' ,否则没办法知道追加从哪里开始。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。

使用演示:

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

int main()
{
	char ch1[20] = { "abcdef" };
	char ch2[] = { "qwerty" };

	char* ret = strcat(ch1, ch2);

	printf("%s\n", ch1);
	printf("%s\n", ret);

	return 0;
}

2.模拟实现:


2.模拟实现:

#include <stdio.h>
#include <assert.h>

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);

	char* ret = dest;

	while (*dest)
	{
		dest++;
	}

	while (*dest++ = *src++)
	{
		;
	}
	
	return ret;
}

解疑:第一个while循环用来定位 dest 中'\0'位置,也就是dest中第一次出现'\0'的位置,第二个循环与前面 strcpy 一样,将源字符串src内容拷贝到目标字符串dest中,只不过是接在dest第一个'\0'的位置处,最后返回目标字符串首地址


另外考虑一个问题,问:strcat 能不能给自己追加自己?

我们使用自己模拟的strcat试一试:

结果是不可以,因为 src 追加后,使得自己变长,永远到不了'\0',结果就会导致死循环

官方的库函数却可以,但其返回值也不可以,底层逻辑的实现不同,这里不再深究


四、strcmp 的使用和模拟实现

1.使用:

功能:比较两字符串大小,不是比较长度,而是按顺序比较每一位对应字符的ASCII码值

    

函数声明:int strcmp ( const char * str1, const char * str2 );

    

用法:分别传入需要比较的字符串首地址,strcmp 会比较两字符串的对应位字符的ASCII码值,其返回值分为三种:

  1. 返回值 >0,表示 str1 中某一位字符大于 str2 对应位的字符
  2. 返回值 <0,表示 str1 中某一位字符小于 str2 对应位的字符
  3. 返回值 == 0,表示 str1 与 str 2完全相同

使用演示:

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

int main()
{
	char* ch1 = "abcdefg";
	char* ch2 = "abcz";

	int ret = strcmp(ch1, ch2);

	printf("%d\n", ret);

	return 0;
}

运行结果:

解疑:在vs中,strcmp三种返回值为1,0,-1,对应的三种情况,但C语言标准中是按照大于0小于0等于0分的。上图结果为-1,因为ch2中的第四个字符为 'z',大于ch1中第四个字符 'd',因此判定ch1小于ch2,返回-1。也就是返回<0的值


2.模拟实现:

#include <stdio.h>
#include <assert.h>

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);

	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}

	return *str1 - *str2;

    /*if (*str1 > *str2)
    {
	    return 1;
    }
    else
    {
	    return -1;
    }*/
}

解疑:首先while循环,判断两字符串对应位置字符是否相同,相同就进入循环,在进行判断,如果其中有一个字符为'\0',表示这两个字符走到头了,并且完全相等,返回0,如果没有就使两字符串地址向后走一位,再进行循环判断,如果两字符串对应位字符不相等,就跳出循环,直接令这两个字符串对应位置的字符相减,其返回值就能判断两字符串的大小,也可以使用分支判断两字符串,使其返回1或-1,如代码中注释的部分


五、strncpy 的使用和模拟实现

1.使用:

功能:拷贝指定个数的字符从源字符串到目标字符串上

    

函数声明:char * strncpy ( char * destination, const char * source, size_t num );

    

用法:和 strcpy 相比多了一个参数 num,用来指定复制多少个字符,有以下几点需要注意:

  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
  • 如果原字符串的长度大于num,则只拷贝num个字符到目标文件中,目标文件中如果有数据将会被覆盖,并且不会追加'\0'。
  • 目标字符串的容量必须足够大,能存放下拷贝的字符

使用演示:

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

int main()
{
	char ch1[10] = { "xxxxxxxxx" };
	char ch2[] = { "abcdef" };

	char* ret = strncpy(ch1, ch2, 9);

	printf("%s\n", ch1);
	printf("%s\n", ret);

	return 0;
}

运行结果:

监视窗口:

解疑:上述代码符号第一种情况,即如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。


2.模拟实现:

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

char* my_strncpy(char* dest, char* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;
	size_t len = strlen(src);
	int count = (int)num - (int)len;

	while (num && *src)
	{
		*dest = *src;
		dest++;
		src++;
		num--;
	}

	while (count > 0)
	{
		*dest = 0;
		dest++;
		count--;
	}

	return ret;
}

解疑:以上的实现是我个人的想法,不是最优解。首先除了保存目标字符串首地址,计算了源字符串大小,并保存了num与源字符串长度的差值,第一个while循环,在保证拷贝没有超过 num 个字符和原字符串没有走到结尾的情况下,拷贝了能拷贝的字符。然后下面一个while循环用来判断 num是否大于源字符串长度,如果大于,则在目标字符串末尾补0。直至刚好拷贝完num个字符,最后返回目标字符串首地址。


六、strncat 的使用和模拟实现

1.使用:

功能:将源字符串的前num个字符追加到目标字符串指向的字符串末尾,再追加⼀个'\0'字符

    

函数声明:char * strncat ( char * destination, const char * source, size_t num );

    

用法:前两个参数与strcat一致,也是后面多了一个num,用来指定追加多少个字符。这里需要注意的有以下几条:

  • 如果 source 指向的字符串的长度小于num的时候,只会将字符串中到 '\0' 的内容追加到destination指向的字符串末尾。大于num的话,就是源字符串的前num个字符追加到目标字符串指向的字符串末尾,再追加⼀个'\0'字符
  • 目标字符串的容量得足够大,能容下追加的字符

使用演示:

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

int main()
{
	char ch1[20] = { "abcd\0xxxxxxxx" };
	char* ch2 = "qwerty";

	char* ret = strncat(ch1, ch2, 8);

	printf("%s\n", ch1);
	printf("%s\n", ret);

	return 0;
}

运行结果:

监视窗口:

解疑:以上代码就符合num大于源字符串长度的情况,即 source 指向的字符串的长度小于num的时候,只会将字符串中到 '\0' 的内容追加到destination指向的字符串末尾。为了方便观察,我在ch1中插入了'\0'和xxxxxxxx,最后发现末尾确实追加了一个'\0'字符。


2.模拟实现:

#include <stdio.h>
#include <assert.h>

char* my_strncat(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;

	while (*dest)
	{
		dest++;
	}

	while (num && *src)
	{
		*dest = *src;
		dest++;
		src++;
		num--;
	}
	
	*dest = '\0';

	return ret;
}

解疑:前面步骤与strcat一致,到了第二个while循环,也是在保证没有追加超过num个字符和源字符串地址没有走到字符串末尾的情况下,追加所有能追加的字符,然后无论 num 大于或者小于 源字符串长度,只需要追加一个'\0'即可。最后返回目标字符串首地址。


七、strncmp 的使用和模拟实现

1.使用:

函数声明:int strncmp ( const char * str1, const char * str2, size_t num );

    

功能及用法:比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不一样,就提前结束,大的字符所在的字符串大于另外⼀个。如果num个字符都相等,就是相等返回0。返回值情况与strcmp一致

使用演示:

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

int main()
{
	char* ch1 = "abcde";
	char* ch2 = "abcqwer";

	int ret1 = strncmp(ch1, ch2, 3);
	int ret2 = strncmp(ch1, ch2, 5);
	
	printf("%d\n", ret1);
	printf("%d\n", ret2);

	return 0;
}

运行结果:

解疑:基本和strcmp一样,只是多了指定比较的个数


2.模拟实现:

#include <stdio.h>
#include <assert.h>

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);

	while ((*str1 == *str2) && num)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
		num--;
	}

	if (*str1 == *str2)
	{
		return 0;
	}
	else if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

解疑:模拟过程与strcmp相比,while循环多了一个num的判断,最后的条件判断也多了一条判断相等的情况,因为while循环的终止可能是由于num等于0的情况,此时需要再对字符串进行一次比较。


八、strstr 的使用和模拟实现

1.使用:

功能:在一个字符串中寻找与另一个字符串完全相同的片段

    

函数声明:char * strstr ( const char * str1, const char * str2 );

    

用法:传入两个字符串的首地址,函数返回字符串str2在字符串str1中第一次出现的位置的地址,如果找不到,就返回空指针(NULL)。

使用演示

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

int main()
{
	char ch1[] = "This is a simple string";
	char ch2[] = "simple";

	char* ret = strstr(ch1, ch2);

	printf("%s\n", ret);

	return 0;
}

运行结果:

解疑:因为函数返回的是str2字符串内容在str1中第一次出现时的地址,所以我们以%s打印时,会从这个地址一直打印到str1字符串末尾遇到'\0'停止


2.模拟实现:

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

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);

	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* cur = str1;

	if (*str2 == '\0')
	{
		return (char*)str1;
	}

	while (*cur)
	{
		s1 = cur;
		s2 = str2;

		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}

		if (*s2 == '\0')
		{
			return (char*)cur;
		}

		if (strlen(cur+1) < strlen(str2))
		{
			return NULL;
		}

		cur++;
	}

	return NULL;
}

解疑:

  1. 首先创建了三个指针变量,s1,s1分别用来记录str1和str2比较过程中的地址,cur记录的是str1当前位置的地址,因为途中的比较过程会打乱str1指针的指向,因此需要cur来记录str1当前位置的地址,以便s1在比较过程中没有找到相同字符串时,可以通过cur找回起始位置。而str2本身指向是不会变的,因此不需要另外的指针进行记录当前位置。
  2.  if (*str2 == '\0') ,这个意思是如果str2是个空字符串的话,直接返回str1的地址,这是C语言标准中strstr的规定。并且空字符串本身也不需要寻找,任何字符串都包含空字符串
  3. while (*cur) ,这个循环条件就是cur没有指向字符串末尾。然后给s1赋值为cur,s2赋值为str2,。s1,s2就是用来比较判断两字符串是否有相同的指针。
  4. while (*s1 && *s2 && *s1 == *s2),这个循环意思是,只要s1,s2没有指向字符串末尾并且它两指向的字符相等,就让s1,s2一直往后走,只要有其中一个条件不满足时,循环就终止
  5. 循环终止后就进行一个判断,if (*s2 == '\0'),该判断的意思是,如果s2等于'\0',表示前一个循环是因为s2走到字符串末尾而终止的,s2能走到末尾,就表示s2前面的字符与s1都相同,这就表明能在str1中找到str1,此时只需要终止函数,返回cur,也就是str1当前的地址就行
  6. 而如果s1指向的字符不为'\0',就表示前一个循环的终止是因为s1,s2指向的字符不相同导致的,就再进行一个判断,if (strlen(cur+1) < strlen(str2)),这个判断表示,当前str1指向的下一个位置到字符串末尾的长度,如果小于str2的长度,就表明str1后面一定找不到str2了,为了提高效率,直接返回空指针。
  7. 如果两个判断都不满足,就让str1当前的位置往后走一步,也就是cur++,再进行循环判断。
  8. 如果直到最后cur都指向'\0'了,就直接返回空指针。


九、strtok函数的使用

功能:将一个字符串以指定字符的格式分隔

    

函数声明:char * strtok ( char * str, const char * sep );

    

用法:第一个参数指向了一个字符串,第二个参数指向了需要分隔的字符的集合,并且有以下要求和细节:

  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。简单来说就是str中可能有sep包含的字符
  • sep参数指向一个字符串,定义了用作分隔符的字符集合
  • strtok函数找到str中的下一个标记字符(sep),并将其用 '\0' 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • 第一次调用,strtok函数的第⼀个参数不为 NULL ,函数将找到str中第一个标记字符,strtok函数将保存它在字符串中的位置
  • 下一次调用,strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
  • 简单来说就是 strtok 具有保存记忆的功能,如果第一个参数传入NULL,strtok能记起同一个字符串上一次被分隔的位置
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。

使用演示:

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

int main()
{
	char ch1[] = "abcd.bbc/123@xp";
	char ch2[] = "./@";

	printf("第一次分割:\n");
	char* ret = strtok(ch1, ch2);
	printf("%s\n", ret);
	printf("%s\n", ch1);

	printf("第二次分割:\n");
	ret = strtok(NULL, ch2);
	printf("%s\n", ret);
	printf("%s\n", ch1);

	printf("第三次分割:\n");
	ret = strtok(NULL, ch2);
	printf("%s\n", ret);
	printf("%s\n", ch1);

	printf("第四次分割:\n");
	ret = strtok(NULL, ch2);
	printf("%s\n", ret);
	printf("%s\n", ch1);

	printf("第五次分割:\n");
	ret = strtok(NULL, ch2);
	printf("%s\n", ret);
	printf("%s\n", ch1);

	return 0;
}

运行结果:

解疑:第一次分割将字符'.'修改为'\0',返回了起始地址,也就是字符'a'的地址,因为改变了源字符串的数据,所以此后以%s打印ch1只能打印abcd。第二次分割将字符'/'修改为'\0',然后返回了第二段起始地址,也就是字符'b'的地址。后面的结果依次类推就行。直到最后没有可分割字符返回空指针

是不是发现上面有大量重复的代码,其实我们可以使用循环来进行打印:

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

int main()
{
	char str[] = "123.4545.446.xpashisdid@qq.com";
	char* sep = ".@";

	for (char* ret = strtok(str, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}

	return 0;
}

运行结果:

解疑:以上for循环使用地非常巧妙,首先初始化部分调用一次strtok,传入需分割的字符串和分割字符。创建一个ret接收strtok的返回值,因为for循环初始化部分只会进行一次。所以该部分不会重复进行,然后判断部分写 ret != NULL,只要返回值不为空指针,循环就不终止。for调整部分写再一次调用strtok,传入空指针即可。strtok具有记忆保存的属性。如此一来就实现了循环分割打印的效果


十、strerror 函数的使用

1.使用:

功能:接收并记录程序运行时的错误码,返回错误码对应的错误信息的字符串地址

    

函数声明:char * strerror ( int errnum );

    

功能介绍:在不同的系统和C语言标准库的实现中都规定了一些错误码,一般是放在 errno.h 这个头文件中说明的,C语言程序启动的时候就会使用一个全局的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。

打印0~10错误码对应的信息:

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

int main()
{
	int i = 0;

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

	return 0;
}

运行结果:

(注:不包含 errno.h 头文件也可以打印)

使用演示:

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

int main()
{
	FILE* pf = fopen("xxx.txt", "r");

	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
	}

	return 0;
}

运行结果:

解疑:定义一个文件指针,以只读的形式打开一个不存在的文件,pf会接收到一个空指针,此时这个文件打开错误会被记录,使用if判断然后打印出这个错误信息,这在我们日常写代码中非常实用。另外记住使用strerror时要传参errno


2.补充:perror 函数的使用
 

函数声明:void perror ( const char * str );

    

功能介绍:perror与strerror类似,都是记录错误信息,但是不同的是:

  • perror使用时会直接打印出错误信息,不需要向strerror那样使用printf进行打印。
  • perror的参数,指我们可以自己添加一个需要打印的字符串信息在错误信息的前面
  • perror函数包含在 <stdio.h> 头文件中

使用演示:

#include <stdio.h>

int main()
{
	FILE* pf = fopen("xxx.txt", "r");

	if (pf == NULL)
	{
		perror("fopen");
	}

	return 0;
}

运行结果:

解疑:如图所示,我们传入perror的字符串参数最终会加上':'打印在屏幕上,我们传入的字符串可以提醒我们哪里或者哪个函数出的问题。更加的方便和实用

关于strerror与perror函数的选择,是根据自己的情况而定,只记录不打印选择strerror,只打印选择perror即可


总结

        以上就是本文的全部内容了,希望对大家有所帮助,感谢支持

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka中的时间轮算法

1. Kafka与时间轮&#xff1a; Kafka的定时器底层使用时间轮算法。Kafka时间轮是层次时间轮&#xff0c;并且支持时间轮复用。 优点&#xff1a; 高效的插入操作&#xff1a; 时间轮底层数据结构&#xff08;桶&#xff09;&#xff0c;使用双向链表的设计使得插入操作的时间…

手机是如何实现多个应用程序同时运行的?

想要理解这个问题&#xff0c;我们要先了解一下操作系统以及进程相关的知识&#xff1a; 操作系统的功能有很多&#xff0c; 例如&#xff1a; 进程管理&#xff08;Process Management&#xff09;&#xff1a; 功能&#xff1a;创建和终止进程&#xff0c;进程调度&#xf…

Android开发更改JDK版本

今天在跑GitHub上面一个Android项目时&#xff0c;在Android编译时出现如下错误&#xff1a; Unsupported Java. Your build is currently configured to use Java 17.0.2 and Gradle 7.0.2.错误原因&#xff1a; JDK和Gradle版本对应出错。 本地的JDK为1.8正好可以更改为本…

深入理解计算机系统 CSAPP 家庭作业6.34

第一步先求(S,E,B,m) 题目说共C32个字节,块大小B为16个字节,那就是分为两组:0,1.然后每组存4个int 每个4字节 CB*E*S .B16 ,直接映射的E就是1,所以S2 m为啥等于7? 通过写出两个数组所有的地址可以得出m7. 得出高速缓存的参数:(S,E,B,m)(2,1,16,7),注意图6-26每个参数的定义…

适合加密货币交易者的免费指标

本文介绍了7种用于分析加密货币市场的免费技术指标&#xff0c;帮助交易者和投资者提升交易技巧和盈利能力。原文: Best 7 Free Trading Indicators for Every Cryptocurrency Trader Austin Distel Unsplash 大家好&#xff01;无论是加密货币市场的交易者还是投资者&#xff…

(Java微服务项目实战)dtpay聚合支付系统对账管理模块系统设计

1 聚合支付系统对账流程 dtpay聚合支付系统对账模块主要涵盖商户侧对账和渠道侧对账、平台侧对账&#xff0c;本文主要分析渠道侧对账。dtpay聚合支付系统通过支付渠道微信、支付宝等产生的支付退款交易数据需要和平台侧产生的数据进行交易数据比对。接下来我们具体分析对账流…

手把手教学部署前端项目到nginx

1.下载nginx 说明&#xff1a;下载11.20.2版本的nginx。 2.配置nginx 说明&#xff1a;找到conf目录下的nginx.conf文件。 2.1代理静态资源 说明&#xff1a;服务器块监听的端口为8089&#xff0c;意味着Nginx将在8089端口上接收和处理HTTP请求。root后面的值相当于html文…

实时交通 | 城市交通态势采集及可视化操作(定时运行)

一、前言 交通态势数据是关于交通状况的一种量化描述&#xff0c;它提供了关于道路网络运行状态的详细信息。交通态势数据指的是根据车流入量和车流出量的定义&#xff0c;衡量整个全局交通区域交通态势的数据。这些数据通常从车辆GPS轨迹数据中提取&#xff0c;包括车辆行驶速…

时代巨兽!深度神经网络如何改变我们的世界?

深度神经网络 1、 简介1.1 定义深度神经网络1.2 深度学习的发展历程1.3 深度神经网络的应用领域 2、深度神经网络的基本原理2.1 神经元层2.1.1 神经元2.1.2 神经元层 2.2 前向传播2.3 反向传播2.4 激活函数2.4.1、作用2.4.2、常见激活函数2.4.3、选择激活函数的考虑 2.5 损失函…

new Set( )的基本使用以及如何去重对象数组

目录 Set 对象方法 Set 对象作用 实现数组的去重 实现字符串的去重 实现并集 交集 差集 实现去重对象数组 相关参考资料 在 ES6 中&#xff0c;引入了一个新的数据结构类型&#xff1a;Set。而 Set 与 Array 的结构是很类似的&#xff0c;且 Set 和 Array 可以相互进…

MySQL学习——创建MySQL Workbench中的Connections

在MySQL Workbench中&#xff0c;Connections&#xff08;连接&#xff09;是用户与MySQL数据库进行交互的桥梁。 本文将添加一个新连接&#xff0c;该连接可以是初始连接&#xff0c;也可以是附加连接。在开始之前&#xff0c;必须安装、启动MySQL服务器的实例&#xff0c;并…

算法体系-19 第十九节 暴力递归到动态规划

一 动画规划的概念 优化出现重复解的递归 一旦写出递归来&#xff0c;改动态规划就很快 尝试策略和状态转移方程是一码事 学会尝试是攻克动态规划最本质的能力 如果你发现你有重复调用的过程&#xff0c;动态规划在算过一次之后把答案记下来&#xff0c;下回在越到重复调用过程…

基于springboot实现农产品直卖平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现农产品直卖平台系统的设计演示 摘要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔…

【安卓设备】通过adb批量安装apk

1、adb链接设备 H:\tv\apk>adb connect 127.0.0.1:21503 2、批量安装apk 如果地址不一致需要将 H:\tv\apk\ 改成自己的路径地址&#xff0c;同时注意该命令只能安装文件名为英文的不支持中文名称&#xff0c;如果有需要先更改文件名称。 H:\tv\apk>for %f in (H:\tv\a…

IT入门知识博客文章大纲第一部分《IT基础知识》(1/10)

目录 IT入门知识博客文章大纲第一部分《IT基础知识》&#xff08;1/10&#xff09; 1.引言 2.第一部分&#xff1a;IT基础知识 2.1 计算机硬件 CPU&#xff1a;计算机的心脏 内存&#xff1a;数据的临时居所 存储设备&#xff1a;数据的长期仓库 输入输出设备&#xff1…

Node.js和npm的安装及配置

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞 I/O 的模型。 npm&#xff08;node package manager&#xff09;是一个 Node.js 包管理和分发工具&#xff0c;也是整个 Node.js 社区最流行、支持第三方模块最多的包管理器。使…

【YashanDB知识库】PHP使用ODBC使用数据库绑定参数功能异常

【问题分类】驱动使用 【关键字】ODBC、驱动使用、PHP 【问题描述】 PHP使用PDO_ODBC连接yashan数据库&#xff0c;使用绑定参数获取数据时&#xff0c;客户现场出现报错 本地复现未出现异常报错&#xff0c;但是无法正确获取数据。 【问题原因分析】开启ODBC报错日志后&am…

使用 Python 进行测试(1)测试基础

原文 总结 我们将从unittest开始&#xff0c;尽管它并不那么好用&#xff0c;但它是Python标准库中的测试工具。 使用unittest编写测试看起来像这样&#xff1a; import unittest# 需要测试的代码 def add(a, b):return a b# The tests class TestAddFunction(unittest.Test…

网络安全攻防基础入门笔记--操作系统名词解释文件下载反弹shell防火墙绕过

渗透测试常用专业术语 POC,EXP,Payload,Shellcode POC 全程Proof of Concept,中文"概念验证",常指一段漏洞证明的代码 EXP 全程Exploit ,中文"利用",指利用系统漏洞进行攻击的动作 Payload 中文"有效载荷",指成功Exploit之后,真正在目标系…

车道偏离预警系统技术规范(简化版)

车道偏离预警系统技术规范&#xff08;简化版&#xff09; 1 系统概述2 预警区域3 功能条件4 显示需求5 指标需求 1 系统概述 车道偏离预警系统工作在中高速驾驶的情况下&#xff0c;当驾驶员因注意力不集中导致车辆偏离本车道时&#xff0c;系统通过光学和声学信号对驾驶员进行…