目录
本文章重点内容
重点介绍处理字符和字符串的库函数的使用和注意事项
- 求字符串长度
- strlen
- 长度不受限制的字符串函数
- strcpy
- strcat
- strcmp
- 长度受限制的字符串函数介绍
- strncpy
- strncat
- strncmp
- 字符串查找
- strstr
- strtok
- 错误信息报告
- strerror
- 字符操作
- 内存操作函数
- memcpy
- memmove
- memset
- memcmp
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。
字符串常量 适用于那些对它不做修改的字符串函数.
一、函数的介绍
1.1 strlen
size_t strlen ( const char * str );
- 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
含 '\0' )。 - 参数指向的字符串必须要以 '\0' 结束,否则会出现随机打印的情况。
- 易错点:注意函数的返回值为size_t,是无符号的。
下面我具体举一个例子来为大家展示一下strlen 函数的返回值是size_t(无符号整型)。
#include <stdio.h>
int main()
{
const char* str1 = "abcdef";
const char* str2 = "bbb";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
大家看这段代码,如果以为strlen的返回类型是int,那么在if 判断部分为假,会执行else部分。下面我们看一下执行结果。
那么为什么会出现这个结果呢?
因为strlen 的返回类型为size_t ,在相减的时候虽然数值是 -3,但是由于是无符号数,所以在内存中存储的是补码,补码又以无符号数的形式解读,会是一个很大的数字。
在讲了strlen函数具体如何使用以后,我们也应该具备自己动手实现strlen函数的能力。
strlen的模拟实现
方法一:计数器的方式
#include<stdio.h>
int my_strlen(char* str)
{
int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
方法二:指针 - 指针的方式
int my_strlen(char* str)
{
char* cur = str;
while (*cur)
{
cur++;
}
return cur - str;
}
int main()
{
char arr[] = "abcdef";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
方法三:递归的方式
int my_strlen(char* str)
{
if (*str == 0)
{
return 0;
}
else
{
return 1 + my_strlen(str + 1);
}
}
int main()
{
char arr[] = "abcdef";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
1.2 strcpy
char* strcpy (char * destination, const char * source );
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
-
该函数的作用是将source字符串,拷贝到dest字符串中,要求dest必须可变,而且空间足够。
strcpy的模拟实现
char* my_strcpy(char* dest, const char* src)
{
char* tmp = dest;
while (*dest++ = *src++)
{
;
}
return tmp;
}
int main()
{
char arr1[20] = "hello bit";
char arr2[] = "hello world";
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
1.3 strcat
char * strcat ( char * destination, const char * source );
- 源字符串必须以 '\0' 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- 思考:字符串自己给自己追加,会如何?
思考题:
strcat 函数的实现
char* my_strcat(char* dest, const char* src)
{
char* tmp = dest;
while (*dest)
{
dest++;
}
while (*dest = *src)
{
dest++;
src++;
}
return tmp;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "bit";
my_strcat(arr1, arr2);
printf("%s", arr1);
return 0;
}
1.4 strcmp
int strcmp ( const char * str1, const char * str2 );
标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
那么如何判断两个字符串?下面我们来具体举一个例子。
总结1:以上我们学习了四个关于字符串的函数,这四个的特点是没有对于字符的限制,接下来我们学习的函数都会对于字符有一定的限制。
1.5 strncpy
char * strncpy ( char * destination, const char * source, size_t num );
- 拷贝num个字符从源字符串到目标空间。这里多出一个参数就是限制了拷贝空间的大小
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
情况1:num小于 源字符串长度,不会拷贝 \0
情况2:num 大于源字符串的长度,会补上相差个数的 \0
strncpy的模拟实现
char* my_strncpy(char* dest, const char* src, int num)
{
char* tmp = dest;
while (num--)
{
if (*src)
{
*dest = *src;
dest++;
src++;
}
else
{
*dest++ = '\0';
}
}
return tmp;
}
int main()
{
char arr1[20] = "**************";
char arr2[] = "abcdefgh";
my_strncpy(arr1, arr2, 10);
printf("%s", arr1);
return 0;
}
1.6 strncat
char * strncat ( char * destination, const char * source, size_t num );
- Appends the first num characters of source to destination, plus a terminating null-character.
- If the length of the C string in source is less than num, only the content up to the terminating
null-character is copied.
情况一:num <= 源字符串长度,正常追加,并且追加 \0
情况二: num > 源字符串长度,追加源字符串 追加 \0
strncat 的模拟实现
char* my_strncat(char* dest, const char* src, int num)
{
char* tmp = dest;
while (*dest)
{
dest++;
}
while (num--)
{
if (*src)
{
*dest = *src;
dest++;
src++;
}
else
{
break;
}
}
*dest = '\0';
return tmp;
}
int main()
{
/*char arr1[20] = "hello ";
char arr2[] = "bit";
my_strncat(arr1, arr2, 15);*/
char arr1[20] = "hello \0*********";
char arr2[] = "bit";
my_strncat(arr1, arr2, 6);
printf("%s", arr1);
return 0;
}
1.7 strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
- 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
1.8 strstr
char * strstr ( const char *str1, const char * str2);
- Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of
str1. - strstr 在第一个字符串中寻找第二个字符串,找到第一次出现的位置并且返回,如果找不到就返回空指针
strstr 的使用
strstr 的模拟实现
char* my_strstr(const char* str1, const char* str2)
{
if (str2 == NULL)
{
return (char*)str1;
}
char* s1 = NULL;
char* s2 = NULL;
const char* cp = str1;
while (*cp)
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbbbcdef";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret ==NULL)
{
printf("找不到\n");
}
else
{
printf("%s", ret);
}
}
1.9 strtok
char * strtok ( char * str, const char * sep );
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标
记。 - strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
并且可修改。) - strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
中的位置。 - strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。 - 如果字符串中不存在更多的标记,则返回 NULL 指针。
strtok的使用
1.10 strerror
char * strerror ( int errnum );
- 返回错误码 errno ,所对应的错误信息
总结
以上就是我今天总结的所有有关于字符串函数的详细解析,其中包含字符串函数的使用以及对于大部分字符串函数的实现。