C语言库函数探究

时间:2022-05-27 16:58:20

1、strlen()求字符串长度

 //模拟实现strlen函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
int my_strlen1(const char* str) //借助临时变量实现
{
int count = ;
while (*str++)
{
count++;
}
return count;
}
int my_strlen2(char* s)
{
char* p = s;
/*while (*p != '\0')
p++;*/
while (*p++);
return p - s - ;
}
int my_strlen3(char* str) //递归法
{
if (!*str)
return ;
else
return + my_strlen3(str + );
}
int main()
{
char src[] = "qwertyuiop";
int num1 = my_strlen1(src);
int num2 = my_strlen2(src);
int num3 = my_strlen3(src);
printf("%d\n", num1);
printf("%d\n", num2);
printf("%d\n", num3);
getchar();
return ;
}

2、strcpy()字符串拷贝函数

 char* my_strcopy1(char* dest, const char* str)
{
assert(dest != NULL);
assert(str != NULL);
char* ret = dest;
while (*dest++ = *str++)
{
;
}
return ret;
}
char* my_strcopy2(char* dest, const char* str)
{
assert(dest != NULL);
assert(str != NULL);
char* ret = dest;
while (*str != '\0')
{
*dest = *str;
dest++;
str++;
}
*dest = *str;
return ret;
}
int main()
{
char str[] = "abcdefg";
char dest1[];
char dest2[];
my_strcopy1(dest1, str);
my_strcopy2(dest2, str);
printf("%s\n", dest1);
printf("%s", dest2);
getchar();
return ;
}

(1)字符数组dest1和dest2必须定义得足够长,以容纳复制进去的字符串;

(2)与其相关的还有strncpy()函数定义拷贝固定长度的字符

 strncpy(str1, str2);

作用是将str2中前2个字符复制到str1中,取代str1中原有的前两个字符,N应不大于str1原字符长度(不包括‘\0’)。

3、strcmp()字符串比较函数

     int my_strcmp(const char *str1, const char *str2)
{
while (*str1 == *str2)
{
if (*str1 == '\0')
return ;
else
{
str1++;
str2++;
}
}
return (*str1 - *str2);
}
int main()
{ printf("%d\n", my_strcmp("awc", "aaaa")); //输出大于0的数
printf("%d\n", my_strcmp("ac", "aw")); //输出小于于0的数
printf("%d\n", my_strcmp("awc", "awc")); //输出0
printf("%d\n", strcmp("awc", "aaaa")); //输出1
printf("%d\n", strcmp("ac", "aw")); //输出-1
printf("%d\n", strcmp("awc", "awc")); //输出0
getchar();
return ;
}

4、strcat()字符串连接函数

 char *my_strcat(char *dest, const char *str)
{
char *ret = dest;
assert(dest != NULL);
assert(str != NULL);
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *str++)
{
;
}
return ret;
}
int main()
{
char arr[] = "abcdefg";
my_strcat(arr, "hit");
printf("%s\n", arr);
getchar();
return ;
}

5、strstr()找子串(模式匹配)

原型可以写成:char *my_strstr(const char *str, const char *substr)

(1)模式匹配是数据结构中字符串的一种基本运算,给定一个子串,要求在某个字符串中找出与该子串相同的所有子串,这就是模式匹配。
假设str是给定的子串,substr是待查找的字符串,要求从str中找出与substr相同的所有子串,这个问题成为模式匹配问题。str称为模式,substr称为目标。如果str中存在一个或多个模式为substr的子串,就给出该子串在str中的位置,称为匹配成功;否则匹配失败。
这种匹配方法可以解决问题,但是并不高效,最坏的情况下要匹配M*(N-M+1)次,时间复杂度为O(M*N)。比如下面的例子:
char str = "ababcababa";
char substr = "ababa";
C语言库函数探究

C语言库函数探究

C语言库函数探究

