提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的
字符串通常放在 常量字符串 中或者 字符数组中
字符串常量 适用于那些对它不做修改的字符串函数
char类型只有一个字节哦!!!!!,也只移动一个字节哦!!!!!
一、字符串长度(strlen)
1.使用介绍
- size_t strlen(const char* str)
- 返回的是在字符串中 \0 前面出现的字符个数
- 参数指向的字符串必须以 \0 结束
- 注意函数的返回值为size_t,是无符号类型的
int main()
{
if(strlen("abc") - strlen("abcdef") > 0)
3 - 6 = -3 由于strlen返回的是无符号数
而 -3在内存中的补码为无符号数,超级大
printf("hehe");
else
printf("haha");
return 0;
}
2.模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)
{
int count = 0;
assert(str);
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("len = %d\n", len);
return 0;
}
二、长度不受限制的字符串函数
1.strcpy(字符串拷贝)
使用介绍
- char* strcpy(char* dest,const char* src)
- 原字符串必须以 \0 结尾
- 会将原字符中的 \0 拷贝到目标空间
- 目标空间必须足够大,以确保能够放原字符串
- 目标空间必须可变
模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
while (*dest++ = *src++);
return ret;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "bit";
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
int main()
{
char arr1[30] = "hello";;
cahr arr2[] = "world";
strcat(arr1,arr2);
printf("%s\n",arr1);
return 0;
}
2.strcat(字符串追加)
使用介绍
- char* strcat(char* dest,const char* src)
- 原字符串必须以 \0 结尾
- 原字符串拷贝过去时,是从目标字符串的第一个 \0 开始覆盖,直到原字符串的 \0
- 目标空间必须足够大,能容纳下原字符串的内容
- 目标空间必须可修改,不可修改无法覆盖
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
assert(dest);
assert(src);
char* ret = dest;
//找到字符串中的 \0
while (*dest)
{
dest++;
}
//追加
while (*dest++ = *src++);
return ret;
}
int main()
{
char arr1[30] = "abcdefg";
char arr2[] = "bit";
my_strcat(arr1, arr2);
printf("%s", arr1);
return 0;
}
3.strcmp(比较两个字符串是否相同)
使用介绍
- int strcmp(const char* str1,const char* str2)
- 比较的不是长度,而是ASCII码值,比较到不相同或者 \0 就会结束并返回值
- str1>str2 return > 0,str2>str1 retrun <0,str1 == str2 return 0
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
char arr1[] = "abcdefgaadada";
char arr2[] = "abcdefg";
int ret = my_strcmp(arr1, arr2);
if (ret == 0)
printf("相同");
else
printf("不相同");
return 0;
}
三、长度受限制的字符串函数
1.strncpy(字符串拷贝)
使用介绍
- char* strcnpy(char* dest,const char* src,size_t num)
- 拷贝num个字符从原字符到目标空间
- 如果原字符串长度小于num,则拷贝完原字符串后,在目标空间后面追加 \0,直到num个
- 目标空间必须足够大,能容纳下原字符
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strncpy(char* dest, const char* src,int k)
{
char* ret = dest;
while (k--)
{
*dest++ = *src++;
}
return ret;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "bit";
my_strncpy(arr1, arr2, 5);
printf("%s", arr1);
return 0;
}
2.strncat(字符串追加)
使用介绍
- char* strncat(char* dest,const char* src,size_t num)
- 从目标空间一个 \0 开始追加num个字符,比num多或少都只添加一个 \0
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strncat(char* dest, const char* src, int k)
{
char* ret = dest;
while (*dest)
{
dest++;
}
while (k-- && (*dest++ = *src++));
return ret;
}
int main()
{
char arr1[30] = "abcdefg";
char arr2[] = "bit\0abv";
my_strncat(arr1, arr2, 5);
printf("%s", arr1);
return 0;
}
3.strncmp(比较两个字符串是否相等)
使用介绍
- int strncmp(const char* str1,const char* str2,size_t num)
- 比较到出现一个字符不一样,或者一个字符串结束,或者num个字符全部比较完
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strncmp(const char* str1, const char* str2, int k)
{
while (k-- && (*str1++ == *str2++))
{
;
}
k++;
if (k == 0)
{
return 0;
}
else if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "abcdefe";
int ret = my_strncmp(arr1, arr2, 7);
if (ret == 0)
printf("相同");
else
printf("不相同");
return 0;
}
四、字符串查找
1.strstr(在字符串中查找字符串)
使用说明
- char* strstr(const char*,const char*)
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strstr(const char* p1, const char* p2)
{
char* s1 = NULL;
char* s2 = NULL;
char* cur = p1;
if (p2 == '\0')
return p1;
while (cur)
{
//重新设置出生点
s1 = cur;
s2 = p2;
while (*s1 && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
return cur;
cur++;
}
return 0;
}
int main()
{
char arr1[] = "abbbccddd";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
printf("无字符串");
else
printf("%s", ret);
return 0;
}
2.strtok(筛选特殊符号)
使用介绍
- char* strtok(const char*,const char* sep)
- sep参数是个字符串,里面定义了用作分隔符的字符集合
- 第一个参数指定一个字符粗换,它包含了0个或多个有sep字符串中一个或多个分隔符分割的标记
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针
- strtok函数会改变被操作的字符串,所以在使用strtok函数切分字符串一般都是临时拷贝的内容并且可修改
- strtok函数的第一个参数不为NULL,函数将找一个str中第一个标记,strtok函数将保存他在字符串中的位置
- 如果字符串中不存在更多的标记,则返回NULL
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
char arr[] = "awd@wasd.sd@aef";
char* p = "@.";
char buf[1024] = { 0 };
strcpy(buf, arr);
char* ret = NULL;
for (ret = strtok(buf, p); ret != NULL; ret = strtok(NULL, p))
{
printf("%s\n", ret);
}
return 0;
}
五、错误信息报告
strerror
使用介绍
- char* strerror(int errnum)
- 错误码 及 错误信息
错误码 错误信息
0 No error
1 Opration not permitted
2 No such file or directory
……k
char* str = strerror(errno)
errno是一个全局的错误码变量,发生了错误就会把对应的错误码,复制到errno中
六、字符分类函数
七、字符转换函数
tolower(转小写字母)
int tolower(int c)
toupper(转大写字母)
int toupper(int c)
例子
char ch = tolower("Q");
putchar(ch);
打印为小写字母
char arr[] = "I Am A Student";
int i = 0;
while(arr[i])
{
if(isupper(arr[i]))
{
arr[i] = tolower(arr[i]);
}
i++;
}
printf("%s\n");
return 0;
八、内存函数
1.memcpy(内存拷贝函数)
使用介绍
- void* memcpy(void* dest,const void* src,size_t num)
- num代表要拷贝的字节个数
- 不可以处理重叠拷贝
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[10] = {0};
将arr1中的数字拷贝到arr2中
memcpy(arr2,arr1,sizeof(arr1));
return 0;
}
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
char* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[10] = { 0 };
int* ret = my_memcpy(arr2, arr1, sizeof(arr1));
int i = 0;
for (i = 0; i < sizeof(arr2)/sizeof(arr2[0]); i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
2.memmove(同字符串内拷贝字符)
使用介绍
- void memmove(void* dest,void* src,size_t num)
- num代表移动的字节
- 在同一个数组内拷贝
模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest, void* src, int count)
{
assert(dest);
assert(src);
char* ret = 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 arr[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr, arr + 2, 20);
int i = 0;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
3.memcmp(字符串内存比较)
使用介绍
- int memcmp(const void* ptr1,const void* pre2,size_t num)
- num代表比较的字节的个数
- ptr1>ptr2 返回 1,prt1 = ptr2 返回 0,ptr1 < ptr2 返回 -1
- 遇到不同的就开始比较并计算并结束
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {1,2,,5,4,3};
int ret = memcmp(arr1,arr2,20);
printf("%d\n",ret);
return 0;
}
打印结果为 -1
4.memset(内存设置)
使用介绍
- void* memset(void* dest,int c,int size_t count)
- 设置缓冲区为一个特定的字符
- count设置多少个字符(1字节),c代表要设置的字符
int main()
{
int arr[10] = {0};
有10个字节
01 01 01 01 01 01 01 01 01…………
memset(arr,1,10);
这里的10是10个字节
return 0;
}