C语言——字符函数、字符串函数和内存函数
姝孟 2024-09-06 11:35:01 阅读 51
目录
1.字符分类函数
2.字符转换函数
3.字符串函数
3.1strlen 函数
3.1.1 strlen函数的模拟实现
3.1.1.1第一种方法:计算器方法
3.1.1.2 第二种方法:指针-指针
3.1.1.3 第三种方法:递归
3.2 strcpy 函数
3.2.1 strcpy函数的模拟实现
3.3 strcat 函数
3.3.1 strcat 函数的模拟实现
3.4 strcmp 函数
3.4.1 strcmp 函数的模拟实现
3.5 strncpy 函数
3.6 strncat 函数
3.7 strncmp 函数
编辑
3.8 strtok 函数
3.9 strstr 函数
3.9.1 strstr 函数的模拟实现
3.10 strerror 函数
3.10.1 strerror 和 perror
4.内存函数
4.1 memcpy 函数
4.1.1 memcpy 函数的模拟实现
4.2 memmove 函数
4.2.1 memmove 函数的模拟实现
4.3 memset 函数
4.4 memcmp 函数
1.字符分类函数
C语言中有专门做字符分类的,也就是一个字符是属于什么类型的字符的,包含的头文件是 ctype.h,以下是一些常见的函数。
来自网页:cplusplus.com - The C++ Resources Network
具体的应用方法,我们可以通过上面所给到的网页进行探索,此处省略。
2.字符转换函数
C语言中提供了两个字符转换函数:
<code>1 int tolower( int c );//将大写字母转换为小写字母
2 int toupper( int c );//将小写字母转换为大写字母
两个函数就比较简便得实现了大小写字母之间的转换。头文件是ctype.h
3.字符串函数
字符串相关函数的头文件均为 string.h
3.1strlen 函数
strlen 统计的‘\0’之前的字符个数,且不包含' \0 '。
注意:当不包含' \0 '时,strlen 所求出的结果就可能出错。
下面给出一段代码:
<code>int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
{
printf(">\n");
}
else
{
printf("<=\n");
}
return 0;
}
根据运行结果,我们要注意的一点是,strlen是size_t 类型的。
3.1.1 strlen函数的模拟实现
3.1.1.1第一种方法:计算器方法
<code>size_t my_strlen(const char* str)
{
assert(str);
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
size_t len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
3.1.1.2 第二种方法:指针-指针
size_t my_strlen(const char* str)
{
assert(str);
const char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;
}
int main()
{
char arr[] = "abcdef";
size_t len = my_strlen(arr);
printf("%zd\n", len);
return 0;
}
3.1.1.3 第三种方法:递归
size_t my_strlen(const char* str)
{
if (*str != '\0')
{
return 1 + my_strlen(str + 1);
}
else
{
return 0;
}
}
int main()
{
char arr[] = "abcdef";
size_t len = my_strlen(arr);
printf("%zd\n", len);
return 0;
}
函数递归的方法最重要的是作图,理清思路。
这里有一篇关于函数递归的文章,想要更深了解,可以点击下面的链接——
C语言——函数递归-CSDN博客
3.2 strcpy 函数
拷贝时,将' \0 ' 也拷贝到目标数组中。目标字符串的空间要足够大。
使用示例:
<code>int main()
{
char arr1[] = "hello world!";
char arr2[20] = { 0 };
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
3.2.1 strcpy函数的模拟实现
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* str = dest;
while (*src != '\0')
{
*dest = *src;
src++;
dest++;
}
*dest = *src;
return str;
}
int main()
{
char arr1[] = "hello world!";
char arr2[20] = { 0 };
printf("%s\n", my_strcpy(arr2, arr1));
return 0;
}
改进一下代码:
//*dest = *src;
//src++;
//dest++;
//上述三行代码可以写成*dest++ = *src++;
//所以,总的可以改成
while( *dest++ = *src++ )
{
;
}
3.3 strcat 函数
应用示例:
<code>int main()
{
char arr1[20] = "hello";
char arr2[] = " world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
需要注意的是:目标空间需要足够大
目标空间出现' \0 '之后,就在后面开始连接字符串。
3.3.1 strcat 函数的模拟实现
char* my_strcat(char* dest, const char* src)
{
char* str = dest;
assert(dest && src);
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
;
return str;
}
int main()
{
char arr1[20] = "hello";
char arr2[] = " world!";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
接下来区别几个易错点:
0 ——数字0
'0' ——数字字符0,ASCII的值是48
'\0'——\ddd
\0的ASCII值为0
NULL——0(表示空)
3.4 strcmp 函数
strcmp 是用来比较两个字符串
注意比较的不是两个字符串的长度,而是对应位置的大小
使用示例:
<code>int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
相关返回值如下所示:
只是在VS平台中,有默认的固定值。
3.4.1 strcmp 函数的模拟实现
<code>int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
3.5 strncpy 函数
而strcpy为:
不同点就在于strncpy中多了一个参数num,这就起到了限制的作用。
使用示例:
<code>int main()
{
char arr1[20] = "abcdef";
char arr2[20] = { 0 };
strncpy(arr2, arr1, 3);
return 0;
}
3.6 strncat 函数
strcat为:
使用示例:
<code>int main()
{
char arr1[20] = "abcdef";
char arr2[20] = "xxxxxxxx";
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
运行结果为:
3.7 strncmp 函数
strcmp为:
使用示例;
<code>int main()
{
char arr1[20] = "abcdef";
char arr2[20] = "abcq";
int ret = strncmp(arr1, arr2, 3);
printf("%d\n", ret);
return 0;
}
3.8 strtok 函数
以下是官网上对于这一函数的解释:
你可能没看懂,没关系,我也没看懂,最重要的是我们应该会运用这个函数,而不是用复杂的语言来解释一个本身没有那么复杂的问题。
简单应用:
<code>int main()
{
char arr[] = "shumeng@163.com";
char buf[100] = { 0 };
strcpy(buf, arr);
char* sep = "@ .";
char* ret = strtok(buf, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
return 0;
}
该代码有缺陷,改进如下:
int main()
{
char arr[] = "shumeng@163.com";
char buf[100] = { 0 };
strcpy(buf, arr);
char* sep = "@ .";
char* ret = NULL;
for (ret = strtok(buf, sep); ret != NULL; ret = strtok(NULL, sep))
{
printf("%s\n", ret);
}
return 0;
}
这样就简化了代码,运行结果为:
3.9 strstr 函数
功能:
在str1中找str2这个字符串第一次出现的位置——
如果找到了,就返回这个字符串第一次出现的起始地址;
如果没找到,就返回NULL;
使用示例:
<code>int main()
{
char arr[] = "abcdefabcdef";
char* p = "efab";
printf("%s\n", strstr(arr, p));
return 0;
}
运行结果为:
3.9.1 strstr 函数的模拟实现
<code>char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* s1 = str1;
const char* s2 = str2;
const char* cur = str1;
if (*str2 == '\0')
return str1;
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return cur;
cur++;
}
}
int main()
{
char arr[] = "abcdefabcdef";
char* p = "efab";
printf("%s\n", my_strstr(arr, p));
return 0;
}
3.10 strerror 函数
使用示例:
<code>int main()
{
int i = 0;
for (i = 0; i <= 10; i++)
printf("%d : %s\n", i, strerror(i));
return 0;
}
运行结果为:
应用举例:在文件中,打开文件时,要先判断文件本身是否存在。
如:
<code>#include<errno.h>
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("打开文件失败,原因为:%s\n", strerror(errno));
return 1;
}
return 0;
}
运行结果为:
3.10.1 strerror 和 perror
strerror—— 将错误码对应的错误信息的字符串的起始地址返回
perror —— 将errno中错误码对应的信息打印出来
例如:
<code>#include<errno.h>
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("打开文件失败,原因为:%s\n", strerror(errno));
perror("打开文件失败,原因为");
return 1;
}
return 0;
}
运行结果为:
4.内存函数
4.1 memcpy 函数
数据类型不确定,因此类型均为void
例如:
<code>int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
//将arr1中的3 4 5 6 7 拷贝到arr2中
memcpy(arr2, arr1 + 2, 20);//其中的20表示的是字节数
return 0;
}
4.1.1 memcpy 函数的模拟实现
void* my_memcpy(void* dest, const void* src, size_t num)
{
int i = 0;
void* ret = dest;
assert(dest && src);
for (i = 0; i < num; i++)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
//将arr1中的3 4 5 6 7 拷贝到arr2中
my_memcpy(arr2, arr1 + 2, 20);//其中的20表示的是字节数
return 0;
}
需要注意的是,使用该函数时,当dest 和 src 中有重叠时,结果是未知的。
4.2 memmove 函数
<code>int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 20);
return 0;
}
因此,我们从上述中可以看出,memmove 可以实现重叠情况。
4.2.1 memmove 函数的模拟实现
void* my_memove(void* dest, const void* src, size_t num)
{
//从后往前拷贝
void* ret = dest;
assert(dest && src);
if (dest < src)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
//从前向后拷贝
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 20);
return 0;
}
4.3 memset 函数
<code>int main()
{
char arr[] = "hello world!";
memset(arr + 6, 'x', 5);//这里的5是字节数
printf("%s\n", arr);
return 0;
}
4.4 memcmp 函数
使用示例:
<code>int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,3,6,5 };
int ret = memcmp(arr1, arr2, 12);//12表示的是字节数
printf("%d\n", ret);
return 0;
}
常见的函数就说到这里。
声明:本文大部分图片内容来源于cplusplus.com - The C++ Resources Network 中的内容
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。