代码如下:

 char *my_strstr(const char *str, const char *dest)
{
const char *str1 = NULL;
const char *str2 = NULL;
const char *start = str;
assert(str);
assert(dest);
if (*dest == NULL)
{
return (char *)str;
}
while (*start)
{
str1 = start;
str2 = dest;
while ((*str1) && (*str2) && (*str1 == *str2))
{
str1++;
str2++;
}
if (*str2 == '\0')
{
return (char *)start;
}
start++;
}
return NULL;
}
int main()
{
char str1[] = "ababcababa";
char str2[] = "ababa";
char *ret = my_strstr(str1, str2);
if (ret != NULL)
printf("%s\n", ret);
else
printf("not exit!\n");
getchar();
return ;
}

(2)介绍另外一种方法,KMP算法

C语言库函数探究

这时,按第一种方法是,将目标串整个后移一位,再从头逐个比较。这样做虽然可行,但是效率很差,因为你要把"查找位置"移到已经比较过的位置,重比一遍。一个基本事实是,当 i=4,j=4 c与a不匹配时,你其实知道前面四个字符是"abab"。KMP算法的想法是,设法利用这个已知信息,不要把"查找位置"移回已经比较过的位置,继续把它向后移,这样就提高了效率。

C语言库函数探究

我们可以针对搜索词,算出一张《部分匹配表》如上表。这张表是如何产生的,后面会介绍,这里先看它的用法。

C语言库函数探究

已知c与a不匹配时,前面四个字符"abab"是匹配的。查表可知,最后一个匹配字符b对应的"部分匹配值"为0,因此按照下面的公式算出向后移动的位数:

 移动位数 = 已匹配的字符数 - 对应的部分匹配值

 4 - 0 等于4,所以将搜索词向后移动4位。

C语言库函数探究

因为a与c不匹配,搜索词还要继续往后移。这时,已匹配的字符数为0,对应的"部分匹配值"为0。所以后移一位

C语言库函数探究

逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果目标字符串后面还有,还要继续搜索的话(即找出全部匹配),移动位数 = 5 - 3,再将搜索词向后移动2位,这里就不再重复了。

下面介绍部分匹配值的算法:

C语言库函数探究

上图中后缀是从后往前看的,写成正序应为: a, ba, aba, baba 最后一个a不算在内。

"部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ababa"为例:

- "a"的前缀和后缀都为空集,共有元素的长度为0;

- "ab"的前缀为[a],后缀为[b],共有元素的长度为0;

- "aba"的前缀为[a, ab],后缀为[ba, a],共有元素的长度1;

- "abab"的前缀为[a, ab, aba],后缀为[bab, ab, b],共有元素的长度为2;

- "ababa"的前缀为[a, ab, aba, abab],后缀为[baba, aba, ba, a],共有元素为"aba",长度为3;

next数组的求解思路(即部分匹配值)

通过上文完全可以对kmp算法的原理有个清晰的了解,那么下一步就是编程实现了,其中最重要的就是如何根据待匹配的模版字符串求出对应每一位的最大相同前后缀的长度。

 void makeNext(const char* str,int next[])
{
int num,max;//num:模版字符串下标;max:最大前后缀长度
int len = strlen(str);//模版字符串长度
next[] = ;//模版字符串的第一个字符的最大前后缀长度为0
for (num = ,max = ; num < len; ++num)//for循环,从第二个字符开始,依次计算每一个字符对应的next值
{
while(max > && str[num] != str[max])//递归的求出dest[0]···dest[n]的最大的相同的前后缀长度max
max = next[max - ];
if (str[num] == str[max])//如果相等,那么最大相同前后缀长度加1
{
max++;
}
next[num] = max;
}
}
 int kmp(const char str[],const char dest[],int next[])
{
int slen, dlen;
int i,n;
slen = strlen(str); //长字符串的长度
dlen = strlen(dest); //目标字符串长度
makeNext(dest,next);
for (i = ,n = ; i < slen; ++i)
{
while(n > && dest[n] != str[i])
n = next[n-]; //目标字符串下标n回退
if (dest[n] == str[i])
{
n++;
}
if (n == dlen) //找到目标串,返回目标串起始下标
{
printf("Pattern occurs with shift:%d\n",(i - dlen + ));
}
}
} int main()
{
int i;
int next[]={};
char str[] = "ababxbababcadfdsss";
char dest[] = "abcdabd";
printf("%s\n",str);
printf("%s\n",dest);
// makeNext(dest, next);
kmp(str, dest, next);
for (i = ; i < strlen(dest); ++i)
{
printf("%d ",next[i]);
}
printf("\n"); return ;
}

