C语言常见字符串库函数的使用与实现
Posted 蓝乐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言常见字符串库函数的使用与实现相关的知识,希望对你有一定的参考价值。
目录
字符串有关库函数介绍及使用
简述
1.strlen的使用及实现
strlen函数是用于计算字符串长度的函数,字符串是以’\\0’作为结束标志的,故strlen计算第一次遇到’\\0’前的字符个数。
strlen函数的实现方式有三种:
1.计数器法
通过count变量来统计字符串中’\\0’前的字符个数
int my_strlen(const char* str)
{
assert(str);//避免对NULL解引用
int count = 0;
while (*str++)
{
count++;
}
return count;
}
2.递归法
不借助临时变量通过递归找到’\\0’并返回其前字符个数
int my_strlen(const char* str)
{
assert(str);
if (*str == '\\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
3.指针-指针法
由于指针与指针的差是两指针间的元素个数,故通过指针作差可以计算字符串的长度
int my_strlen(const char* str)
{
assert(str);
char* start = (char*)str;
char* end = (char*)str;
while (*end)
{
end++;
}
return end - start;
}
【注意】
1.由于字符串是以’\\0’为结束标志的,故以下两个语句之间有区别:
int main()
{
char str1[] = "never give up";
char str2[] = { 'a','b','c' };
printf("%d\\n", my_strlen(str1));
printf("%d\\n", my_strlen(str2));
return 0;
}
对于str1其在字符串末尾隐藏了’\\0’,而对于str2,由于不确定’\\0’的位置,因此所求出的字符串长度是随机值。
2.库中strlen函数的形式为:size_t strlen ( const char * str );
其返回类型是size_t,即无符号整形,因为其认为字符串函数是非负的,但这可能在实际使用中出现问题,比如strlen(“abc”) - strlen(“abcdef”)是大于0的(因二者皆为无符号整形,始终非负)。
2.strcmp的使用及实现
int strcmp ( const char * str1, const char * str2 );
strcmp函数是依次比较字符串中的字符的函数,若字符相同则返回0,遇到第一个不相同的字符,则比较其ASCII码值,str1大于str2则返回大于0的数,str1小于str2则返回小于0的数。
函数的实现非常简单:
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)//判断两字符串是否相等
{
if (*str2 == '\\0')//相等则返回0
{
return 0;
}
else
{
str1++;
str2++;
}
}
if (*str1 > *str2)
{
return 1;
}
else
return -1;
}
3.strcpy的使用及实现
char * strcpy ( char * destination, const char * source );
将source所指向的字符串拷贝到destination中。
int main()
{
char str1[] = "################";
char str2[] = "never give up";
my_strcpy(str1, str2);
printf("%s\\n", str1);
return 0;
}
函数实现也相对简单:
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;//记录下目的字符串首字符的地址并返回
while (*dest++ = *src++)//将*src赋值给*dest
{
;
}
return ret;
}
4.strcat的使用及实现
char * strcat ( char * destination, const char * source );
将source所指向的字符串追加到destination所指向的字符串后。
int main()
{
char str1[30] = "never ";
char str2[] = "give up";
my_strcat(str1, str2);
printf("%s\\n", str1);
return 0;
}
代码实现:
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* cp = dest;
while (*cp)//cp指向dest所指字符串中'\\0'的位置
{
cp++;
}
while (*cp++ = *src++)//将src所指向字符串拷贝到cp所指向的字符串中
{
;
}
return dest;
}
5.strstr的使用及实现
char * strstr ( const char *str1, const char *str2 );
判断str2是否在str1中出现,即str2是否为str1的子串,若是,则返回str2在str1中首次出现的字符地址,否则返回NULL。
int main()
{
char str1[] = "abbbcdef";
char str2[] = "bbc";
printf("%s", my_strstr(str1, str2));
return 0;
}
函数的实现需要引入三个临时变量,s1与s2比较判断s2是否与s1相同,cp记录当前比较的第一个字符的位置,遍历cp即可比较str2是否在str1中出现
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
char* s1 = NULL;//不改变str1和str2的指向
char* s2 = NULL;//保留模式串str2
char* cp = (char*)str1;
while (*cp)//cp遍历str1
{
s1 = cp;
s2 = (char*)str2;
while (*s1 == *s2 && *s1 && *s2)
{
s1++;
s2++;
if (*s2 == '\\0')//s2遍历
return cp;
}
cp++;
}
return NULL;
}
在使用strcat时并不能让字符串自己追加到自己之后,因为这样做会让’\\0’被覆盖以至于无法找到结束标志而进入死循环,因此需要strncat函数来实现这个功能,同时strncat函数作为长度受限制的函数,在一定程度上防止了越界的出现,使代码相对安全。
6.strncat的使用及实现
char * strncat ( char * destination, const char * source, size_t num );
在destination所指向的字符串末尾加上num个source所指向的字符串的字符。
int main()
{
char str1[30] = "never ";
char str2[] = "give up";
my_strncat(str1, str2, 4);
printf("%s\\n", str1);
return 0;
}
函数的实现与strcat类似,只是需要分num大于str2所指向的字符串的长度和num小于两种情况:
char* my_strncat(char* str1, const char* str2, size_t num)
{
assert(str1 && str2);
char* cp = str1;
while (*cp)//cp遍历str1至'\\0'
{
cp++;
}
while (num--)//将str2中num个字符拷贝到str1中,若num大于str2字符串长度,则将str1之后的一个字符置为'\\0'
{
*cp++ = *str2++;
if (*str2 == '\\0')
return str1;
}
*cp = '\\0';
return str1;
}
在strcpy函数中,如果str2的长度大于str1,则会出现越界,因此为了保证代码的安全行,需要strncpy函数来限制字符串的长度。
7.strncpy的使用及实现
char * strncpy ( char * destination, const char * source, size_t num );
strncpy函数的功能是将source所指向的字符串中num个字符拷贝到destination所指向的字符串中
int main()
{
char str1[] = "#################";
char str2[] = "never give up";
my_strncpy(str1, str2, 14);
printf("%s\\n", str1);
return 0;
}
strncpy函数的实现也与strcpy类似:
char* my_strncpy(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* cp = dest;
while (num && (*cp++ = *src++))//将src字符串中的num个字符拷贝到cp中
{
num--;
}
while (num)//若num人大于0,则将cp中接下来的num个字符置为'\\0'
{
*cp++ = '\\0';
num--;
}
return dest;
}
8.strncmp的使用及实现
int strncmp ( const char * str1, const char * str2, size_t num );
strncmp顾名思义,就是比较str1和str2中前num个字符,比较规则与strcmp相同。
int main()
{
char str1[] = "never give up";
char str2[] = "never get mad";
int ret = my_strncmp(str1, str2, 7);
printf("%d\\n", ret);
return 0;
}
strncmp函数的实现与上面两个长度受限制的字符串函数类似:
int my_strncmp(const char* str1, const char* str2, size_t num)
{
assert(str1 && str2);
while (*str1 == *str2 && num)//str1与str2相等或num不为0是进入循环
{
str1++;
str2++;
num--;
if (*str2 == '\\0' || num == 0)//num等于0或str2与str1已比较完成说明二者相同,返回0
return 0;
}
if (*str1 > *str2)
return 1;
else
return -1;
}
9.strtok的使用
char * strtok ( char * str, const char * sep );
strtok函数是一个不怎么常见的库函数,它的作用是:
a)第一个参数指定一个字符串,该字符串包含了0个或多个有srp字符串中一个或者多个分割符分割的标记。
b)strtok函数找到str中的下一个标记,并将其用 \\0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
c)strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
d)strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
e)如果字符串中不存在更多的标记,则返回 NULL 指针。
上面还是有些抽象,下面用一段代码来介绍一下这个函数:
#include <string.h>
int main()
{
char str[] = "1506536196@qq.com";
char* sep = "@.";
char tmp[30];
char* cp = NULL;
strcpy(tmp, str);//将str拷贝一份到tmp中,避免strtok将str中的数据修改
for (cp = strtok(tmp, sep); cp; cp = strtok(NULL, sep))
{
printf("%s\\n", cp);
}
return 0;
}
第一次调用strtok函数时第一个参数传的是要分割的字符串,之后strtok函数会保留已经分割过的字符串因此第一个参数只需要传NULL即可,故使用strtok函数可以用一个for循环语句,初始化条件为将strtok返回的地址赋给接收的cp指针,结束条件为cp不为NULL,调整部分即为将NULL作为参数传给strtok函数,再将返回值赋给cp指针,for循环体内打印出被分割的字符串。
10.strerror的使用
char * strerror ( int errnum );
strerror函数的作用是:返回错误码所对应的错误信息。
# include <string.h>
# include <errno.h>
int main()
{
printf("%s\\n", strerror(0));
printf("%s\\n", strerror(1));
printf("%s\\n", strerror(2));
printf("%s\\n", strerror(3));
printf("%s\\n", strerror(4));
printf("%s\\n", strerror(5));
printf("%s\\n", strerror(6));
printf("%s\\n", strerror(7));
printf("%s\\n", strerror(8));
printf("%s\\n", strerror(9));
printf("%s\\n", strerror(10));
return 0;
}
strerror函数的应用在判断一些操作的错误类型时能起到很好的效果,比如在程序未达到预期的效果时,可以通过strerror来判断错误的原因,比如:
想打开text.txt文件时,没用达到预期效果,可以调用该函数来查找原因
以上是关于C语言常见字符串库函数的使用与实现的主要内容,如果未能解决你的问题,请参考以下文章