本文接着学习字符和字符串函数,并用代码模拟实现。主要学习内容包括:
4、 字符串查找
5、错误信息报告
6、字符操作函数
7、内存操作函数
char * strstr ( const char *str1, const char * str2);
int main()
{
char a1[] = "abbbcdef";
char a2[] = "bbc";
char* ret = strstr(a1, a2);
if (NULL==ret)
{
printf("找不到子字串\n");
}
else
{
printf("%s\n", ret);
}
}
char* my_strstr(const char* p1, const char* p2)
{
assert(p1&&p2);
const char* s1 = p1;//赋予指针初始位置
const char* s2 = p2;//赋予指针初始位置
const char* cur = p1;//记录字符串当前指针位置
while (*cur)
{
s1 = cur;
s2 = p2;//移到初始位置
while (*s1 && *s2 && (*s1==*s2))
{
s1++;//相等时,指针后移,直到两个不相等或者一方为0
s2++;
}
if (*s2=='\0')
{
return (char*)cur;
}
cur++;//不相等,当前指针加1
}
//跳出,就是字符串1移动到末尾
return NULL;
}
int main()
{
char a1[] = "abbbcdef";
char a2[] = "bbc";
char* ret = my_strstr(a1, a2);
if (NULL==ret)
{
printf("找不到子字串\n");
}
else
{
printf("%s\n", ret);
}
}
结果见下图:
char * strtok ( char * str, const char * sep );
int main()
{
char a[] = "[email protected]@hello world";
char a2[50] = { 0 };
strcpy(a2, a);
printf("%s\n", a2);
const char* sep = "@. ";//三个分隔符
printf("%s\n", strtok(a2, sep));//learnC
printf("%s\n", strtok(NULL, sep));//day
printf("%s\n", strtok(NULL, sep));//day
return 0;
}
int main()
{
char a[] = "[email protected]@hello world";
char a2[50] = { 0 };
strcpy(a2, a);
printf("%s\n", a2);
const char* sep = "@. ";//三个分隔符
char* str = NULL;
//用循环来查找多有的分隔符隔开的字符串,不为空,就找下一个,直到结束
for (str =strtok(a2,sep); str != NULL; str=strtok(NULL,sep))
{
printf("%s\n", str);
}
return 0;
}
结果见下图:
char * strerror ( int errnum );
int main()
{
int* p = (int*)malloc(INT_MAX);//在堆区申请内存
if (p==NULL)
{
printf("%s\n", strerror(errno));//打印出错信息
return 1;
}
return 0;
}
结果见下图:
函数 | 如果他的参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’ |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A~ F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a-z或A~Z |
isalnum | 字母或者数字,a-z, A-Z, 0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
void * memcpy ( void * destination, const void * source, size_t num );
int main()
{
int a1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int a2[5] = { 0 };
memcpy(a2, a1, 20);
int sz = sizeof(a1) / sizeof(a1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d\n", a2[i]);
}
return 0;
}
//模拟实现
void* my_memcpy(void* dest, const void* src, size_t cnt)
{
assert(dest&&src);
void* ret = dest;//接收任何类型的数据
while (cnt--)
{
*(char*)dest = *(char*)src;//按字节顺序来交换
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int a1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int a2[5] = { 0 };
my_memcpy(a2, a1, 20);
int sz = sizeof(a1) / sizeof(a1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d\n", a2[i]);
}
return 0;
}
结果见下图:
void * memmove ( void * destination, const void * source, size_t num );
int main()
{
int a1[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(a1+2, a1, 20);
int sz = sizeof(a1) / sizeof(a1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d\n", a1[i]);
}
return 0;
}
//模拟实现
void* my_memmove(void* dest, const void* src, size_t cnt)
{
assert(dest&&src);
void* ret = dest;
if (dest<src)
{//从左往右拷贝
while (cnt--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{//从右往左
while (cnt--)
{
*((char*)dest + cnt) = *((char*)src + cnt);
}
}
return ret;
}
int main()
{
int a1[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(a1+2, a1, 20);
int sz = sizeof(a1) / sizeof(a1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d\n", a1[i]);
}
return 0;
}
结果见下图:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
int main()
{
int a1[] = { 1,2,3,4,5 };
int a2[] = { 1,2,3,4,0x11223305 };
int ret = memcmp(a1, a2, 18);
printf("%d\n", ret);
return 0;
}
结果见下图:
void *memset( void *dest, int c, size_t count );
int main()
{
int a[] = { 0x11111111,0x22222222,3,4,5 };
memset(a, 6, 20);
return 0;
}
结果见下图:
字符串库函数的学习基本结束了。学完有点混乱,这块内容就当字典,需要的时候再来查。
感觉单独学字符串库函数有点枯燥,这个要后面刷题才能深刻的理解并掌握这些函数的用法。
库函数实现学习的眼花缭乱,还有一点内容没写完全,等以后再添加内容。
下一篇更新结构体相关的内容。