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码值,其返回值分为三种:
- 返回值 >0,表示 str1 中某一位字符大于 str2 对应位的字符
- 返回值 <0,表示 str1 中某一位字符小于 str2 对应位的字符
- 返回值 == 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;
}
解疑:
- 首先创建了三个指针变量,s1,s1分别用来记录str1和str2比较过程中的地址,cur记录的是str1当前位置的地址,因为途中的比较过程会打乱str1指针的指向,因此需要cur来记录str1当前位置的地址,以便s1在比较过程中没有找到相同字符串时,可以通过cur找回起始位置。而str2本身指向是不会变的,因此不需要另外的指针进行记录当前位置。
- if (*str2 == '\0') ,这个意思是如果str2是个空字符串的话,直接返回str1的地址,这是C语言标准中strstr的规定。并且空字符串本身也不需要寻找,任何字符串都包含空字符串
- while (*cur) ,这个循环条件就是cur没有指向字符串末尾。然后给s1赋值为cur,s2赋值为str2,。s1,s2就是用来比较判断两字符串是否有相同的指针。
- while (*s1 && *s2 && *s1 == *s2),这个循环意思是,只要s1,s2没有指向字符串末尾并且它两指向的字符相等,就让s1,s2一直往后走,只要有其中一个条件不满足时,循环就终止
- 循环终止后就进行一个判断,if (*s2 == '\0'),该判断的意思是,如果s2等于'\0',表示前一个循环是因为s2走到字符串末尾而终止的,s2能走到末尾,就表示s2前面的字符与s1都相同,这就表明能在str1中找到str1,此时只需要终止函数,返回cur,也就是str1当前的地址就行
- 而如果s1指向的字符不为'\0',就表示前一个循环的终止是因为s1,s2指向的字符不相同导致的,就再进行一个判断,if (strlen(cur+1) < strlen(str2)),这个判断表示,当前str1指向的下一个位置到字符串末尾的长度,如果小于str2的长度,就表明str1后面一定找不到str2了,为了提高效率,直接返回空指针。
- 如果两个判断都不满足,就让str1当前的位置往后走一步,也就是cur++,再进行循环判断。
- 如果直到最后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即可
总结
以上就是本文的全部内容了,希望对大家有所帮助,感谢支持
相关文章:
C语言之常用字符串函数总结、使用和模拟实现
文章目录 目录 一、strlen 的使用和模拟实现 二、strcpy 的使用及模拟实现 三、strcat 的使用和模拟实现 四、strcmp 的使用和模拟实现 五、strncpy 的使用和模拟实现 六、strncat 的使用和模拟实现 七、strncmp 的使用和模拟实现 八、strstr 的使用和模拟实现 九、st…...
【JMeter接口测试工具】第二节.JMeter项目实战(上)【实战篇】
文章目录 前言项目实战零、接口测试流程一、测试数据准备二、接口功能测试三、掌握测试用例编写四、自动化脚本架构搭建总结 前言 零、接口测试流程 1、制定测试计划,分配任务 2、从 API 文档中提取接口清单:对 API 文档简化,提高测试效率,接口清单就是对 API 文档…...
Ansible——fetch模块
目录 参数 示例1:最基本的用法 示例2:指定目标目录和主机名子目录 示例3:flat 参数设置为 yes 示例4:处理源文件不存在的情况 示例5:验证文件校验和 示例 Playbook 1. 拉取远程主机上的 syslog 文件 2. 直接…...
HTTP常见响应状态码
1xx:正在处理中 100 Continue:服务器确认收到了请求的第一部分,并告知客户端继续发送剩余的请求。 101 Switching Protocols:服务器根据客户端的请求,同意切换到另一个协议。 2xx:成功响应 200 OK&#…...
如何制定工程战略
本文介绍了领导者如何有效制定工程战略,包括理解战略核心、如何收集信息并制定可行的策略,以及如何利用行业最佳实践和技术债务管理来提升团队效能和产品质量。原文: How to Build Engineering Strategy 如果你了解过目标框架(如 OKR…...
认识和使用 Vite 环境变量配置,优化定制化开发体验
Vite 官方中文文档:https://cn.vitejs.dev/ 环境变量 Vite 内置的环境变量如下: {"MODE": "development", // 应用的运行环境"BASE_URL": "/", // 部署应用时使用的 URL 前缀"PROD": false, //应用…...
Java18新特性总结
Java 18作为Java编程语言的一个重要更新,引入了一系列新特性和改进,旨在提高开发者的生产力和程序的性能。以下是Java 18的主要新特性概述: 元编程功能: Java 18引入了元注释和元类型声明的功能,允许开发人员在编译时…...
理解 Java 中的 `final` 关键字
理解 Java 中的 final 关键字 final 关键字是 Java 编程语言中一个重要的修饰符,它可以应用于类、方法和变量。理解 final 的用法和作用对于编写稳健和高效的 Java 代码至关重要。在本文中,我们将深入探讨 final 关键字的各种用法及其意义。 一、final…...
磁盘未格式化:深度解析、恢复方案及预防之道
在当今这个信息化爆炸的时代,磁盘未格式化问题无疑成为了众多用户头疼的难题。当我们的存储设备突然提示“磁盘未格式化”时,数据的丢失与恢复的挑战便摆在了我们面前。本文将深入解析磁盘未格式化的现象、原因,并给出两种有效的数据恢复方案…...
JWT 从入门到精通
什么是 JWT JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案 JSON Web Token Introduction - jwt.ioLearn about JSON Web Tokens, what are they, how they work, when and why you should use them.https://jwt.io/introduction 一、常见会…...
31-捕获异常(NoSuchElementException)
在定位元素的时候,经常会遇到各种异常,遇到异常又该如何处理呢?本篇通过学习selenium的exceptions模块,了解异常发生的原因。 一、发生异常 打开百度搜索首页,定位搜索框,此元素id"kw"。为了故意…...
使用Spring Boot设计对象存储系统
对象存储系统是一种以对象为存储单位的存储架构,适合存储大量非结构化数据,如图片、音视频文件、文档等。MinIO是一个高性能的对象存储系统,基于开源和云原生的设计理念。本文将讨论如何使用Spring Boot设计一个类似MinIO的对象存储系统。 目…...
Apple开发者macOS设备与描述文件Profile创建完整过程
安装并打开Apple Configurator 新建描述文件 输入macOS平台的描述文件的相关信息,然后选择证书 选择一个可用证书 存储描述文件 存储成功如下: 使用文本编辑器打开刚才保存的描述文件,找到设备名与UDID...
SpringBootWeb 篇-深入了解 Redis 五种类型命令与如何在 Java 中操作 Redis
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 Redis 概述 1.1 Redis 下载与安装 2.0 Redis 数据类型 3.0 Redis 常见五种类型的命令 3.1 字符串操作命令 3.2 哈希操作命令 3.3 列表操作命令 3.4 集合操作命令 …...
mysql设置允许外部ip访问,局域网IP访问
(支持MYSQL8版本) 1. 登录进入mysql;mysql -uroot -p输入密码进入 2. 输入以下语句,进入mysql库,查看user表中root用户的访问 use mysql; select host,user from user; 3. 更新user表中root用户域属性,…...
mac虚拟光驱工具:Daemon Tools for Mac
Daemon Tools for Mac是一款功能强大的虚拟光驱工具,它为用户提供了在Mac上模拟物理光驱的能力,从而方便用户处理各种光盘映像文件。以下是关于Daemon Tools for Mac的详细介绍: 守护进程工具:Daemon Tools不仅是一个简单的虚拟光…...
软考 系统架构设计师系列知识点之杂项集萃(32)
接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(31) 第51题 网络逻辑结构设计的内容不包括( )。 A. 逻辑网络设计图 B. IP地址方案 C. 具体的软硬件、广域网连接和基本服务 D. 用户培训计划 正确答案&am…...
Web--CSS基础
文章目录 定义方式选择器文本字体背景边框元素展示格式内边距与外边距盒子模型位置浮动flex布局响应式布局 定义方式 行内样式表 直接定义在style属性中,作用于当前标签 <img src "/imges/logo.jpg" alt "" style "width 400"…...
服务部署:Linux系统部署C# .NET项目
1. 安装 .NET SDK 首先,你需要在你的 Linux 系统上安装 .NET SDK。 Ubuntu系统: 下载 Microsoft 包配置文件 wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 这个命令使用 wge…...
【机器学习】基于卷积LSTM的视频预测
1. 引言 1.1 LSTM是什么 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络(RNN)变体,旨在解决传统RNN在处理长序列数据时遇到的梯度消失和梯度爆炸问题。LSTM通过引入门控机制和细胞状态的概念,使得…...
细说wayland和X11
文章目录 协议介绍协议区别开发差异 Wayland和X11都是用于Linux和其他类Unix系统的显示服务器协议。它们负责在用户和应用程序之间的交互中管理屏幕的输出以及输入设备的输入。 协议介绍 X11通常称为X Window System,是一个历史悠久的显示服务器,自1987…...
数据结构:二叉树的实现
目录 二叉树的遍历方式 前序遍历: 中序遍历: 后序遍历: 二叉树的基本结构和功能 基本结构: 基本功能: 二叉树功能的实现思路 二叉树功能的实现 1、构建一个二叉树 2、二叉树的销毁 3、计算二叉树里的节点个数 4、得…...
Helm离线部署Rancher2.7.10
环境依赖: K8s集群、helm 工具 Rancher组件架构 Rancher Server 包括用于管理整个 Rancher 部署的所有软件组件。 下图展示了 Rancher 2.x 的上层架构。下图中,Rancher Server 管理两个下游 Kubernetes 集群 准备Rancher镜像推送到私有仓库 cat >…...
Linux目录的作用和常用指令
目录结构及其详细作用 / (根目录) Linux文件系统的起点,所有文件和目录都在其下。 /bin 存放系统启动和运行时所需的基本命令,如 ls, cp, mv, rm,这些命令在单用户模式下或系统崩溃时仍然可用。 /boot 包含启动引导加载器的文件和Linux内核…...
Nvidia/算能 +FPGA+AI大算力边缘计算盒子:隧道和矿井绘图设备
RockMass 正在努力打入采矿业和隧道工程利基市场。 这家位于多伦多的初创公司正在利用 NVIDIA AI 开发一款绘图平台,帮助工程师评估矿井和施工中的隧道稳定性。 目前,作为安全预防措施,地质学家和工程师会站在离岩石五米远的地方࿰…...
MySQL物理备份
目录 备份策略 全量备份 (Full Backup) 增量备份 (Incremental Backup) 差异备份 (Differential Backup) 使用 Percona XtraBackup 全量备份 步骤 1:全量备份 步骤 2:备份后处理(应用日志) 步骤 3:恢复备份 验…...
AWT常用组件
AWT中常用组件 前言一、基本组件组件名标签(Label类)Label类的构造方法注意要点 按钮(Button)Button的构造方法注意要点 文本框(TextField)TextField类的构造方法注意要点 文本域(TextArea)TextArea 的构造方法参数scrollbars的静态常量值 复选框&#x…...
CorelDRAW2024破解激活码序列号一步到位
亲们,今天给大家种草一个神奇的软件——CorelDRAW破解2024最新版!🎨这是一款专业级的矢量图形设计软件,无论你是平面设计师、插画师还是设计师,都能在这个软件中找到你需要的工具和功能。✨ 让我来给大家介绍一下这款软…...
Webpack前端打包工具详解
目录 Webpack前端打包工具详解一、Webpack 的作用二、Webpack 的安装和基本使用1. 安装 Webpack2. 创建 Webpack 配置文件3. 运行 Webpack 三、Webpack 核心概念1. 入口(Entry)2. 输出(Output)3. 加载器(Loaders&#…...
计网总结☞网络层
.................................................. 思维导图 ........................................................... 【Wan口和Lan口】 WAN口(Wide Area Network port): 1)用于连接外部网络,如互联…...
西宁网站制作哪里好/河南搜索引擎优化
图形学界大牛Jim Blinn对Phong模型进行了改进,提出了Blinn-Phong模型。Blinn-Phong模型与Phong模型的区别是,把dot(V,R)换成了dot(N,H),其中H为半角向量,位于法线N和光线L的角平分线方向。Blinn-Phong模型可表示为: Is…...
wordpress网站合并/优化大师下载
配置好了conda环境,想要继续打开该环境时,出现服务器出问题 问题描述: jupyter notebook打开显示500 : Internal Server Error 解决方法: 在CMD中直接输入: pip install --upgrade --user nbconvert 解决历程&…...
aws如何搭建wordpress/百度推广管理
1. Telnet Telnet:(Telecommunication和Network的联合缩写) 是TCP/IP协议族中的一员,属于应用层协议,是Internet远程登录服务器的标准协议和主要方式。 telnet服务属于典型的客户机/服务器模型,当用telnet…...
石景山网站建设有哪些公司/seo是什么意思 职业
10:简单密码 描述 Julius Caesar曾经使用过一种很简单的密码。对于明文中的每个字符,将它用它字母表中后5位对应的字符来代替,这样就得到了密文。比如字符A用F来代替。如下是密文和明文中字符的对应关系。密文A B C D E F G H I J K L M N O P Q R S T U…...
网站建设 html5/怎么做百度网页
三层架构已经学了一段时间,一直想做一个比較完整、比較完美的总结。可是左思右想,不知道怎样下笔。都说万事开头难嘛,今天整理了一下凌乱的思路,哎,还是没整理好,想到哪就说到哪吧。 刚開始学习的人非常不理解…...
织梦做英文网站/google play下载安装
Index与Shard,这两个概念在《Elasticsearch最佳实践之核心概念与原理》一文有详细的介绍,分别对应了Elasticsearch的两种数据组织方式:逻辑组织和物理组织。逻辑层面上,Index与业务数据的结构、类型、使用方式等息息相关ÿ…...