文章目录
- 字符串拓展函数
- strncpy
- strncat
- strncmp
- strstr
- strtok
- strerror
- memcpy
- memmove
- memcmp
- memset
- 库函数模拟实现
- memmove
- qsort
我们在学习C语言时已经学习了一些常见的字符串函数,但这还不能满足我们的需求,为此我们拓展了几个常用的字符串函数。
字符串拓展函数
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 );
该函数将源字符串前num个字符追加到目标空间中,追加完后自动在目标字符串后加上‘\0’,如果num大于源字符串的长度,最多也只会将源字符串全部追加到目标字符串后面。
strncmp
函数原型为:
int strncmp ( const char * str1, const char * str2, size_t num );
用于两个字符串的比较,比较到出现两个字符不一样或其中一个字符串结束或num个字符全部比完,
其返回值的含义为:
strstr
函数原型为:
const char * strstr ( const char * str1, const char * str2 );
该函数用于查找在str1中是否出现了str2,如果有,返回str2在str1中第一次出现的地址,否则返回空指针。
strtok
函数原型为:
char * strtok ( char * str, const char * delimiters );
· delimiters参数是个字符串,定义了用作分隔符的字符集合
· 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
· strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
· strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
· strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
· 如果字符串中不存在更多的标记,则返回 NULL 指针。
从加粗部分我们可以知道strtok函数具有记忆功能,因此我们若想将字符串分为多部分,第一次调用strtsr函数时str传非空指针,后面都要传空指针,直至分割完毕。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This,a sample/string.";
char * pch;
pch = strtok (str,",/");//第一次传非空
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ",/");//后面都传空指针
}
return 0;
}
输出结果为:
This
a simple
string.
strerror
函数原型为:
char * strerror ( int errnum );
该函数会返回错误码所对应的错误信息,可以通过printf函数将错误信息打印出来。
库函数在执行过程中发生了错误会将错误码放在errnum这个变量中,该变量是C语言提供的全局变量,记录最后一次错误信息的错误码,因此要包含头文件<errno.h>。
memcpy
函数原型为:
void * memcpy ( void * destination, const void * source, size_t num );
该函数是将souce开始的num个字节的内容拷贝到destination中,换言之,memcpy是对内存进行拷贝,而不只是单单拷贝字符串那么简单。这也意味着如果destination和source存在内存重叠,那么拷贝的内容是不确定的。
memmove
函数原型为:
void * memmove ( void * destination, const void * source, size_t num );
memmove函数是对memcpy函数的改进,解决了源内存块和目标内存块的内存不能重叠的问题。
memcmp
函数原型为;
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
用于比较ptr1和ptr2指针开始的num个字节
其返回值为:
memset
函数原型为:
void * memset ( void * ptr, int value, size_t num );
该函数用于将ptr开始的num个字节全部设为value,要注意是以一个字节为单位的。
库函数模拟实现
memmove
void * memmove ( void * destination, const void * source, size_t num );
要实现memmove函数,主要是解决内存重叠的问题。
我们的解决办法是:由拷贝字节大小和比较源空间与目标空间起始地址的大小来决定我们是选择从前往后还是从后往前拷贝内存。
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
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);
}
qsort
可以对任意可以进行比较的数据进行排序
函数原型为:
qsort
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
相关参数介绍:
假如我们要对一个数组排升序,可以这样用:
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int values[] = { 40, 10, 100, 90, 20, 25 };
qsort (values, 6, sizeof(int), compare);
return 0;
}
这里为了简便,选择冒泡排序进行模拟:
#include <stdio.h>
int int_cmp(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}
void _swap(void *p1, void * p2, int size)
{
int i = 0;
for (i = 0; i< size; i++)
{
char tmp = *((char *)p1 + i);
*(( char *)p1 + i) = *((char *) p2 + i);
*(( char *)p2 + i) = tmp;
}
}
void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{
int i = 0;
int j = 0;
for (i = 0; i< count - 1; i++)
{
for (j = 0; j<count-i-1; j++)
{
if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)
{
_swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
}
}
}
}
由于其他函数的模拟比较容易实现,这里就不在一一进行模拟实现。至此,本文已经结束。