目录
前言
本篇博文将讲解重点介绍处理字符和字符串的库函数的使用和注意事项。
求字符串长度
strlen
用于求取一个字符串的长度,使用格式如下
size_t strlen ( const char * str );
易错点分析:注意函数的返回值为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(str2) = 3 ; strlen(str1) = 6 。按照一般道理说,此时strlen(str2)-strlen(str1)应该小于0,应该输出str2>str1。那么结果真的是这样吗?我们看一下运行结果
结果却是str2<str1。这是什么原因造成的呢?
是因为:函数的返回值为size_t,strlen(str2)-strlen(str1) = -3,-3在内存中的存储为下图所示
模拟实现strlen
模拟实现strlen,只需要遍历字符串,遇到'\0'停止就好
方式一
int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
方式二
int my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}
方式三
int my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
长度不受限制的字符串函数
何为长度不受限制呢?也就是说在作用于字符串时,没有长度限制,遇'\0'停止
strcpy
用于拷贝字符串,使用格式如下
char* strcpy(char * destination, const char * source );
说明:1、源字符串必须以 '\0' 结束。 2、会将源字符串中的 '\0' 拷贝到目标空间。 3、目标空间必须足够大,以确保能存放源字符串。 4、目标空间必须可变。
模拟实现 strcpy
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;//记录的dest的首地址
assert(dest != NULL);//断言,防止空指针
assert(src != NULL);
while((*dest++ = *src++))//一步步遍历,直至遇\0结束
{
;
}
return ret;//首地址
}
strcat
实现字符串追加,将source里的字符串追加到destination后面,格式如下
char * strcat ( char * destination, const char * source );
说明:
1、源字符串必须以 '\0' 结束。
2、目标空间必须有足够的大,能容纳下源字符串的内容。
3 、目标空间必须可修改。
4、字符串不可以自己给自己追加
模拟实现strcat
只需要遍历destination到\0,然后再用source对destination里的0及以后的元素进行一一替换就好,最后还要加上source里的\0;代码实现如下
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;//记录起始位置
assert(dest != NULL);//防止dest为空指针
assert(src != NULL);
while(*dest)
{
dest++;//使dest遍历到\0的位置
}
while((*dest++ = *src++))//进行一一替换,先++,所以\0也进行了替换了
{
;
}
return ret;
}
strcmp
对两个字符串进行大小比较,格式如下
int strcmp ( const char * str1, const char * str2 );
说明 :两字符串比较是一位一位进行比较的,实际比较的是它们的ascll值。
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
模拟实现strcmp
//int my_strcmp(const char* str1, const char* str2)
//{
// assert(str1 && str2);//断言,不为空
//
// while (*str1 == *str2)//进行判断,是否相等
// {
// if (*str1 == '\0')//判断是否字符串遍历结束
// return 0;
//
// str1++;//遍历
// str2++;
// }
//
// return (*str1 - *str2);//返回值
//}
长度受限制的字符串函数介绍
长度限制也就是说作用于字符串时,可以限制其长度,再任意处停止
strncpy
可以规定拷贝的字符个数,格式如下
char * strncpy ( char * destination, const char * source, size_t num );
说明:
1、拷贝num个字符从源字符串到目标空间。
2、如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
strncat
可以规定追加的长度,格式如下
char * strncat ( char * destination, const char * source, size_t num );
说明:把 source所指向的字符串追加到 destination所指向的字符串的结尾,直到 n 字符长度为止。
strncmp
可以选择所需要比较的长度,格式如下
int strncmp ( const char * str1, const char * str2, size_t num );
说明 :比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
字符串查找
strstr
寻找一个字符串中含目标字符串的地址,格式如下
char * strstr ( const char *str1, const char * str2);
说明:
1、函数搜索一个字符串在另一个字符串中的第一次出现。
2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;
3、如果未找到所搜索的字符串,则返回NULL
应用如下
#include <stdio.h>
#include <string.h>
main()
{
char *s="GoldenGlobalView";
char *l="lob";
char *p;
p=strstr(s,l);
if(p)
printf("%s",p);
else
printf("NotFound!");
return 0;
}
模拟实现strstr
char* my_strstr(char *str1, char* str2)
实现strstr我们我们需要对两个字符串进行比较,那么对于str1,我们每次遍历都需要一个起点,而对于str1与str2进行遍历时,我们也各自需要指针进行遍历,逻辑如下
代码实现如下
//char* my_strstr(char *str1, char* str2)
//{
// char* cp = str1;
// char* s1 = cp;
// char* s2 = str2;
//
// if (*str2 == '\0')
// return str1;
//
// while (*cp)
// {
// //开始匹配
// s1 = cp;
// s2 = str2;
// while (*s1 && *s2 && *s1 == *s2)
// {
// s1++;
// s2++;
// }
// if (*s2 == '\0')
// return cp;
//
// cp++;
// }
//
// return NULL;
//}
strtok
分解字符串为一组字符串。str为要分解的字符,sep为分隔符字符,搭配头文件#include<string.h>使用,格式如下:
char * strtok ( char * str, const char * sep );
说明:
1、sep参数是个字符串,定义了用作分隔符的字符集合
2、第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标
3、strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
4、strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。
//int main()
//{
// char arr[] = "zpengwei@yeah.net@666#777";
// char copy[30];
// strcpy(copy, arr);
//
// char sep[] = "@.#";
// char* ret = NULL;
// char* ret = strtok(copy, sep);
// printf("%s\n", ret);
//
// ret = strtok(NULL, sep);//在同一个字符串中被保存的位置开始,查找下一个标
记。
// printf("%s\n", ret);
//
// ret = strtok(NULL, sep);
// printf("%s\n", ret);
上述代码有很大的局限性,而且使用起来不方便,下面代码博主进行了一些优化,代码如下
// char arr[] = "zpengwei@yeah.net@666#777";
// char copy[30];
// strcpy(copy, arr);
//
// char sep[] = "@.#";
// char* ret = NULL;
//
// for (ret = strtok(copy, sep); ret != NULL; ret=strtok(NULL, sep))//循环进行
// {
// printf("%s\n", ret);
// }
这样以来就不用管分割几次了,交给循环来实现就好
注意:需要注意的是,使用该函数进行字符串分割时,会破坏被分解字符串的完整,调用前和调用后的str已经不一样了。第一次分割之后,原字符串str是分割完成之后的第一个字符串,剩余的字符串存储在一个静态变量中,因此多线程同时访问该静态变量时,则会出现错误。
错误信息报告
库函数在执行时,发生了错位,就会产生错误码,产生的错误码会存放在errno这个变量中,errno时C语言提供的全局变量
strerror
使用sterror可以对错误码进行一个打印,应用代码如下
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d: %s\n", i, strerror(i));//
}
return 0;
}
运行结果如下
也可将其应用至文件处,用于找出错误,并指出错误原因,简单运用代码如下
//int main()
//{
// FILE* pf = fopen("data.txt", "r");
// if (pf == NULL)
// {
// printf("fopen: %s\n", strerror(errno));
// perror("fopen");
// //fopen: xxxxxx
// return 1;
// }
// fclose(pf);
// 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
|
任何可打印字符,包括图形字符和空白字符
|
字符转换
tolower()
tolower()函数是把字符串都转化为小写字母。格式如下
int tolower ( int c );
使用如下
string str= "THIS IS A STRING";
for (int i=0; i <str.size(); i++)
{
str[i] = tolower(str[i]);
}
toupper()
toupper()函数是把字符串都转化为大写字母。格式如下
int toupper ( int c );
使用如下
string str= "hahahahaha";
for (int i=0; i <str.size(); i++)
str[i] = toupper(str[i]);
字符函数与字符串函数至此就讲解完毕了,请关注博主后续对内存函数的讲解。
记得三连哦!!!