字符函数和字符串函数的使用
- 求字符串长度 strlen
- 长度不受限制的字符串函数 strcpy strcat strcmp
- 长度受限制的字符串函数介绍
strncpy strncat strncmp - 字符串查找 strstr strtok
- 错误信息报告 strerror
- 内存操作函数memcpy memmove memset memcmp
c语言中对字符和字符串的处理很是频繁,但是c语言本身是没有字符串类型的字符串通常放在常量字符串中,或者字符数组中,字符串常量,适用于那些对它不做修改的字符串函数
strlen
size_t strlen(const char* str)
字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’);参数指向的字符串必须要以’\0’结束注意函数的返回值为size_t,是无符号的学会strlen函数的模拟实现,size_t是unsigned int 是无符号的整数
strlen深入理解
size_t strlen(const char* str);
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
return 0;
}
下面代码是模拟实现strlen
size_t strlen(const char* str);
size_t 就是unsigned int是一个无符号的数字
int my_strlen(const char* str)
{
int count = 0;
assert(str != NULL);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
int arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
strcpy 字符串拷贝
strcpy的参数是:
char* strcpy(char* destination, const char * source);
desitination是目的地,source是源头
1:源字符串必须以'\0'结束
2:会将源字符串中的'\0'拷贝到m目标空间
3:目标空间必须足够大,以确保能存放源字符串
4:目标空间必须可变
5:学会模拟实现
strcpy的用法
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "bit";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
模拟实现strcpy
char* my_strcpy(char* dest,const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (*src != '\-')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
return ret;
}
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "bit";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcat 字符串追加
char * strcat (char* destination, const char * source); 字符串追加
1.源字符串必须以 '\0'结束
2.目标空间必须有足够的大,能容纳下源字符串的内容
3.目标空间必须可修改
4.字符串自己给自己追加如何
自己给自己追加要使用strncat
strcat的用法是什么
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
模拟实现strcat
char* my_strcat(char* arr1,const char* arr2)
{
char* ret = arr1;
assert(arr1 != NULL);
assert(arr2 != NULL);
while (*arr1 != '\0')
{
arr1++;
}
while (*arr2 != '\0')
{
*arr1 = *arr2;
arr1++;
arr2++;
}
*arr1 = *arr2;
return ret;
}
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s\n",arr1);
return 0;
}
strcmp 字符串比较
int strcmp(const char * str1,const char* str2);参数
标准规定 1.第一个字符串大于第二个字符串,则返回大于0的数字 2.第一个字符串等于第二个字符串,则返回0 3.第一个字符串小于第二个字符串,则返回小于0的数字
strcmp的用法是什么
int main()
{
char* p1 = "asbc";
char* p2 = "def";
int ret = strcmp(p1, p2);
printf("%d\n", ret);
if (strcmp(p1, p2) > 0)
{
printf("p1>p2\n");
}
else if (strcmp(p1, p2) == 0)
{
printf("p1======p2\n");
}
else if (strcmp(p1, p2) < 0)
{
printf(" p1<p2\n");
}
return 0;
}
模拟实现strcmp
int my_strcmp(char* p1,char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
while (*p1 == *p2)
{
if (*p1 == '\0')
{
return 0;
}
p1++;
p2++;
}
return (*p1-*p2)
}
int main()
{
char* p1 = "abcdef";
char* p2 = "abcdds";
int ret = my_strcmp(p1, p2);
if (ret == 1)
{
printf("p1>p2\n");
}
else if (ret == -1)
{
printf("p1==p2\n");
}
else
{
printf("p1<p2\n");
}
return 0;
}
strncpy
char* strncpy(char* strDest,const char* strSource,size_t num); num单位是字节
拷贝num个字符从源字符串到目标空间 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,知道num个
strncpy的用法
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "hello bit";
strncpy(arr1, arr2, 4);
printf("%s\n", arr1);
return 0;
}
strncat
参数 char * strncat(char * destination, const char * source,size_t num);//追加
strncat的用法
int main()
{
char arr1[30] = "hello\0xxxxaxx";
char arr2[] = "world";
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
strncmp
参数是:int strncmp(const char * str1,const char * str2, size_t num);
int main()
{
const char* p1 = "abcdef";
const char* p2 = "abcdqwer";
int ret = strncmp(p1, p2, 6);
printf("%d\n", ret);
return 0;
}
strstr 找子字符串, 查找字符串
参数是: char* strstr(const char* ,const char*);
strstr的用法
int main()
{
char* p1 = "abcdefsss";
char* p2 = "def";
char* ret = strstr(p1, p2);
if (ret == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s\n", ret);
}
return 0;
}
注意平时看英文文档时
看文档时:NULL–空指针 NUL/Null 表示’\0’
模拟实现strstr
char* my_strstr(const char* p1,const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char *s1 = p1;
char *s2 = p2;
char *cur = p1;
if (*p2 == '\0')
{
return p1;
}
while (*cur)
{
s1 = cur;
s2 = p2;
while ((*s1 != '\0')&&(*s2 != '\0')&&(*s1 ==*s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur;
}
cur++;
}
return NULL;
}
int main()
{
char * p1 = "abbbcdef";
char * p2 = "bbc";
char * ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s\n",ret);
}
return 0;
}
模拟实现my_strstr
char* my_strstr(const char* p1,const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char* s1 = p1;
char* s2 = p2;
char* cu = p1;
if (*p2 == '\0')
{
return p1;
}
while (*cu)
{
s1 = cu;
s2 = p2;
while ((*s1 != '\0') && (*s2 != '\0')&&(*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cu;
}
cu++;
}
return NULL;
}
int main()
{
char* p1 = "abbbcdef";
char* p2 = "bbc";
char* ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("没有找到子串\n");
}
else
{
printf("%s\n", ret);
}
return 0;
}
strtok 字符串切割打印
参数 char* strtok( char* str, const char* sep);//sep分隔符 1.sep参数是个字符串,定义了用作分隔符的字符集合 2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符 分割的标记 3.strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针 (注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是 临时拷贝的内容并且可修改) 4.strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存 它在字符串中的位置 5.strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找 下一个标记 6.如果字符串中不存在更多的标记,则返回NULL指针
分隔符理解
192.168.31.121 //这里的分隔符就是 . 192.168.31.121 - strtok zpw@bitdu.tech //这里的分隔符就是@和. zpw bitdu tech
strtok的使用
int main()
{
char arr[] = "zpw@bitdu.tech";
char* p = ("@.");
char buf[1024] = { 0 };
strcpy(buf,arr);
char* ret =strtok(arr, p);
printf("%s\n", ret);
ret = strtok(NULL, p);
printf("%s\n", ret);
ret = strtok(NULL, p);
printf("%s\n", ret);
return 0;
}
自己实现strtok
int main()
{
char arr[] = "zpw@bitdu.tech";
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
errno是一个全局的错误码变量 当c语言的库函数在执行过程中,发生了错误,就会把对应的错误码,赋值到errno中 strerror 参数 char * strerror(int errnum); 返回错误码 所对应的错误信息 0 No error 1 Operation not permitted 2 No such file or directory …
int main()
{
char* str = strerror(errno);
printf("%s\n", str);
return 0;
}
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
}
else
{
printf("open file success\n");
}
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 任何可打印字符,包括图形字符和空白字符
下面是具体的使用实例
#include<ctype.h>
int main()
{
char ch = '@';
int ret = isdigit(ch);
printf("%d\n", ret);
return 0;
}
字符转换函数 tolower toupper
int tolower(int c);
int toupper(int c);
int main()
{
char ch = toupper('s');
putchar(ch);
return 0;
}
int main()
{
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", arr);
return 0;
}
内存操作函数 memcpy memmove memcmp memset
memcpy 内存拷贝
memcpy - 内存拷贝 void* -通用类型的指针 -无类型指针
void * mencpy( void * destination, const void * source, size_t num );
- destination 目的地
- source 源头
- num多少字节
1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置 2.这个函数在遇到’\0’的时候并不会停下来 3.如果source和destination有任何的重叠,复制的结果都是未定义的
下面是memcpy的用法
struct S
{
char name[20];
int age;
};
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[5] = { 0 };
struct S arr3[] = { {"张三",20}, {"李四",30} };
struct S arr4[3] = { 0 };
memcpy(arr4, arr3, sizeof(arr3));
return 0;
模拟实现memcpy
void* my_memcpy(void* dest,const void* src, size_t num)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
return ret;
}
struct S
{
char name[20];
int age;
};
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[5] = { 0 };
struct S arr3[] = { { "张三", 20 }, { "李四", 30 } };
struct S arr4[3] = { 0 };
memcpy(arr2 , arr1 , sizeof(arr1));
return 0;
}
C语言标准
1:memcpy 只要处理 不重叠的内存拷贝就可以
2:memmove 处理重叠内存的拷贝
memmove
参数 void * memmove( void * destination, const void * source, size_t num); 1.和memcpy的差别就是memmove函数处理的源内存块和目标n内存块是可以重叠的 2.如果源空间和目标空间出现重叠,就得使用memmove函数处理
memmove进行模拟实现
void* my_memmove(void* dest, const void* src,size_t count)
{
void* ret = dest;
assert(dest != NULL);
assert(src != NULL);
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 };
memmove(arr+4, arr+2, 20);
return 0;
}
memcmp 内存比较
参数 int memcmp(const void* ptr1, const void* ptr2, size_t num); 返回值 >0 <0 ==
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[] = { 1, 2, 5, 4, 3 };
int ret = memcmp(arr1, arr2, 9);
printf("%d\n", ret);
return 0;
}
memset - 内存设置
void * memset( void* dest, int c, size_t count); count的单位是字节 dest 目的地要把那一块的空间进行设置 c 就是你要设置的字符是什么 count 你要设置多少个字符
int main()
{
char arr[10] = "";
memset(arr, '#', 10);
return 0;
}
|