1、strlen
size_t strlen(const char * str);strlen函数声明
strlen计算字符串的长度,寻找\0结束。
int len = strlen("abcedf");//字符串结尾自动带有\0,并且一个字符是一个字节
printf("%d\n", len);
char arr3[] = { 'a','b','c','d','e' };
int len1 = strlen(arr3);//随机值,因为一个字符后面没有\0,所以\0不知道什么时候出现
printf("%d\n", len1);
运行结果:
自己实现strlen功能:
//const修饰的*str,表示str指向的东西在这里面是不能修改的
int my_strlen(const char* str)
{
int count = 0;
//assert断言函数,如果括号内为true则继续执行,反之报错退出
assert(str != NULL);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
int len2 = my_strlen("abcedf");
printf("%d\n", len2);
return 0;
}
运行结果:
strlen返回值:
strlen函数原型是size_t类型的,size_t==unsigned int-无符号整型;
if ((strlen("abc") - strlen("abcdef")) > 0)
{
printf("haha\n");
}
else
{
printf("hehe\n");
}
运行结果:
3-6=-3,要当成无符号整型3
2、strcat、strnact
char* strcat(char* destination, const char* source);strcat函数声明-字符串追加
char* strncat(char* destination, const char* source, size_t count);strncat函数声明-字符串追加
注意事项:
- destination字符串足够大,能够包含source。
- destination必须是可以更改的;常量字符串是不行的。
- 包含’\0’
追加字符串strcat,但是不能用到自己给自己追加,追加字符串strncat,第三个参数是追加几个变量,注意:追加后不要超过原数组的长度。
char arr1[30] = "abc";
char arr2[] = "de";
strcat(arr1, arr2);
strncat(arr1, arr1,5);
printf("%s\n", arr1);
运行结果:
自己实现strcat函数:
char* my_strcat(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr521[30] = "abcdef";
char arr522[] = "xyz";
my_strcat(arr521, arr522);
printf("%s\n", arr521);
}
运行结果:
3、strcpy、strncpy
char* strcpy(char* destination, const char* source);strcpy函数声明-字符串复制
长度不受限制的字符串函数,遇到’\0’停止
注意事项:
- destination字符串足够大,能够包含source。
- destination必须是可以更改的;常量字符串是不行的。
- 包含’\0’
char arr411[] = "abcdef";
char arr412[] = "xyz";
strcpy(arr411, arr412);
printf("%s\n", arr411);
运行结果:
自己实现strcpy函数:
char* my_strcpy(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while(*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr421[] = "abcdef";
char arr422[] = "xyz";
my_strcpy(arr421, arr422);
printf("%s\n", arr421);
}
运行结果:
char* strncpy(char* destination, const char* source, size_t count);strncpy函数声明-字符串复制
长度受限制的字符串函数
char arr61[10] = "abcdefeee";
char arr62[] = "bit";
strncpy(arr61, arr62, 6);
printf("%s\n", arr61);
arr62只有三个字符,后面的三个应’\0’替代
运行结果:
4、strcmp、strncmp
int strcmp(const char* str1, const char* str2);//strcmp函数声明-字符串比较
首先比较第一个字符,相对再比较第二个,在vs里面大于返回1,小于返回-1,等于返回0;在linux-gcc编译器里面大于返回一个大于0的数,小于返回一个小于0的数,等于返回0;所以不能用返回值==1/-1来判断;最好是>0或者<0。
char* p1 = "abcdef";
char* p2 = "abcdefs";
int ret1 = strcmp(p1, p2);
printf("%d\n", ret1);
运行结果:
自己实现strcmp函数:
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 != NULL);
assert(str2 != NULL);
while (*str1 == *str2)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char* p1 = "abcdef";
char* p2 = "abcdefs";
int ret1 = my_strcmp(p1, p2);
printf("%d\n", ret1);
}
运行结果:
int strncmp(const char* str1, const char* str2, size_t count);strncmp函数声明-字符串比较
char* p3 = "abcdef";
char* p4 = "abcd";
int ret2 = strncmp(p3, p4, 4);
printf("%d\n", ret2);
运行结果:
5、strstr
char* strstr(const char* string, const char* str);strstr-字符串查找
返回第一次遇到字串的第一个字符的地址
char* p5 = "aaaeeffddd";
char* p6 = "ef";
char* ret3 = strstr(p5, p6);
if (ret3 == NULL)
{
printf("字串不存在");
}
else
{
printf("%s\n", ret3);
}
运行结果:
自己实现strstr函数:
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 != NULL);
assert(str2 != NULL);
char* st1;
char* st2 = (char*)str2;
while (*str1 != '\0')
{
st1 = (char*)str1;
while ((*str2 != '\0') && ( * str1 == *str2))
{
str1++;
str2++;
}
if (*str2 == '\0')
{
return st1;
}
str1 = st1;
str2 = st2;
str1++;
}
return NULL;
}
5、strtok
char* strtok(char* str, sonst char* sep);strtok-字符串分割
字符串分割会改变字符串的元素,所以最好复制一个字符串用来分割。
分割原理:找到分隔符后用’\0’代替,返回第一个字符,如果再分割此字符串只需要传入NULL指针,如果中间分割其他字符串,再分割此字符串需重新传入字符串,并且是从头开始查询。
char arr81[] = "sjsdhaj@sadjwa.dhwiao*dajiowa";//要分割的字符串
char* p7 = "@*.";//在这三种字符处分割:@和*和.
char buf11[1024] = { 0 };
char buf12[1024] = { 0 };
strcpy(buf11, arr81);
strcpy(buf12, arr81);
char* ret4 = strtok(buf11, p7);
printf("1%s\n", ret4);
ret4 = strtok(NULL, p7);
printf("2%s\n", ret4);
ret4 = strtok(buf12, p7);
printf("3%s\n", ret4);
ret4 = strtok(NULL, p7);
printf("4%s\n", ret4);
ret4 = strtok(buf11, p7);
printf("5%s\n", ret4);
ret4 = strtok(buf11, p7);
printf("6%s\n", ret4);
ret4 = strtok(NULL, p7);
printf("7%s\n", ret4);
- buf11:“sjsdhaj\0sadjwa.dhwiao*dajiowa”,返回sjsdhaj
- 继续buf11:“sjsdhaj\0sadjwa\0dhwiao*dajiowa”,返回sadjwa
- buf12:“sjsdhaj\0sadjwa.dhwiao*dajiowa”,返回sjsdhaj
- 继续buf12:“sjsdhaj\0sadjwa\0dhwiao*dajiowa”,返回sadjwa
- buf11:“sjsdhaj\0sadjwa\0dhwiao\0dajiowa”,返回sjsdhaj,此时改掉的是buf中的*,“sjsdhaj\0sadjwa\0dhwiao*dajiowa”->“sjsdhaj\0sadjwa\0dhwiao\0dajiowa”,并返回头上的s,打印遇到第一个\0停止打印。
- 此时没有可改的,返回头上的s,sjsdhaj\0,输出结束
- 继续buf,但是没有可改的,返回NULL
运行结果:
6、字符函数
- islower判断是不是小写字符
- iscntrl-任何控制字符
- isspace-空白字符:空格,换页\f,换行\n,回车\r,制表符\t,垂直制表符\v
- isdigit-十进制数组0-9
- isxdigit-十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
- isupper-大写字母A-Z
- isalpha-字母a-z或A-Z
- isalnum-字母或者数字,0-9或a-z或A-Z
- ispunct-标点符号任何不属于数字和字母的图形字符(可打印)
- isgraph-任何图形字符
- isprint-任何可打印的字符,包括图形字符和空白字符
- tolower-转小写字符
- toupper-转大写字符
//如果是一个小写字母,则该函数返回非零值(true),否则返回 0(false)。
char ch11 = 'w';
char ch12 = 'W';
int ret = islower(ch11);
printf("%d\n", ret);
printf("%d\n", islower(ch12));
运行结果:
把大写字母转换成小写:
char ch21 = tolower('Q');
putchar(ch21);
printf("\n");
char ch22[] = "I Am A Student";
int i = 0;
while (ch22[i] != '\0')
{
if (isupper(ch22[i]))
{
ch22[i] = tolower(ch22[i]);
}
i++;
}
printf("%s\n", ch22);
运行结果:
7、内存函数mem…
memcpy
void* memcpy(void* dest, const void* source, size_t num);num单位字节
从存储区 source 复制 num 个字节到存储区 dest。
memcpy实例以及自己实现memcpy函数:
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
return ret;
}
int main()
{
int arr11[] = { 1,2,3,4,5 };
int arr12[5] = { 0 };
int arr13[5] = { 0 };
memcpy(arr12, arr11, sizeof(arr11));
my_memcpy(arr13, arr11, sizeof(arr11));
for (int i = 0; i < 5; i++)
{
printf("%d ", arr12[i]);
}printf("\n");
for (int i = 0; i < 5; i++)
{
printf("%d ", arr13[i]);
}printf("\n");
}
运行结果:
memmove
void* memmove(void* dest, const void* src, size_t count);memmove处理内存重叠的情况
比如:arr[10]={1,2,3,4,5,6,7,8,9,10};把arr中3,4,5,6,7复制到1,2,3,4,5,输出为{3,4,5,6,7,6,7,8,9,10}。当前编译器memcpy也能实现memmove的效果,但是最好还是使用memmove。memcpy适合拷贝内存不重复的数据
void* my_memmove(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest != NULL);
assert(src != NULL);
if (dest < src)
{
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr21[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr21, arr21 + 3, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr21[i]);
}printf("\n");
int arr22[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr22, arr22 + 2, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr22[i]);
}printf("\n");
}
运行结果:
memcmp
int memcmp(const void* str1, const void* str2, size_t num);比较内存
int arr31[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr32[10] = { 1,2,3,4,5,6,7,8,9,1 };
int ret1 = memcmp(arr31, arr32, 37);
printf("%d\n", ret1);
运行结果:
memset
void* memset(void* dest, int c, size_t count);内存设置函数
注意:容易用错,设置的是字节,而不是元素
char arr41[10] = "";
memset(arr41, '*', 10);
int arr42[10] = { 0 };
memset(arr42, 1, 10);//出错