文章目录
前言
最近在刷题的时候,经常遇到需要用到字符串函数的问题,因此发现对这方面函数使用的一些不足,遂写一篇博客(笔记),巩固自身也便复习。
一、字符串函数
1.求字符串长度 strlen
函数定义:
size_t strlen ( const char * str );
注意点:
- 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
- 参数指向的字符串必须要以 ‘\0’ 结束。
- 注意函数的返回值为size_t,是无符号的( 易错 )
2.长度不受限制的字符串函数strcpy、strcat、strcmp
字符串拷贝 strcpy
函数定义:
char* strcpy(char * destination, const char * source );
注意点:
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
Strcpy的作用是将一个数组的字符串以覆盖的方式复制到另一个数组,由于‘\0’也被复制,所以相当于完全拷贝。strcpy会返回一个char型指针,该指针指向被覆盖的目标字符串的第一个字符的地址。
例如:
#include<stdio.h>
#include<string.h>
//strcpy的作用以及用法
int main(){
char a[32]="America";
char b[32]="China";
strcpy(a,b); // 将b的内容覆盖复制到a
printf("%s\n%s",a,b);
return 0;
}
以上代码的结果为:
China
China
字符串追加拷贝 strcat
函数定义:
char * strcat ( char * destination, const char * source );
注意点:
- 源字符串必须以 ‘\0’ 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
Strcat的用法与strcpy相似,作用是以拼接的方式,将源字符串的内容追加拷贝到目标字符串后面。
例如:
#include<stdio.h>
#include<string.h>
int main(viod){
char c[32]="America";
char d[32]="China";
strcat(c,d);
printf("%s\n",c);
return 0;
}
以上代码的结果为:
AmericaChina
字符串比较 strcmp
函数定义:
int strcmp ( const char * str1, const char * str2 );
注意点:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
strcmp函数按照ASCII码来比较两字符串每一位字符的的大小,直到出现不同的字符or遇到‘\0’为止。当某一个字符串提前结束(遇到‘\0’),那么就算做另一个字符串比较‘大’。
3.长度受限制的字符串函数strncpy、strncat、strncmp
strncpy、strncat、strncmp三个函数的作用与strcpy、strcat、strcmp几乎完全一样,唯一不同的是他们多了一个参数,所以这里只给出其函数定义及注意点:
字符串拷贝 strncpy
函数定义
char * strncpy ( char * destination, const char * source, size_t num );
注意点:
- 拷贝num个字符从源字符串到目标空间。
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
字符串追加拷贝 strncat
函数定义
char * strncat ( char * destination, const char * source, size_t num );
注意点:
- 同strncpy
字符串比较 strncmp
函数定义
int strncmp ( const char * str1, const char * str2, size_t num);
注意点:
- 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完
4.判断字符串匹配问题 strstr
函数定义
char * strstr ( const char *, const char * );
strstr(str1,str2)函数用于判断字符串str2是否是str1的子串。如果是、则返回str1字符串从str2第一次出现的位置到str1结尾的字符串,否则返回NULL。可以用来1.分割字符串;2.通过查找子串进行删除,修改等一系列操作。
5.字符操作
字符分类函数
函数 | 如果他的参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’ |
isgraph | 任何图形字符 |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母 |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母az或AZ |
isalnum | 字母或者数字,az,AZ,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
字符转换函数
int tolower ( int c );//转换成小写
int toupper ( int c );//转换成大写
二、内存操作函数
1.memcpy
函数定义
void * memcpy ( void * destination, const void * source, size_t num );
注意点:
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的(存在内存重叠)。
memcpy与strcpy的区别
- 复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
- 用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
- 复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
2.memmove
函数定义
void * memmove ( void * destination, const void * source, size_t num );
注意点:
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
三、库函数模拟实现
1.strlen
int my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
2.strcpy
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
}
3.strcat
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest)
{
dest++;
}
//追加拷贝
while((*dest++ = *src++))
{
;
}
return ret;
}
4.strcmp
int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL);
assert(dest != NULL);
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
5.memcpy
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
//从低地址向高地址拷贝
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
6.memmove
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
//如果条件成立,表明向前拷贝不会出现内存重叠现象,采用memcpy相同方法拷贝,反之采用高地址向低地址拷贝
if (dst <= src || (char *)dst >= ((char *)src + count)) {
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}