书山有路勤为径,学海无涯苦作舟。 创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~
上节回顾:【C语言基础】:字符函数和字符串函数
函数原型:
char * strncpy ( char * destination, const char * source, size_t num );
strncpy与strcpy的区别:
从函数的参数来看,strncpy和strcpy前面几个参数都是char * destination, const char * source,也就是将source的内容拷贝到destination里面去,但是strncpy函数多了一个参数size_t num,也就是对拷贝的内容有了数量上的限制,而strcpy则对拷贝的内容没有数量上的限制。
从字符串中复制字符 将源的第一个num字符复制到目标。如果在复制num个字符之前找到源C字符串的结尾(用空字符表示),则目的地将用零填充,直到向其写入总数为num个字符。
如果source大于num,则不会在destination的末尾隐式添加空字符。因此,在这种情况下,destination不应被视为以空结束的C字符串(这样读取会溢出)。
【strncpy的使用】
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[20] = { 0 };
strncpy(arr2, arr1, 3);
printf("%s\n", arr2);
return 0;
}
使用strncpy的注意事项
:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[20] = "xxxxxxxxxxxx";
strncpy(arr2, arr1, 3);
printf("%s\n", arr2);
return 0;
}
在调试的时候可以看到,strncpy并没有将 \0给拷贝过去,另外我们运行之后可以看到打印之后把abc之后的x也打印出来了,如果 \0也拷过来的话,那么用\s打印的话遇到 \0就会停止打印。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[20] = "xxxxxxxxxxxxxxx";
strncpy(arr2, arr1, 10);
printf("%s\n", arr2);
return 0;
}
调试之后可以看到,但原字符串数量不够时,会用 \0来补充,不够10位就用 \0来不够10位。用/s打印到 \0就会停止,后面即使有内容也不会打印。
函数原型:
char * strncat ( char * destination, const char * source, size_t num );
从字符串中添加字符 将源的第一个num字符附加到目标,加上一个结束的空字符。 如果source中的C字符串的长度小于num,则只复制结束空字符之前的内容。
和上面的类似strncat和strcat的区别也是在于strncat函数多了一个size_t num的参数。
【strncat的使用】
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[20] = "xx";
strncat(arr2, arr1, 3);
printf("%s\n", arr2);
return 0;
}
注意事项
:
可以看到,strncat会将 \0也追加进来。
调试之后可以看到,如果追加的数量大于原字符数量,那么将 \0追加完追后就不会继续追加了。
函数原型:
int strncmp ( const char * str1, const char * str2, size_t num );
比较两个字符串的字符 比较C字符串str1和C字符串str2的最多num个字符。 这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续执行后面的对,直到字符不相同,直到达到终止的空字符,或者直到两个字符串中的num字符匹配,以先发生的为准。
【strncmp函数的使用】
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abqdefgui";
int ret = strncmp(arr1, arr2, 3);
printf("%d\n", ret);
return 0;
}
第三个参数就是最多比较的次数,如果在这之前就比较出了结果,那么后面的也将不会再比较。
函数原型:
char * strstr ( const char * str1, const char * str2 );
查找子字符串 返回指向str1中str2第一次出现的指针,如果str2不是str1的一部分,则返回空指针。 匹配过程不包括结束的空字符,但它到此为止。 字符串的比较匹配不包含 \0 字符,以 \0 作为结束标志
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "this is an apple\n";
const char arr2[] = "is";
char arr3[] = "pa";
char* p = strstr(arr1, arr2);
char* pa = strstr(arr1, arr3);
printf("%s\n", p);
printf("%s\n", pa);
return 0;
}
返回arr2在arr1中第一次出现的指针,如果没有匹配到,就返回空指针。
模拟实现的函数参数类型以及返回类型:从原函数可以看出,参数是接收的arr1和arr2数组首元素的地址,也就是char* 类型的,我们只是用来进行比较匹配,为了防止被修改,参数前面都要加const进行修改。原函数的返回类型是arr2在arr1中第一次出现的指针,所以返回类型就是 char*。
char* my_strstr(const char* str1, const char* str2)
{
}
模拟分析:
第一种情况: str1:abcdef\0 str2:bcd\0
这里arr1从b开始匹配一次就能匹配成功,当str2的指针指向\0时,就说明已经匹配到了,但需要有一个指针记录从哪里开始匹配的。
第二种情况: str1:abbbcdef\0 str2:bbc\0
这种情况就比较复杂,当str1中的第一个b和str2中的b匹配时,str2中的第一个和第二个都能匹配上,当第三个str2是c,而str1却是b,这时候又要回去重新进行匹配,但str2中的指针已经指向c了,没办法回去,所以这里不仅需要一个指针记录开始匹配的位置,还需要一个指针指向str2的开始位置,方便那个指针能指向回来。
第三种情况: str1:abcdef\0 str2:bbq\0
这种情况最简单,就是匹配不到。
#include<stdio.h>
char* my_strstr(const char* str1, const char* 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 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0') // 匹配完成
{
return (char*)cur;
}
cur++;
}
return NULL; // 没找到
}
int main()
{
char arr1[] = "this is an apple\n";
const char arr2[] = "is";
char arr3[] = "pa";
char* p = my_strstr(arr1, arr2);
char* pa = my_strstr(arr1, arr3);
printf("%s\n", p);
printf("%s\n", pa);
return 0;
}
函数原型:
char * strtok ( char * str, const char * sep );
【strtok函数的使用】
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "zhangxu@qq.com";
char arr2[30] = { 0 };
strcpy(arr2, arr1);
const char* sep = "@.";
char* ret = NULL;
for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep))
{
printf("%s\n", ret);
}
// ret = strtok(arr2, sep);
// printf("%s\n", ret);
// ret = strtok(NULL, sep);
// printf("%s\n", ret);
// ret = strtok(NULL, sep);
// printf("%s\n", ret);
return 0;
}
函数原型:
char * strerror ( int errnum );
strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。 在不同的系统和C语⾔标准库的实现中都规定了一些错误码,⼀般是放在 errno.h 这个头⽂件中说明 的,C语言程序启动的时候就会使用一个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应 的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
【strerror函数的使用】
#include<stdio.h>
#include<string.h>
int main()
{
for (int i = 0; i <= 10; i++)
{
printf("%d:\t%s\n", i, strerror(i));
}
return 0;
}
举例:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
FILE* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
printf("Error opening file unexist.ent: %s\n", strerror(errno));
return 0;
}