strlen
- 测量长度: size_t strlen ( const char * str );
字符串已以’\0’ 作为结束标志;strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ );参数指向的字符串必须要以 ‘\0’ 结束。注意函数的返回值为size_t,为无符号型
#include<stdio.h>
int main()
{
const char *str = "abc\0def";
printf("%d\n", strlen(str)); //3
return 0;
}
- 模拟实现
int Mystrlen(const char * str) //计数
{
int count = 0;
while (*str)
{ count++;
str++;
}
return count;
}
int Mystrlen(char *s) //指针-指针的方式
{
char *p = s;
while (*p != ‘\0’)
p++;
return p - s;
}
int Mystrlen(const char * str) //递归实现
{
assert(str);
if (*str == '\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
strcpy
- 拷贝: char * strcpy (char * destination, const char * source);
源字符串必须以 ‘\0’ 结束;将源字符串中的 ‘\0’ 拷贝到目标空间;目标空间必须足够大,以确保能存放源字符串;目标空间必须可变。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "abc\0def";
const char str2[] = "def\0abc";
strcpy(str1, str2);
printf("%s\n", str1); //输出def
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
char *Mystrcpy(char *dest, const char*src) //函数源字符串必须加const
{
char *ret = dest;
assert(dest);
assert(src);
while ((*dest++ = *src++));
return ret;
}
int main()
{
char str1[]="def";
char str2[]="abc";
printf("%s\n", Mystrcpy(str1, str2)); //输出abc
return 0;
}
strcat
- 连接: char * strcat(char * destination, const char * source);
目标空间必须足够大,能容纳下源字符串;目标空间必须可修改。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "abc\0def";
const char str2[] = "def\0abc";
strcat(str1, str2); //以'\0'截止
printf("%s\n", str1); //输出abcdef
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
char *Mystrcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest);
assert(src);
while (*dest)
dest++;
while ((*dest++ = *src++));
return ret;
}
int main()
{
char str1[] = "abcd\0def";
const char str2[] = "def\0abc";
Mystrcat(str1, str2); //以'\0'截止
printf("%s\n", str1); //输出abcddef
return 0;
}
strcmp
- 比较大小: int strcmp(const char* str1,const char* str2);
第一个字符串大于第二个字符串,返回大于0的数字;第一个字符串小于第二个字符串,返回小于0的数字;相等则返回0。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "abcd";
char str2[] = "def";
int ret = strcmp(str1, str2);
if (ret > 0)
printf("第一个大\n");
else if (ret < 0)
printf("第二个大\n");
else
printf("相等\n");
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
int MyStrcmp(const char*str1, const char*str2)
{
assert(str1);
assert(str2);
while (*str1 == *str2)
{
if (*str1 == '\0'); //不能放在最后,两个字符串均为'\0'时不再需要比较
{
return 0;
}
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char str1[] = "abcd";
char str2[] = "def";
int ret = MyStrcmp(str1, str2);
if (ret > 0)
printf("第一个大\n");
else if (ret < 0)
printf("第二个大\n");
else
printf("相等\n");
return 0;
}
strncpy
- 拷贝(字符):char* strncpy(char* destination,constchar* source,size_t num);
拷贝指定个字符从源字符串到目标空间;如果源字符串的长度小于num,则拷贝完源字符之后,在目标的后边追加0,直到指定个;拷贝最后一个字符不追加’\0’
#include<stdio.h>
#include<string.h>
int main()
{
char str[20] = "asdfasdfsadfasd";
strncpy(str,"Hello!",5);
printf("%s\n", str); //Hellosdfsadfasd
getchar();
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
char *MyStrncpy(char * str3, const char * str4, int count)
{
assert(str3);
assert(str4);
while (count && (*str3++ = *str4++))
count--;
if (count)
while (--count)
*str3++ = '\0';
return (str3);
}
int main()
{
char str1[20] = "asdfasdfsadfasd";
MyStrncpy(str1, "Hello!", 5); //Hellosdfsadfasd
printf("%s\n", str1);
return 0;
}
strncat
- 连接(字符):char* strncat(char* destination,const char* source,size_t num);
将指定个字符从源字符串连接到目标空间;如果源字符串的长度小于num,不追加0;连接最后一个字符追加’\0’
#include<stdio.h>
#include<string.h>
int main()
{
char str[20] = "asnlgk";
strncat(str, "Hello!", 5); //asnlgkHello
printf("%s\n", str);
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
char* MyStrncat(char* dest, const char* src, int n)
{
assert(dest);
assert(src);
while (*dest)
++dest;
while (n)
{
if (*src == '\0')
break;
*dest++ = *src++;
--n;
}
*dest = '\0'; //在结果后面添加'\0',而不是用'\0'填充目标剩余空间
return dest;
}
int main()
{
char str[20] = "asnlgk";
MyStrncat(str, "Hello!", 5); //asnlgkHello
printf("%s\n", str);
return 0;
}
strncmp
- 比较大小:int strncmp(const char* str1,const char* str2,size_t num);
第一个字符串大于第二个字符串,返回大于0的数字;第一个字符串小于第二个字符串,返回小于0的数字;相等则返回0;比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
#include<stdio.h>
#include<string.h>
int main()
{
int ret1 = strncmp("acc", "abcd", 4);
int ret2 = strncmp("abc", "abcd", 3);
int ret3 = strncmp("abc", "abcd", 4);
printf("%d\n", ret1); //1
printf("%d\n", ret2); //0
printf("%d\n", ret3); //-1
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
int MyStrncmp(char* str1, char* str2, int a)
{
int i = 0;
assert(str1);
assert(str2);
for (i = 0; i < a; i++)
{
if (*(str1 + i) > *(str2 + i))
return 1;
else if (*(str1 + i) == *(str2 + i))
continue;
else if (*(str1 + i) < *(str2 + i))
return -1;
}
if (i == a)
return 0;
}
int main()
{
int ret1 = MyStrncmp("acc", "abcd", 4);
int ret2 = MyStrncmp("abc", "abcd", 3);
int ret3 = MyStrncmp("abc", "abcd", 4);
printf("%d\n", ret1); //1
printf("%d\n", ret2); //0
printf("%d\n", ret3); //-1
return 0;
}
strstr
- 在字符串中查找子字符串:char* strstr(const char* ,const char* );
在第一个字符串中查询含有第二个子字符串的内容
#include<stdio.h>
#include<string.h>
int main()
{
char*p1 = "abc";
char*p2 = "thaabcaedef";
char*ret = strstr(p2, p1);
printf("%s\n", ret); //abcaedef
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
char* MyStrstr(const char*str1, const char*str2)
{
const char *s1 = str1;
const char *s2 = str2;
const char *cp = str1;
assert(str1);
assert(str2);
if (!*str2) //若查找空字符串,直接返回子字符串
return str1;
while (*cp)
{
s1 = cp; //将跳过字符的指针重新赋值,重新查找
s2 = str2; //将指针重新指向子字符串
while (*s1 && *s2 && !(*s1 - *s2)) //当两个字符串均未结束且找到相同字符,继续查找
{
s1++;
s2++;
}
if (*s2 == '\0') //当子字符串结束时停止循环
return cp;
cp++; //子字符串与源字符串有部分不完全相同时,跳过此时指向的第一个字符
}
return NULL;
}
int main()
{
char*p1 = "abc";
char*p2 = "thaabcaedef";
char*ret = MyStrstr(p2, p1);
printf("%s\n", ret); //abcaedef
return 0;
}
strtok
char* strtok(char* str,const char* sep);
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。strtok函
数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符
串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)strtok函数的第一个参数不为NULL,
函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。strtok函数的第一个参数为NULL,函数将在同
一个字符串中被保存的位置开始,查找下一个标记。
#include<stdio.h>
#include<string.h>
int main()
{
char *str = "Seincfe@yeah.net";
char arr[20] = { 0 };
char *ret = NULL;
char *p = "@.";
strcpy(arr, str);
for (ret = strtok(arr, p); ret != NULL; ret = strtok(NULL, p))
//仅在第一次传参的时候传入arr的地址吗,如果使用while将会使每次传入的参数都是arr的地址
//strotk函数中有延长局部变量生存时间,自动记录节点
printf("%s\n", ret);
/*char arr[] = "Seincfe@yeah. net";
printf("%s\n", strtok(arr, "@."));
printf("%s\n", strtok(NULL, "@."));
printf("%s\n", strtok(NULL, "@."));*/ //过于麻烦所以不考虑这种方法
return 0;
}
strerro
char* strerror(int errnum); 返回错误码,所对应的错误信息;检测错误。
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
FILE* pF = fopen("unexist.ent", "r");
if (pF == NULL)
printf("Erroropeningfileunexist.ent:%s\n", strerror(errno)); //errno:Lasterrornumber
fclose(pF);
return 0;
}
memcpy
- 内存拷贝:void* memcpy(void* destination,constvoid* source,size_t num);
遇到’\0’的时候并不会停下来;函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。(库函数中的memcpy可以实现memmove的功能,我们这里不实现memmove)
#include<stdio.h>
#include<string.h>
int main()
{
int str1[] = { 1,2,3,4,5,6 };
int str2[20] = { 0 };
memcpy(str2, str1, 24);
printf("%d\n", str2[0]);
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
void* MyMemcpy(void* dest, const void* src, int count)
{
void *ret = dest;
assert(dest);
assert(src);
while (count--)
{
*(char*)dest = *(char*)src; //按字节拷贝
((char*)dest)++;
((char*)src)++;
}
return ret;
}
int main()
{
int str1[] = { 1,2,3,4,5,6 };
int str2[20] = { 0 };
MyMemcpy(str2, str1, 24);
printf("%d\n", str2[0]);
return 0;
}
memmove
- 内存拷贝:void* memmove(void* destination,const void* source,size_t num);
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的;如果源空间和目标空间出现重叠,就得使用memmove函数处理。
#include<stdio.h>
#include<string.h>
int main()
{
int i = 0;
int str1[] = { 1,2,3,4,5,6 };
int str2[20] = { 20,19,18,17,16,15,14,13,12,11,10 };
memmove(str2 + 5, str1, 24);
for (i = 0; i < 20; i++)
printf("%-3d", str2[i]);
return 0;
}
- 模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>
void* MyMemmove(void* dest, const void*src, int count)
{
void *ret = dest;
assert(src && dest);
if (dest < src) //从后往前拷贝
{
while (count--)
{
*(char*)dest = *(char*)src; //按字节拷贝
((char*)dest)++;
((char*)src)++;
}
}
else //从前往后拷贝
while (count--)
*((char *)dest + count) = *((char*)src + count);
return ret;
}
int main()
{
int i = 0;
int str1[] = { 1,2,3,4,5,6 };
int str2[20] = { 20,19,18,17,16,15,14,13,12,11,10 };
MyMemmove(str2 + 5, str1, 24);
for (i = 0; i < 20; i++)
printf("%-3d", str2[i]);
return 0;
}
memcmp
内存比较:int memcmp(const void* ptr1,const void* ptr2,size_t num);
第一个字符串大于第二个字符串,返回大于0的数字;第一个字符串小于第二个字符串,返回小于0的数字,相等则返回0
#include<stdio.h>
#include<string.h>
int main()
{
char str1[] = "DWgAOtP12df0";
char str2[] = "DWGAOTP12DF0";
int n = memcmp(str1, str2, sizeof(str1)); //按字节比大小,可选取字节长度
printf("%d\n", n);
return 0;
}
memset
初始化函数:void *memset(void *s, int ch, size_t n);
将已开辟内存空间s的首n个字节的值设为值ch。
#include <stdio.h>
#include <string.h>
int main() {
char s[] = "Golden Global View";
memset(s, 'G', 6);
printf("%s", s);
return 0;
}
- memset()函数常用于内存空间初始化,将某一块内存中的内容全部设置为指定的值,通常为新申请的内存做初始化工作;
- memset()的深刻内涵:用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化
例如:memset(a,’\0’,sizeof(a)); - memset可以方便的清空一个结构类型的变量或数组;它是对较大的结构体或数组进行清零操作的一种最快方法。
附: