目录
三、其他字符串函数
3.1 strstr——判断是否为子串
3.2 strtok——切割字符串
3.3 strerror——返回错误码所对应错误信息
四、字符操作函数
4.1 字符分类函数
4.2 字符转换函数
五、内存操作函数
5.1 memcpy
5.2 memmove
5.3 memcmp
5.4 memset
char* strstr(const char *str1, const char *str2);
如果str2是str1的子串的话则返回str2在str1中首次出现的地址。如果str2在str1中没出现则返回空指针NULL。
例如:
int main()
{
char arr1[20] = "abcdefabcdef";
char arr2[] = "cdef";
char* ret = strstr(arr1, arr2);
if(NULL == ret)
printf("找不到子串\n");
else
printf("%s\n", ret);
return 0;
}
输出为cdefabcdef。
【strstr的模拟实现】:
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
char* s1 = str1;
char* s2 = str2;
char* cur = str1;
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur;
}
cur++;
}
return NULL; //找不到
}
int main()
{
char arr1[20] = "abcqabcd";
char arr2[] = "bcd";
char* ret = my_strstr(arr1, arr2);
if (NULL == ret)
printf("找不到子串\n");
else
printf("%s\n", ret);
return 0;
}
这是一个很奇怪的函数,希望大家能仔细阅读以下讲解~
char* strtok(char* str, const char* sep);
str是一个字符串,sep是一个由分隔符组成的字符串,str是被分割的。
例如:
int main()
{
char arr[] = "[email protected]";
const char* sep = "@.";
strtok(arr, sep);
return 0;
}
strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。即上面那个代码使用了一次strtok会把arr变成"abcdefg\0yeah.net",它把分隔符的地方变成\0,返回a的地址。
注意:strtok会改变被操作的字符串,所以在使用时切分的字符串一般都是临时拷贝的内容,并且可修改。如:
int main()
{
char arr[] = "[email protected]";
char buf[30] = {0};
strcpy(buf, arr);
const char* sep = "@.";
strtok(buf, sep);
return 0;
}
strtok第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。若第一个参数为空的话,则会从保存好的位置继续往后找。例如:
int main()
{
char arr[] = "[email protected]";
char buf[30] = {0};
strcpy(buf, arr);
const char* sep = "@.";
printf("%s\n", strtok(buf, sep));//只找第一个标记
printf("%s\n", strtok(NULL, sep));//是从保存好的位置开始继续往后找
printf("%s\n", strtok(NULL, sep));//是从保存好的位置开始继续往后找
return 0;
}
输出结果为:
abcdefg
yeah
net
可以用for循环简化为:
int main()
{
char arr[] = "[email protected]";
char buf[30] = {0};
strcpy(buf, arr);
const char* sep = "@.";
char* str = NULL;
for(str=strtok(buf, sep); str!=NULL; str=strtok(NULL,sep))
{
printf("%s\n",str);
}
return 0;
}
例如:
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
}
这四种错误会分别输出:
No error Operation not peimitted No such file or directory No such process
每种错误码对应一种错误信息。
又例如:
#include
#include
#include
#include //用到了INT_MAX
#include
int main()
{
int* p = (int*)malloc(INT_MAX);
if(p == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
return 0;
}
遇到错误时会把错误码放到errno里去,所以这里用strerror(errno)即可输出错误信息:Not enough space
(补充:perror更方便,若将上面的printf那行换成perror("malloc");则可直接输出malloc: Not enough space)
再此列举一些:
iscntrl——判断是否为任何控制字符;isspace——判断是否为空白字符;
isdigit——判断是否为数字字符; isxdigit——判断是否为十六进制数字字符;
islower——判断是否为小写字母; isupper——判断是否为大写字母;
isalpha——判断是否为字母;isalnum——判断是否为字母或数字;
ispunct——判断是否为标点符号; isgraph——判断是否为任何图形字符;
isprint——判断是否为可打印字符;
比如:
是数字返回非0,不是数字返回0。
其他字符分类函数也类似,可以自行查阅使用~
int tolower (int c); //小写转大写
int toupper (int c); //大写转小写
int main()
{
char ch = 'a';
putchar(toupper(ch));
return 0;
}
这样可以输出A。
strcpy只拷贝字符串,而memcpy是通用的。
int main()
{
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
int arr2[5] = {0};
//此时strcpy()是不行的
memcpy(arr2, arr1, 20);
return 0;
}
void*更有通用性。
【memcpy的模拟实现】:
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
while (count)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
count--;
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[5] = { 0 };
//此时strcpy()是不行的
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
但这种写法也有一定缺陷,比如my_memcpy(arr1+2, arr1, 20);就会有问题(其实用库函数里的memcpy不会有问题但是不好)。因为这设计重叠内存拷贝。那么我们就可以使用下一个函数:memmove。
看上去好像没什么区别~但memmove可以完成重叠内存的拷贝!
【memmove的模拟实现】:
void* my_memmove(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
if (dest < src)
{
//前->后
while (count--)
{
*(char*)dest = *(char*)(src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后->前
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[5] = { 0 };
//此时strcpy()是不行的
my_memmove(arr1+2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {1,2,3,4,0x11223305};
int ret = memcmp(arr1,arr2,17);
printf("%d\n", ret);
return 0;
}
输出为0(因为是小端存储)。若改为memcpy(arr1,arr2,18);则输出负数。
以字节为单位的内存设置。
int main()
{
int arr[] = {1,2,3,4,5};
memset(arr,0,20);
return 0;
}
这个操作可以把arr内值全变为0。(每个字节都是00)
好啦~这次关于“C语言常见库函数详解——【字符/字符串函数及内存操作函数】”的介绍就到此为止啦!感谢大家的阅读~希望能对大家有所帮助!欢迎大家一起交流ovo