KMP算法的时间复杂度为O(m+n);空间复杂度为O(n)。

6、strlwr将字符串中的字符转换为小写

原型为:char *strlwr(char *str);

参数说明:str为要转换的字符串。
返回值:返回转换后的小写字符串,其实就是将str返回。
 strlwr() 不会创建一个新字符串返回,而是改变原有字符串。所以strlwr()只能操作字符数组,而不能操作指针字符串,因为指针指向的字符串是作为常量保存在静态存储区的,常量不能被修改
注意:strlwr()和不是标准库函数,只能在windows下(VC、MinGW等)使用,Linux
GCC中需要自己定义。

  char* my_strlwr(char *str)
{
assert(str);
char* start = str;
while (*start)
{
if (*start >= 'A' && *start <= 'Z')
*start += ;
start++;
}
return str;
}
char* my_strupr(char *str)
{
assert(str);
char* start = str;
while (*start)
{
if (*start >= 'a' && *start <= 'z')
*start -= ;
start++;
}
return str;
}
int main()
{
char str1[] = { "ABCDCFbbbdgeJhssW" }; printf("%s\n", my_strlwr(str1)); //调用该函数,并且输出新的字符串
printf("%s\n", my_strupr(str1)); //调用该函数,并且输出新的字符串
getchar();
return ;
}

7、memcpy内存拷贝函数

函数原型:void *memcpy(void *dest, const void *src, size_t n);

功能:从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

返回值:函数返回指向dest的指针。

说明:1.source和destin所指的内存区域可能重叠,但是如果source和destin所指的内存区域重叠,那么这个函数并不能够确保source所在重叠区域在拷贝之前不被覆盖。而使用memmove可以用来处理重叠区域。函数返回指向destin的指针。

2.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
注意:source和destin都不一定是数组,任意的可读写的空间均可。
 void *my_memcpy(void *dest, const void *str, int sz)
{
int i = ;
char *pdest = (char *)dest;
char *pstr = (char *)str;
assert(dest);
assert(str);
for (i = ; i < sz; i++)
{
*pdest = *pstr;
pdest++;
pstr++;
}
return dest;
}
int main()
{
int i = ;
int arr1[] = { , , , , , , , };
int arr2[];
my_memcpy(arr2,arr1,*sizeof(int));
for (i = ; i < sizeof(arr2) / sizeof(arr2[]); i++)
{
printf("%d\n", arr2[i]);
}
getchar();
return ;
}

8、memmove内存拷贝函数

函数原型:void *memmove(void *dest, const void *src, size_t n);

描述:memmove() 函数从src内存中拷贝n个字节到dest内存区域,但是源和目的的内存可以重叠。
返回值:memmove函数返回一个指向dest的指针。
它和memcpy唯一区别就是在对待重叠区域的时候,memmove可以正确的完成对应的拷贝,而memcpy不能。

内存覆盖的情形主要有以下两种:
C语言库函数探究
 #include<stdio.h>
#include<string.h>
#include<assert.h>
void *my_memmove(void *dest, const void *str, int count)
{
char *pdest = (char *)dest;
const char *pstr = (char *)str;
assert(pdest);
assert(pstr);
if (pdest > pstr)
{
while (count--)
{
*(pdest + count) = *(pstr + count);
}
}
else
{
while (count--)
{
*pdest = *pstr;
pdest++;
pstr++;
}
}
return dest;
} int main()
{
int i = ;
int arr[] = { , , , , , , , , , };
my_memmove(arr + , arr + , * sizeof(int));
for (i = ; i < sizeof(arr) / sizeof(arr[]); i++)
{
printf("%d\n", arr[i]);
}
getchar();
return ;
}

赐教!

