目录
1、strlen函数
strlen函数的模拟实现
2、strcpy函数
strcpy函数的模拟实现
strncpy函数
strncpy函数的模拟实现
3、srtcat函数
strcat函数的模拟实现
strncat函数
strncat函数的模拟实现
4、strcmp函数
strcmp函数的模拟实现
strncmp函数
5、strstr函数
strstr函数的模拟实现
6、strtok函数
7、strerror函数
8、perror函数
1、strlen函数
描述:
C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。
函数声明:
size_t strlen(const char *str)
返回值:
该函数返回字符串的长度。
用法:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[50];
int len;
strcpy(str, "This is runoob.com");
len = strlen(str);
printf("|%s| 的长度是 |%d|\n", str, len);
return(0);
}
结果:
strlen函数的模拟实现
#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
int count = 0;
assert(str);
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = { "hello world!" };
int red = my_strlen(arr);
printf("%d\n", red);
return 0;
}
2、strcpy函数
描述:
C 库函数 char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest。
需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。
函数声明:
char *strcpy(char *dest, const char *src)
参数:
- dest -- 指向用于存储复制内容的目标数组。
- src -- 要复制的字符串。
返回值:
该函数返回一个指向最终的目标字符串 dest 的指针。
用法:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]="Sample string";
char str2[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,"copy successful");
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
return 0;
}
结果:
strcpy函数的模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* str)
{
char* ret = dest;//把dest的地址给ret
assert(dest != NULL);
assert(str != NULL);
while (*dest++ = *str++)//将str上的值赋给dest
{
;
}
return ret;//ret是一个插入类型的指针,里面存储着dest的地址
}
int main()
{
char arr1[] = { "hello world!" };
char arr2[100] = { 0 };
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
strncpy函数
与strcpy相似,只是多了一个限制复制字符个数的条件
声明:
char *strncpy(char *dest, const char *src, size_t n)
n -- 要从源中复制的字符数。
用法:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = { "hello world" };
char arr2[20] = { 0 };
int n = 5;
strncpy(arr2, arr1, n);
printf("%s\n", arr2);
return 0;
}
strncpy函数的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strncpy(char* dest, char* str, size_t n)
{
char* ret = dest;
assert(dest != NULL);
assert(str != NULL);
int i = 0;
for (i = 0; i < n; i++)
{
*dest++ = *str++;
}
return ret;
}
int main()
{
char arr1[20] = "hello world";
char arr2[20] = { 0 };
int num = 7;
my_strncpy(arr2, arr1, num);
printf("%s\n", arr2);
return 0;
}
结果:
3、srtcat函数
描述:
C 库函数 char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
函数声明:
char *strcat(char *dest, const char *src)
参数:
- dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。
- src -- 指向要追加的字符串,该字符串不会覆盖目标字符串。
返回值:
该函数返回一个指向最终的目标字符串 dest 的指针。
用法:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[20] = { 0 };
strcpy(arr1, "world hello");
strcpy(arr2, "hello ");
strcat(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
strcat函数的模拟实现
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* dest, const char* str)
{
char* ret = dest;//把dest的地址给ret
assert(dest != NULL);
assert(str != NULL);
while (*dest)
{
dest++;//遍历完dest
}
//在遍历完dest的基础上再给dest赋值
while (*dest++ = *str++)
{
;
}
return ret;//ret是一个char类型的指针,里面存储着dest的地址
}
int main()
{
char arr1[] = { "hello world!" };
char arr2[100] = { "hello " };//目标空间一定要足够,不然会报错
my_strcat(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
strncat函数
与strcat相似,只是多了一个限制追加字符个数的条件
函数声明:
char *strncat(char *dest, const char *src, size_t n)
n -- 要追加的最大字符数。
用法:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[20] = { 0 };
strcpy(arr1, "world hello");
strcpy(arr2, "hello ");
int num = 5;
strncat(arr2, arr1,num);
printf("%s\n", arr2);
return 0;
}
结果:
strncat函数的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strncat(char* dest, char* str, size_t n)
{
assert(dest != NULL);
assert(str != NULL);
char* ret = dest;
while (*dest)
{
dest++;
}
for (int i = 0; i < n; i++)
{
*dest++ = *str++;
}
return ret;
}
int main()
{
char arr1[20] = { 0 };
char arr2[20] = { 0 };
strcpy(arr1, "world hello");
strcpy(arr2, "hello ");
int num = 5;
my_strncat(arr2, arr1,num);
printf("%s\n", arr2);
return 0;
}
结果:
4、strcmp函数
描述:
C 库函数 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。
声明:
int strcmp(const char *str1, const char *str2)
参数:
- str1 -- 要进行比较的第一个字符串。
- str2 -- 要进行比较的第二个字符串。
返回值:
- 如果返回值小于 0,则表示 str1 小于 str2。
- 如果返回值大于 0,则表示 str1 大于 str2。
- 如果返回值等于 0,则表示 str1 等于 str2。
用法:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
ret = strcmp(str1, str2);
if(ret < 0)
{
printf("str1 小于 str2");
}
else if(ret > 0)
{
printf("str1 大于 str2");
}
else
{
printf("str1 等于 str2");
}
return(0);
}
strcmp函数的模拟实现
#include <stdio.h>
#include <assert.h>
#include <string.h>
int my_strcmp( const char* s1,const char* s2)
{
assert(s1 != NULL);
assert(s2 != NULL);
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return *s1 - *s2;
}
int main()
{
char str1[15];
char str2[15];
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
int ret = my_strcmp(&str1, &str2);
if (ret > 0)
{
printf("str1 > str2\n");
}
else if (ret < 0)
{
printf("str1 < str2\n");
}
else
{
printf("str1 = str2\n");
}
return 0;
}
strncmp函数
函数声明:
int strncmp(const char *str1, const char *str2, size_t n)
用法:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
ret = strncmp(str1, str2, 4);
if(ret < 0)
{
printf("str1 小于 str2");
}
else if(ret > 0)
{
printf("str2 小于 str1");
}
else
{
printf("str1 等于 str2");
}
return(0);
}
5、strstr函数
描述:
C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。
声明:
char *strstr(const char *haystack, const char *needle)
参数:
- haystack -- 要被检索的 C 字符串。
- needle -- 在 haystack 字符串内要搜索的小字符串。
返回值:
该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null。
用法:
#include <stdio.h>
#include <string.h>
int main()
{
const char haystack[20] = "notebook";
const char needle[10] = "book";
char* ret = strstr(haystack, needle);
if (ret != NULL)
{
printf("%s\n", ret);
}
else
{
printf("找不到\n");
}
return 0;
}
strstr函数的模拟实现
这个函数的模拟实现就比较麻烦了。我们来仔细分析一下。
先来看函数的定义:
char* my_strstr(const char* haystack, const char* needle)
haystack和needle分别指向字符串的首字母,如果找到相同的字符,haystack和needle向后移一位,如果没有找到相同的,haystack向后移一位。如果全部找到,就要返回 b 的地址。当haystack和needle分别向后找的时候,没人会记得b的地址,所以就要有一个指针记录开始匹配的位置。
但是还有一种情况:
haystack找到n的时候和needle找到 t 的时候,两个不匹配,就要重匹配,needle就要重新回去,所以还要有一个指针记录needle的起始位置.同理也还要一个指针记录haystack的起始位置。
#include <stdio.h>
char* my_strstr(const char* haystack, const char* needle)
{
const char* str1 = NULL;//str1 用来记录haystack
const char* str2 = NULL;//str2 用来记录needle
const char* count = haystack;// count记录 查找的起始位置
while (*count)
{
str1 = count; //将查找的起始位置给str1
str2 = needle;//将被查找的起始位置给str2
while (*str1 != '\0' && *str2 != '\0' && *str1 == *str2)
{ //*str1为\0,就说明后面没有可以查找的了
//*str2为\0,就说明已经找完了
str1++;
str2++;
}
if (*str2 == '\0')
{
return (char*)count;//查找完了就返回查找的起始位置count
}
count++; //查找不匹配,查找起始位置就往后移一位
}
return NULL; //找不到返回空指针
}
int main()
{
char arr1[20] = "nonotebook";
char arr2[10] = "note";
char* ret = my_strstr(arr1, arr2);
if (ret != NULL)
{
printf("%s\n", ret);
}
else
{
printf("找不到\n");
}
return 0;
}
6、strtok函数
描述:
C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。
声明:
char *strtok(char *str, const char *delim)
参数:
- str -- 要被分解成一组小字符串的字符串。
- delim -- 包含分隔符的 C 字符串。
返回值:
该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
用法:
#include <string.h>
#include <stdio.h>
int main() {
char str[80] = "This is - www.runoob.com - website";
const char s[2] = "-";
char* token;
/* 获取第一个子字符串 */
token = strtok(str, s);
/* 继续获取其他的子字符串 */
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, s);
}
return(0);
}
7、strerror函数
描述:
C 库函数 char *strerror(int errnum) 从内部数组中搜索错误号 errnum,并返回一个指向错误消息字符串的指针。strerror 生成的错误字符串取决于开发平台和编译器。
声明:
char *strerror(int errnum)
参数:
- errnum -- 错误号,通常是 errno。
返回值:
该函数返回一个指向错误字符串的指针,该错误字符串描述了错误 errnum。
strerror函数可以把参数部分错误码对应的信息的字符串地址返回来。
在不同的系统和C语言标准库的实现中都规定了一些错误码,一般是放在error.h这个头文件中说明的,C语言程序启动的时候就会使用一个全面的变量 errno 来记录程序的当前错误码,只不过程序启动的时候 errno 是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在 errno 中,而一个错误码的数字是整数很难理解是什么意思,所以每一个错误码都是有对应的错误信息的。 strerror 函数就可以将错误对应的错误信息字符串的地址返回。
在Windouws和VS2022环境下
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i = 0;
for (i = 0; i <= 10; i++) {
printf("%s\n", strerror(i));
}
return 0;
}
结果:
用法:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE *fp;
fp = fopen("file.txt","r");
if( fp == NULL )
{
printf("Error: %s\n", strerror(errno));
}
return(0);
}
结果:
8、perror函数
描述:
C 库函数 void perror(const char *str) 把一个描述性错误消息输出到标准错误 stderr。首先输出字符串 str,后跟一个冒号,然后是一个空格。
声明:
void perror(const char *str)
参数:
- str -- 这是 C 字符串,包含了一个自定义消息,将显示在原本的错误消息之前。
注意,这里str是一个C字符串,就要用C字符串的格式来写
返回值:
该函数没有返回值。
用法:
#include <stdio.h>
int main ()
{
FILE *fp;
/* 首先重命名文件 */
rename("file.txt", "newfile.txt");
/* 现在让我们尝试打开相同的文件 */
fp = fopen("file.txt", "r");
if( fp == NULL ) {
perror("Error: ");
return(-1);
}
fclose(fp);
return(0);
}