c语言字符串处理函数
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C语言字符串处理函数
一、函数
1、字符串的长度strlen()
说明:
返回s的长度,不包括结束符NULL。
strlen(char*)函数求的是字符的实际长度,它求得方法是从开始到遇到第一个'\0',如果你只定义没有给它赋初值,这个结果是不定的,它会从首地址一直找下去,直到遇到'\0'停止。
与sizeof()的区别:
A、char ss[10]="";
sizeof(ss) = 10;
strlen(ss) = 0;
B、char *aa = "asd";
sizeof(aa) = 4;
strlen(aa) = 3;
C、sizeof是在编译期间计算其值;
Strlen在运行期间计算返回值
D、sizeof是操作符(关键字),strlen是函数。
E、.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。
这是因为sizeof是个操作符不是个函数。
F、当适用了于一个结构类型时或变量,sizeof 返回实际的大小,
当适用一静态地空间数组,sizeof 归还全部数组的尺寸。
sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸
自定义strlen()
int strlen(const char *str)
{
assert(str != NULL);
int len = 0;
while((*str++) != '\0')
len++;
return len;
}
2、比较字符串大小函数
区分大小写:strcmp()
(1)函数原型:int strcmp(char*str1,char*str2);
函数说明:通过比较字串中各个字符的ASCII码,来比较参数Str1和Str2字符串,比较时考虑字符的大小写。
返回值:比较字符串str1和str2的大小,如果str1小于str2,返回值就<0,反之如果str1大于str2,返回值就>0,如果str1等于str2,返回值就=0,
自定义实现:
int strcmp (char* a,char* b)
{
int k=0;
for( ; a[k] && b[k] && (a[k]==b[k]) ; k++);
return(a[k]-b[k]);
}
strncmp()
(2) 函数原型:int strncmp(char *str1, char *str2, int maxlen);
函数说明:比较字符串str1和str2的前maxlen个字符
返回值:比较字符串str1和str2的大小,
如果str1小于str2,返回值就<0;
反之如果str1大于str2,返回值就>0;
如果str1等于str2,返回值就=0;
maxlen指的是str1与str2的比较的字符数。
自定义实现:
int strncmp(char *str1, char *str2, int maxlen)
{
if (maxlen == 0)
{
return 0;
}
int k=0;
for (;str1[k]&&str2[k]&&(str1[k]==str2[k])&&(k<maxlen);++k)
;
return str1[k] - str2[k];
}
不区分大小写:
1)忽略大小写---strcasecmp
函数原型:int strcasecmp (const char *s1, const char *s2);
函数说明:用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异
2)忽略大小写—stricmp
函数原型:int stricmp(char *str1, char *str2);
函数说明:以大小写不敏感方式比较两个串
3)比较一部分—strncmpi
函数原型:int strncmpi(char *str1, char *str2, unsigned maxlen);
函数说明:比较字符串str1和str2的前maxlen个字符
5)内存区域比较---memcmp
函数原型:int memcmp(void*buf1,void *buf2,unsigned int count)
函数说明:比较内存区域buf1和buf2的前count个字节。
Void*是指任何类型的指针。
6)内存区域部分比较-- memicmp Void*是指任何类型的指针。
函数原型:int memicmp(void*buf1,void *buf2,unsigned int count)
函数说明:比较内存区域buf1和buf2的前count个字节,但不区分大小写。
以上比较函数的返回值:
若参数1中字符串和参数中2字符串相同则返回0;
若参数1中字符串长度大于参数2中字符串长度则返回大于0 的值;
若参数1中字符串长度小于参数2中字符串长度则返回小于0的值。
3、从字符串中提取子串
1)提取子串—strstr (这个实现传说很复杂)
函数原型:char* strstr(char*src,char*find)
函数说明:从字符串src中寻找find第一次出现的位置(不比较结束符NULL)
返回值:返回指向第一次出现find位置的指针,如果没有找到则返回NULL
2)提取分隔符间字串—strtok
函数原型:char *strtok(char *s, char *delim);
函数说明:分解字符串为一组字符串。
s为要分解的字符串,delim为分隔符字符串。
首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。
strtok在s中查找包含在delim中的字符并用NULL('')来替换,直到找遍整个字符串。
返回值:从s开头开始的一个个被分割的串。
当没有被分割的串时则返回NULL。
所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点
举例:
#include <string.h> #include <stdio.h> int main(){ char *s="Golden Global View"; char *d=" ";
char *p;
p=strtok(s,d);
while(p){
printf("%s\n",p); strtok(NULL,d); }
return 0; }
输出:Golden
Global
View
4、字符串复制
1) 字串复制--strcpy
函数原型:char*strcpy(char*dest,char*src)
功能:把src所指由NULL结束的字符串复制到dest所指的数组中。
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回值:返回指向dest的指针。
标准库函数实现:
char *strcpy(char *strDestination, const char *strSource)
{
assert(strDestination && strSource);
char *strD=strDestination;
while ((*strDestination++=*strSource++)!='\0');
return strD;
}
题目:
已知strcpy函数的原型是:
char * strcpy(char * strDest,const char * strSrc);
1.不调用库函数,实现strcpy函数。
2.解释为什么要返回char *。
解答:
1. strcpy的实现代码
char *strcpy(char *strDestination, const char *strSource)
{
assert(strDestination && strSource);
char *strD=strDestination;
while ((*strDestination++=*strSource++)!='\0');
return strD;
}
错误的做法:
[1]
(A)不检查指针的有效性,说明答题者不注重代码的健壮性。
(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C 语言中类型的隐式转换没有深刻认识。
在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。
所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
(C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。
直接使用字面常量(如本例中的0)会减少程序的可维护性。
0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。
而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。
[2]
(A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。
从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。
(B)return 0; 说明答题者没有掌握异常机制。
调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。
妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。
应该以抛出异常来代替返回值,这样可以减轻调用者的负
担、使错误不会被忽略、增强程序的可维护性。
[3]
(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。
[4]
(A)循环写成while (*strDest++=*strSrc++);,同[1](B)。
(B)循环写成while (*strSrc!='\0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。
循环体结束后,strDest字符串的末尾没有正确地加上'\0'。
2.返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。
同样功能的函数,如果能合理地提高的可用性,自然就更加理想。
链式表达式的形式如:
int iLength=strlen(strcpy(strA,strB));
又如:
char * strA=strcpy(new char[10],strB);
返回strSrc的原始值是错误的。
其一,源字符串肯定是已知的,返回它没有意义。
其二,不能支持形如第二例的表达式。
其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。
2)字串复制--strdup
原型:extern char *strdup(char *s);
用法:#include <string.h>
功能:复制字符串s
说明:返回指向被复制的字符串的指针,所需空间由malloc()分配且可以由free()释放。
举例:
// strdup.c
#include <string.h>
main()
{
char *s="Golden Global View";
char *d;
clrscr();
d=strdup(s);
printf("%s",d);
free(d);
getchar();
return 0;
}
3)内存空间复制--memcpy
函数原型:void *memcpy(void *dest,void *src,unsigned int count);
函数说明:src和dest 所指内存区域不能重叠;由src所致内存区域复制count个字节到dest所指内存区域中。
返回值:返回指向dest的指针。
5、字符串连接
1)接尾连接--strcat
函数原型:char* strcat(char*dest,char*src)
函数说明:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'
自定义函数实现:
char * strcat(char * dest, const char * src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0')
;
return tmp;
}
2)部分连接--strncat
函数原型:char* strncat(char*dest,char*src,int n);
函数说明:把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的’\0’)并添加’’\0’.
返回值:返回指向dest的指针。
6、从字符串中查找字符
1)内存区域找字符--memchr
函数原型:void *memchr(void*buf,char ch,usigned count)
函数说明:从buf所指内存区域的前count个字节查找字符ch,当第一次遇到字符ch时停止查找。
返回值:如果找到了,返回指向字符ch的指针;否则返回NULL
2)字串中找字符--strchr
函数原型:char* strchr(char*src,char ch)
函数说明:查找字符串s中首次出现字符ch的位置
返回值:返回首次出现c的位置的指针,如果s中不存在c则返回NULL
3)搜所现字符--strcspn
函数原型:int strcspn(char*src,char*find)
函数说明:在字符串src中搜寻find中所出现的字符
返回值:返回第一个出现的字符在src中的下标值,即src中出现而不在find中出现的字串的长度。
举例:
#include <string.h>
#include <stdio.h>
int main(){
char *s="Golden Global View"; char *r="new";
int n;
n=strcspn(s,r);
printf("The first char both in s1 and s2 is: %c",s[n]);
return 0;
}
输出:The first char both in s1 and s2 is :e
4)匹配任一字符--strpbrk
函数原型:char*strpbrk(char*s1,char*s2)
函数说明:在字符串S1中寻找字符串S2中任何一个字符相匹配的第一个字符的位置,空字符不包括在内。
返回值:返回指向S1中第一个相匹配的字符的指针,如果没有匹配字符则返回空指针。
举例:
#include <stdio.h>
#include <string.h>
int main(){
char *s1="Welcome To Beijing"; char *s2="BIT";
char *p;
p=strpbrk(s1,s2);
if(p)
printf("%s\n",p);
else printf("Not Found!\n"); return 0;
}
输出:To Beijing
7、其他函数
1)全部转成大写---strupr
函数原型:char*strupr(char*src)
函数说明:将字符串src转换成大写形式,只转换src中出现的小写字母,不改变其他字符
返回值:返回指向src的指针。
2)全部转成小写---strlwr
函数原型:char*strlwr(char*src)
函数说明:将字符串src转换成小写形式,只转换src中出现的大写字母,不改变其他字符返回值:返回指向src的指针。
3)将字串逆向--strrev
函数原型:char*strrev(char*src)
函数说明:把字符串src的所有字符的顺序颠倒过来(不包括NULL)
返回值:返回指向颠倒顺序后的字符串指针。