C语言库函数探究的更多相关文章

  1. C语言库函数--操作文件

    //C库函数读取文件的代码 I/O缓冲机制 C语言库函数写文件都是写在内存中,然后一次写入磁盘.提高了效率. 读写文件,不对系统进行操作,一般采用C语言库函数.移植可以在任何可以对C支持的操作系统,而 ...

  2. C语言库函数大全及应用实例十四

    原文:C语言库函数大全及应用实例十四                                       [编程资料]C语言库函数大全及应用实例十四 函数名: strset 功 能: 将一个串 ...

  3. C语言库函数大全及应用实例十三

    原文:C语言库函数大全及应用实例十三                                          [编程资料]C语言库函数大全及应用实例十三 函数名: stat 功 能: 读取打 ...

  4. C语言库函数大全及应用实例十一

    原文:C语言库函数大全及应用实例十一                                         [编程资料]C语言库函数大全及应用实例十一 函数名: setbkcolor 功 能 ...

  5. C语言库函数大全及应用实例十二

    原文:C语言库函数大全及应用实例十二                                          [编程资料]C语言库函数大全及应用实例十二 函数名: setrgbpalette ...

  6. C语言库函数大全及应用实例十

    原文:C语言库函数大全及应用实例十                                             [编程资料]C语言库函数大全及应用实例十 函数名: qsort 功 能: 使 ...

  7. C语言库函数大全及应用实例九

    原文:C语言库函数大全及应用实例九                                                [编程资料]C语言库函数大全及应用实例九 函数名: mktemp 功 ...

  8. C语言库函数大全及应用实例八

    原文:C语言库函数大全及应用实例八                                            [编程资料]C语言库函数大全及应用实例八 函数名: kbhit 功 能: 检查 ...

  9. C语言库函数大全及应用实例七

    原文:C语言库函数大全及应用实例七 [编程资料]C语言库函数大全及应用实例七 函数名: getw 功 能: 从流中取一整数 用 法: int getw(FILE *strem); 程序例: #i nc ...

随机推荐

  1. Sqrtx

    我只能想出二分的方法,而且还不一定能写出最简洁的代码.无论刷多少遍,牛顿迭代法我都想不到,莫名有种悲哀的感觉:智力是硬伤啊.就算如此,却还要一遍遍不厌其烦地刷,这才是最悲剧的.多说无益,上代码. 二分 ...

  2. Effective C&plus;&plus; -----条款40:明智而审慎地使用多重继承

    多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. virtual继承会增加大小.速度.初始化(及赋值)复杂度等等成本.如果virtual base classes不带任何 ...

  3. Xutils 源码解析【转】

    原文:http://my.oschina.net/u/1538627/blog/395098 目录[-] 1. 功能介绍 2. 详细设计 2.1 View模块 2.1.1 总体设计 2.1.2 流程图 ...

  4. select的使用(一)

    单表操作 select Name,Major,InDate from T_Employee as 计算结果 select Name as 姓名,Major,InDate from T_Employee ...

  5. 读headFirst设计模式 - 装饰者模式

    继承可以在复用父类代码的情况下扩展父类的功能,但同时继承增加了对象之间的耦合度,所以要慎用继承.那么有没有既能扩展父类的功能,又能使对象间解耦的方法呢?答案是肯定的,这就是我们今天要学习的装饰者模式. ...

  6. mayavi安装

    Mayavi是python的一个包,提供方便的可视化方案.目前(20150809)Mayavi还没有py3的支持,以下安装环境在python 2.7.10下进行 安装Mayavi: 1. 通过pip ...

  7. Linux 帳號管理與 ACL 權限設定

    1. Linux 的账号与群组1.1 使用者识别: UID 与 GID1.2 使用者账号:/etc/passwd, /etc/shadow1.3 关于群组: 有效与初始群组. groups, newg ...

  8. hibernate框架学习之数据查询(QBC)helloworld

    package cn.itcast.h3.query.hql; import java.util.List; import org.hibernate.Criteria; import org.hib ...

  9. &lbrack;py&rsqb;&lbrack;mx&rsqb;django实现课程机构排名

    如果是第一次做这个玩意,说实话,确实不知道怎么弄, 做一次后就有感觉了 此前我们已经完成了: 分类筛选 分页 这次我们做的是 课程机构排名 知识点: - 按照点击数从大到小排名, 取出前三名 hot_ ...

  10. python windows打包

    接触过的工具有pyinstaller,或者py2exe.感觉pyinstaller更简单易用. 真正将依赖的dll打包称一个安装包还需要借助windows打包工具 Inno Setup 或 NSIS ...