引言
在上一篇中,我们介绍了字符函数和一些字符串函数,在这一篇章中,我们会继续学习字符串函数,那我们现在就开始学习吧!!!
字符串函数
strncpy
1.strncpy的用法
strncpy是一个在C语言中常用的字符串处理函数,用于将源字符串的前n个字符复制到目标字符串中。其函数原型为:
char *strncpy(char *dest, const char *src, size_t n);
其中,参数的含义如下:
dest 是目标字符串,即你想要将源字符串的字符复制到的位置
src 是源字符串,即你想要从中复制字符的字符串
n 是你想要从源字符串中复制的字符数
如果源字符串的长度小于 n,strncpy 会复制源字符串的所有字符到目标字符串中,并在目标字符串的剩余位置上用 \0 填充,直到总共复制了 n 个字符
2.strncpy的使用
当src的字符串长度>=n
int main()
{
char src[12] = "hello world";
char dest[] = "xxxxxxxxxxxx";
strncpy(dest, src, 5);
printf("最终的目标字符串:%s\n", dest);
return 0;
}
运行结果为:
最终的目标字符串:helloxxxxxxx
当src的字符串长度<n
int main()
{
char src[25] = "hello world";
char dest[] = "xxxxxxxxxxxxxx";
strncpy(dest, src, 20);
printf("最终的目标字符串:%s\n", dest);
return 0;
}
运行结果为:
最终的目标字符串:hello world
3.strncpy的模拟实现
思路:通过自定义的 my_strncpy 函数,将源字符串 str2 的 n 个内容复制到目标字符串 str1 中,确保复制操作安全进行(通过断言检查指针非空),并返回目标字符串的起始地址。
代码如下:
char* my_strncpy(char* dest,const char* src,size_t n)
{
// 断言dest和src不是空指针,以确保它们是有效的内存地址
assert(dest && src);
// 保存dest的原始地址,以便稍后返回
char* ret = dest;
// 循环复制字符,直到遇到源字符串的结束符'\0',或者复制了n个字符
while (*src && n)
{
*dest = *src;
dest++;
src++;
n--; // 递减n,表示已经复制了一个字符
}
// 如果n不为0,说明还有剩余的空间需要填充null终止符
if (n != 0)
{
while (n)
{
*dest = '\0';
dest++;
n--;
}
}
return ret;
}
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "bbq";
my_strncpy(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
strncat
1.strncat的用法
strncat()函数是C语言中的一个字符串函数,用于将一个字符串的前n个字符连接到另一个字符串的末尾。
函数的原型为:
char *strncat(char *dest, const char *src, size_t n);
其中,参数的含义如下:
dest:目标字符串,即要将源字符串连接到的位置
src:源字符串,即要连接到目标字符串末尾的字符串
n:要连接的字符个数
strncat函数的工作原理是将源字符串src中的字符逐个复制到目标字符串dest的末尾,直到复制了指定的字符个数n或者遇到了源字符串的结束符'\0'。连接完成后,目标字符串dest的末尾会添加一个新的结束符'\0'。如果源字符串的长度小于n,则strncat函数会将整个源字符串连接到目标字符串的末尾。
2.strncat的使用
当src的字符串长度>n
int main()
{
char str1[20] = "hello";
char str2[20] = "hello world";
strncat(str1, str2, 5);
printf("%s\n", str1);
return 0;
}
输出结果为:hellohello
当src的字符串长度<=n
int main()
{
char str1[20] = "hello";
char str2[20] = "hello world";
strncat(str1, str2, 15);
printf("%s\n", str1);
return 0;
}
输出结果为:hellohello world
3.strncat的模拟实现
思路:先找到目标字符串的末尾位置,然后将源字符串的前n个字符逐个追加到目标字符串的末尾,并更新目标字符串的长度
代码如下:
char* my_strncat(char* dest, const char* src, int n)
{
char* ret = dest; //将dest首地址储存在ret中
assert(dest && src); //保证dest、src非空
while (*dest != '\0') //找到dest结尾的'\0'
{
dest++;
}
while (n && (*dest++ = *src++))//把src里的字符一个个放入dest后
{
n--; //跳出循环的条件
}
if (n == 0)
{
*dest = '\0'; //如果n<src
}
return ret; //返回dest字符串起始地址
}
int main()
{
char str1[20] = "hello ";
char str2[] = "world";
my_strncat(str1, str2, 5);
printf("%s\n", str1);
return 0;
}
strncmp
1.strncmp的用法
strncmp 是一个字符串比较函数,用于比较两个字符串的前n个字符
函数原型为:
int strncmp(const char *str1, const char *str2, size_t n);
其中,参数的含义如下:
str1:要比较的第一个字符串
str2:要比较的第二个字符串
n:要比较的最大字符数
返回值:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。
2.strncmp的使用
int main()
{
char arr1[20] = "abcdef";
char arr2[20] = "abcddd";
char arr3[20] = "abcdff";
int ret1 = strncmp(arr1, arr2, 3);
int ret2 = strncmp(arr1, arr2, 8);
int ret3 = strncmp(arr1, arr2, 6);
int ret4 = strncmp(arr1, arr3, 6);
printf("%d %d %d %d\n", ret1, ret2, ret3, ret4);
return 0;
}
输出结果为:0 1 1 -1
3.strncmp的模拟实现
思路:逐个比较两个字符串的前n个字符的ASCII值,直到遇到不同字符、遇到空字符或比较完n个字符为止,根据比较结果返回相应的整数。
代码如下:
int my_strncmp(const char* str1, const char* str2, size_t n)
{
assert(str1 && str2);
// 如果n为0,说明不需要比较任何字符,直接返回0,表示两个字符串的前0个字符是相同的。
if (n == 0)
{
return 0;
}
// 循环条件中,*str1 == *str2 确保两个字符相同,
// *str1 确保str1没有到达字符串结束符,
// --n 确保已经比较了n个字符或n已经减到0。
while (*str1 == *str2 && *str1 && --n)
{
// 如果两个字符相同且没有到达字符串结束符,继续比较下一个字符。
str1++;
str2++;
}
//返回的是两个字符的ASCII码差值。
return *str1 - *str2;
}
int main()
{
char str1[] = "abcddd";
char str2[] = "abcdef";
int ret1 = my_strncmp(str1, str2, 4);
int ret2 = my_strncmp(str1, str2, 6);
printf("%d %d\n", ret1, ret2);
return 0;
}
strstr
1.strstr的用法
strstr用于查找一个字符串 str2 是否存在于另一个字符串 str1 中,并返回 str2 在 str1 中首次出现的位置。以下是关于strstr函数的详细介绍。
函数原型为:
char *strstr(const char* str1, const char* str2);
其中,参数的含义如下:
str1:这是主串,即你希望在其中查找子串的字符串。
str2:这是子串,即你希望在主串中查找的字符串。
返回值:
如果str2是str1的子串,strstr返回一个指向str1中str2首次出现的位置的指针。
如果str2不是str1的子串,strstr返回NULL。
2.strstr的使用
int main()
{
const char* str1 = "hello world";
const char* str2 = "world";
char* result = strstr(str1, str2);
if (result != NULL)
{
printf("找到了,子字符串为:%s\n", result);
}
else
{
printf("找不到\n");
}
return 0;
}
输出结果为:找到了,子字符串为:world
3.strstr的模拟实现
思路:通过遍历主串,依次比较每个位置开始的子串是否与目标子串匹配,直到找到匹配或遍历完整个主串
代码如下:
char* my_strstr(const char* str1, const char* str2)
{
const char* s1 = NULL; //用于遍历str1
const char* s2 = NULL; //用于遍历str2
const char* cp = str1; //指向str1的起始地址
//检查传入的第二个字符串str2是否为空字符串(即只包含一个结束字符\0)
//如果str2是空字符串,函数会立即返回str1的起始地址。
if (*str2 == '\0')
return (char*)str1;
//遍历str1的字符
while (*cp)
{
s1 = cp; //初始化s1为当前cp的位置
s2 = str2; //初始化s2为当前str2的位置
//s1和s2均为到达末尾,且字符相等,则继续比较
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1++; //s1向后移动一位
s2++; //s2向后移动一位
}
//如果s2到达str2末尾,说明str2在str1中从cp位置被找到
if (*s2 == '\0')
{
return (char*)cp; //返回找到的位置的指针
}
cp++; //没找到则继续遍历str1
}
return NULL; //遍历完没找到则返回NULL
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "eg";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
printf("找不到\n");
else
printf("%s\n", ret);
return 0;
}
strtok
1.strtok的用法
strtok用于分割字符串,该函数的主要目的是将字符串按照指定的分隔符切分成多个子串,并返回指向这些子串的指针。
函数原型为:
char *strtok(char* str, const char* sep);
其中,参数的含义如下:
str:在第一次调用时,str是传入需要被切割字符串的首地址;在后续调用时,str应设置为NULL,以便strtok函数能够在之前的位置基础上继续查找下一个标记。
sep:这是一个字符串,它定义了用作分隔符的字符集合。字符串中的每个字符都会被当作一个分割符。
工作机制:
1.strtok在str字符串中查找由sep字符串定义的分隔符。当找到分隔符时,strtok会将其替换为\0字符,从而结束当前子串。
2.strtok返回指向当前找到的子串的指针。这个子串是从str开始,到当前找到的分隔符(现在已替换为\0)结束的部分。
3.在第一次调用之后,strtok会保存其在str中的位置,以便在后续调用时能够继续查找下一个子串。因此,在后续的调用中,需要将str参数设置为NULL。
4.如果字符串中不存在更多的分隔符,strtok将返回NULL指针。
需要注意的是,strtok函数会破坏被分解字符串的完整性。调用strtok后,原字符串str的内容会被修改,因为它会将分隔符替换为\0。因此,通常建议对原始字符串进行拷贝,并在拷贝的字符串上使用strtok,以避免修改原始数据。
2.strtok的使用
int main()
{
char arr1[] = "114514.2314.666";
char* sep = ".";
char* str = NULL;
for (str = strtok(arr1, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
return 0;
}
输出结果为:
114514
2314
666
我们来分析一下:
114514.2314.666
使用strtok函数后,它会在在找到分隔符的位置后,将那个位置的字符设置为\0来结束当前的标记
然后从上一次标记的地方开始找下一个标记,直至结束
简单来说,就是"strtok会把目标字符串中间的符号作为分隔符,将目标字符串分为几个子串"
strerror
1.strerror的用法
在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会讲对应的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
函数原型为:
char* strerror(int errnum);
2.strerror的使用
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%s\n", strerror(i));
}
return 0;
}
输出结果为:
No error(没有错误。这通常表示操作成功,没有发生任何错误)
Operation not permitted(操作不允许。这表明尝试进行的操作由于权限不足或其他限制而未能执行)
No such file or directory(没有这样的文件或目录。这通常意味着程序试图访问一个不存在的文件或目录)
No such process(没有这样的进程。这通常发生在尝试运行或管理一个不存在的进程时)
Interrupted function call(被中断的函数调用。这可能是由于某些外部因素(如用户中断)导致正在执行的函数被突然终止)
Input/output error(输入/输出错误。这通常发生在读取或写入文件或其他设备时,可能是由于设备故障、文件系统损坏或其他问题导致的)
No such device or address(没有这样的设备或地址。这通常表示程序试图访问一个不存在的设备或网络地址)
Arg list too long(参数列表过长。这通常发生在命令行参数超过系统限制时)
Exec format error(执行格式错误。这通常意味着尝试执行的程序或文件格式不正确或不被支持)
Bad file descriptor(错误的文件描述符。这通常表明程序尝试使用了一个无效或未正确初始化的文件描述符)
结束语
字符函数和字符串函数的内容就先讲到这里,下一篇文章我们将会学习内存操作函数
看到这里的友友们,感谢你们的支持,
求个点赞收藏加关注!!!
十分感谢!!!