常用字符串函数原理及实现
2017-04-20 10:11
465 查看
1.函数名称: void* memchr_m(const void* buffer, int ch, int count)
函数说明:字符串函数实现,防止memchr函数重载,定义为memchr_m函数
在buffer指向的数组的count个字符的字符串里查找ch 首次出现的位置。int ch表示字符对应的ascii
返回一个指针,指向ch 在字符串中首次出现的位置, 如果ch 没有在字符串中找到,返回NULL。#include<iostream>
#include<assert.h>
using namespace std;
void* memchr_m(const void* buffer, int ch, int count)
{
assert(NULL != buffer);
char*p = (char*)buffer;
while (*p!='\0' && count--)
{
if (*p == (char)ch)
return (void*)p;
p++;
}
return NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
char a[] = "pengpeng has a nice mood!";
char *p;
p = (char*)memchr_m(a, 'm', 100);
//p = (char*)memchr_m(a, 'x', 100);
if (p != NULL)
{
cout << "Find!" << endl;
cout << p << endl;
}
else
{
cout << "Not Find!" << endl;
}
getchar();
return 0;
}
2.函数名称: strstr(s1,s2)
函数说明:用于在字符串中查找子串,函数返回s2在s1中第一次出现的字符串地址,若s1中没有找到s2,返回NULL,若s2为空,则返回s1.
3. 函数名称:char *strchr(const char *s, char c);
函数说明:查找字符串s中首次出现字符c的位置
返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL。
Linux下实现:
思路:
检测字符串安全性,s2为空果断抛弃之。
s1逐个递增,并与s2整串比较内存大小,判断字串是否相等。相等则返回s1,否则s1++,再执行比较。
最后返回空值,代表未找到相符的串
关于memcmp的实现见函数 7
4. 函数名称:char* strcpy_m(char*dst ,const char* src)
函数说明:字符串复制
说明1:const修饰,源字符串参数用const修饰,防止修改源字符串。
说明2:空指针检查, assert(src!=NULL) 增加健壮性、如果拼写错误编译器就会查出来
说明3:返回目标地址,要返回char * ,返回dst的原始值使函数能够支持链式表达式。
链式表达式的形式如:int l = strlen(strcpy(strA, strB));
说明4: 循环写成while(*src != '\0') *dst++ = *src++;
循环体结束后,dst字符串的末尾没有正确地加上'\0'.
说明5:char s[10]="hello";strcpy(s, s + 1); //应返回ello,
strcpy(s+1, s); //应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了
所谓重叠,就是src未处理的部分已经被dst给覆盖了,只有一种情况:src <= dst <= src + strlen(src)
C函数memcpy自带内存重叠检测功能,下面给出memcpy的实现my_memcpy。
5.函数名称:void *memcpy_m(void *dst, const void* src, int cnt);
函数说明:从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
由以上很简单可以给出:
6.函数名称:char* strncpy(char* dst, const char* src, int n)
函数说明:把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。
注意提前结束即遇到'\0'和n个长度字节数据复制结束的情况
7.函数名称:int memcmp(const void *cs, const void *ct, size_t count)
函数说明:比较内存区域参数cs和 ct的前count个字节。
当cs<ct时,返回值小于0;当cs==ct时,返回值=0;当cs>ct时,返回值大于0;
Linux类似实现:
首先看看3个函数的功能:
1、strcmp(const char * a1,const char *a2)
用来比较a1和a2两个字符串(按ASCII值大小相比较),注意点是这个函数只能用来比较字符串
当a1<a2时候,返回的值<0
当a1>a2时候,返回的值>0
当a1=a2时候,返回的值=0
2、strncmp(const char * a1,const char *a2,int maxlen)
与上面的函数类似),用来比较a1和a2两个字符串的,但是之比较两个字符串的钱maxlen长度的字符串
当a1<a2时候,返回的值<0
当a1>a2时候,返回的值>0
当a1=a2时候,返回的值=0
3、int memcmp (const void *a1, const void *a2, size_t size)
原型是:extern int memcmp(void *buf1, void *buf2, unsigned int count);
功能上来说是比较a1和a22个buff内的前size个字节,如果相同返回的结果是0
1、strcmp是按照字节比较的,如果出现"\0"的情况会终止比较;
2、memcmp 用来比较内存块的内容是否一致,不常用于字节的比较,中包含一些由于边界对齐需求而填入结构对象中的空格、联合 (union)结束的额外空格、字符串所分配的空间未使用完的部分引起的“holes”的话,最好使用memcmp来完成,这些“holes”的内容是不确定的,在执行byte-wise比较时结果也是不明确的;
3、strcmp比较的字符串,而memcmp比较的是内存块,strcmp需要时刻检查是否遇到了字符串结束的 \0 字符,而memcmp则完全不用担心这个问题,所以memcmp的效率要高于strcmp
8. 字符串转换int
int转换为字符串
void int2str(int n, char *str){
char buf[10] = "";
int i = 0;
int len = 0;
int temp = n < 0 ? -n : n; // temp为n的绝对值
if (str == NULL){
return;
}
while (temp){
buf[i++] = (temp % 10) + '0'; //把temp的每一位上的数存入buf
temp = temp / 10;
}
len = n < 0 ? ++i : i; //如果n是负数,则多需要一位来存储负号
str[i] = 0; //末尾是结束符0
while (1){
i--;
if (buf[len - i - 1] == 0){
break;
}
str[i] = buf[len - i - 1]; //把buf数组里的字符拷到字符串
}
if (i == 0){
str[i] = '-'; //如果是负数,添加一个负号
}
}
函数说明:字符串函数实现,防止memchr函数重载,定义为memchr_m函数
在buffer指向的数组的count个字符的字符串里查找ch 首次出现的位置。int ch表示字符对应的ascii
返回一个指针,指向ch 在字符串中首次出现的位置, 如果ch 没有在字符串中找到,返回NULL。#include<iostream>
#include<assert.h>
using namespace std;
void* memchr_m(const void* buffer, int ch, int count)
{
assert(NULL != buffer);
char*p = (char*)buffer;
while (*p!='\0' && count--)
{
if (*p == (char)ch)
return (void*)p;
p++;
}
return NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
char a[] = "pengpeng has a nice mood!";
char *p;
p = (char*)memchr_m(a, 'm', 100);
//p = (char*)memchr_m(a, 'x', 100);
if (p != NULL)
{
cout << "Find!" << endl;
cout << p << endl;
}
else
{
cout << "Not Find!" << endl;
}
getchar();
return 0;
}
2.函数名称: strstr(s1,s2)
函数说明:用于在字符串中查找子串,函数返回s2在s1中第一次出现的字符串地址,若s1中没有找到s2,返回NULL,若s2为空,则返回s1.
char* strstr_m(const char *s1, const char *s2) { if (*s2 == '\0') /*如果s2为空,则返回s1*/ return ((char *)s1); for (; s1 != '\0'; ++s1) /*每次后移s1的位置,在新的位置进行下一次匹配*/ { const char *sc1, *sc2; while ((*s1 != *s2) && (*s1 != '\0')) ++s1; /*在s1中找到和s2第一个字符匹配的位置*/ if (*s1 == '\0') /*如果找不到,说明s1现在的位置不匹配,退出循环进行下一次匹配*/ break; else /*如果找到和s2第一个字符匹配的位置,开始逐个匹配s2后面的字符*/ for (sc1 = s1, sc2 = s2; sc1 != '\0'; ++sc1, ++sc2) { if (*sc2 == '\0') /*如果匹配完毕,返回s1此时的位置*/ return ((char *)s1); else if (*sc1 != *sc2) /*如果后面有一个字符不匹配,说明s1现在的位置不匹配,退出循环进行下一次匹配*/ break; } } return (NULL); } int _tmain(int argc, _TCHAR* argv[]) { char *s = "1233345hello"; char *sub = "333435"; const char *p = strstr_m(s, sub); if (NULL != p) printf("%s\n", p); else printf("can find the matching str\n"); getchar(); return 0; }
3. 函数名称:char *strchr(const char *s, char c);
函数说明:查找字符串s中首次出现字符c的位置
返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL。
char* strchr_m(const char*s, char c) { assert(s != NULL); while (*s != '\0') { if (*s == c) return (char*)s; s++; } return NULL; } int _tmain(int argc, _TCHAR* argv[]) { char *s = "1233345hello"; char ch = '5'; const char *p = strchr_m(s, ch); if (NULL != p) printf("%s\n", p); else printf("can find the matching str\n"); getchar(); return 0; }
Linux下实现:
思路:
检测字符串安全性,s2为空果断抛弃之。
s1逐个递增,并与s2整串比较内存大小,判断字串是否相等。相等则返回s1,否则s1++,再执行比较。
最后返回空值,代表未找到相符的串
char *strstr(const char *s1, const char *s2) { size_t l1, l2; l2 = strlen(s2); if (!l2) return (char *)s1; l1 = strlen(s1); while (l1 >= l2) { l1--; if (!memcmp(s1, s2, l2)) return (char *)s1; s1++; } return NULL; }
关于memcmp的实现见函数 7
4. 函数名称:char* strcpy_m(char*dst ,const char* src)
函数说明:字符串复制
char* strcpy_m(char* dst, const char* src) { assert(dst != NULL && src != NULL); char *ret = dst; while ((*dst++ = *src++) != '\0'); //或者改为 while((*dst=*src)!='\0') return ret; //{ dst++; src++} }
说明1:const修饰,源字符串参数用const修饰,防止修改源字符串。
说明2:空指针检查, assert(src!=NULL) 增加健壮性、如果拼写错误编译器就会查出来
说明3:返回目标地址,要返回char * ,返回dst的原始值使函数能够支持链式表达式。
链式表达式的形式如:int l = strlen(strcpy(strA, strB));
说明4: 循环写成while(*src != '\0') *dst++ = *src++;
循环体结束后,dst字符串的末尾没有正确地加上'\0'.
说明5:char s[10]="hello";strcpy(s, s + 1); //应返回ello,
strcpy(s+1, s); //应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了
所谓重叠,就是src未处理的部分已经被dst给覆盖了,只有一种情况:src <= dst <= src + strlen(src)
C函数memcpy自带内存重叠检测功能,下面给出memcpy的实现my_memcpy。
char * strcpy_m2(char *dst, const char *src) { assert(dst != NULL && src != NULL); char *ret = dst; memcpy_m(dst, src, strlen(src) + 1); return ret; }
5.函数名称:void *memcpy_m(void *dst, const void* src, int cnt);
函数说明:从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
void *memcpy_m(void *dst, const void* src, int cnt) { assert(dst != NULL && src != NULL); void *ret = dst; if (dst >= src && (char*)dst <=(char*) src + cnt - 1) //内存重叠,从高地址开始复制 { dst = (char*)dst + cnt - 1; src = (char*)src + cnt - 1; while (cnt--) { *(char*)dst = *(char*)src; dst = (char*)dst - 1; src = (char*)src - 1; } } else //正常情况,从低地址开始复制 无重叠 dst<=src { while (cnt--) { *(char*)dst = *(char*)src; dst = (char*)dst + 1; src = (char*)src + 1; } } return ret; }
由以上很简单可以给出:
6.函数名称:char* strncpy(char* dst, const char* src, int n)
函数说明:把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。
注意提前结束即遇到'\0'和n个长度字节数据复制结束的情况
char* strncpy_m(char* dst, const char* src, int n) { assert(dst != NULL && src != NULL); char*ret = dst; while ((n--) && (*dst++ = *src++) != '\0') { if (n == 0) *dst = '\0'; break; } return ret; } //或者修改为 char* strncpy_m2(char* dst, const char* src, int n) { assert(dst != NULL && src != NULL); char*ret = dst; while ((n--) && (*dst++ = *src++) != '\0'); if (n < 0) *dst = '\0'; return ret; }
7.函数名称:int memcmp(const void *cs, const void *ct, size_t count)
函数说明:比较内存区域参数cs和 ct的前count个字节。
当cs<ct时,返回值小于0;当cs==ct时,返回值=0;当cs>ct时,返回值大于0;
Linux类似实现:
int memcmp(const void *cs, const void *ct, size_t count) { const unsigned char *su1, *su2; int res = 0; for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) if ((res = *su1 - *su2) != 0) break; return res; }
int strcmp(const char *cs, const char *ct) { signed char __res; while (1) { if ((__res = *cs - *ct++) != 0 || !*cs++) //比较到结束符\0,时,已经做了__res = *cs - *ct了,但是此时*cs和*ct的值都为\0,所以返回肯定为0 break; } return __res; }
/* *strncmp - Compare two length - limited strings * @cs: One string * @ct : Another string * @count : The maximum number of bytes to compare * / int strncmp(const char *cs, const char *ct, size_t count) { signed char __res = 0; while (count) { if ((__res = *cs - *ct++) != 0 || !*cs++) //比较到结束符\0,时,已经做了__res = *cs - *ct了,所以不等长度时,肯定返回不为0 break; count--; } return __res; }
首先看看3个函数的功能:
1、strcmp(const char * a1,const char *a2)
用来比较a1和a2两个字符串(按ASCII值大小相比较),注意点是这个函数只能用来比较字符串
当a1<a2时候,返回的值<0
当a1>a2时候,返回的值>0
当a1=a2时候,返回的值=0
2、strncmp(const char * a1,const char *a2,int maxlen)
与上面的函数类似),用来比较a1和a2两个字符串的,但是之比较两个字符串的钱maxlen长度的字符串
当a1<a2时候,返回的值<0
当a1>a2时候,返回的值>0
当a1=a2时候,返回的值=0
3、int memcmp (const void *a1, const void *a2, size_t size)
原型是:extern int memcmp(void *buf1, void *buf2, unsigned int count);
功能上来说是比较a1和a22个buff内的前size个字节,如果相同返回的结果是0
比较:
1、strcmp是按照字节比较的,如果出现"\0"的情况会终止比较;2、memcmp 用来比较内存块的内容是否一致,不常用于字节的比较,中包含一些由于边界对齐需求而填入结构对象中的空格、联合 (union)结束的额外空格、字符串所分配的空间未使用完的部分引起的“holes”的话,最好使用memcmp来完成,这些“holes”的内容是不确定的,在执行byte-wise比较时结果也是不明确的;
3、strcmp比较的字符串,而memcmp比较的是内存块,strcmp需要时刻检查是否遇到了字符串结束的 \0 字符,而memcmp则完全不用担心这个问题,所以memcmp的效率要高于strcmp
8. 字符串转换int
int str2int(const char *str){ int temp = 0; const char *ptr = str; //ptr保存str字符串开头 if (*str == '-' || *str == '+'){//如果第一个字符是正负号, str++; //则移到下一个字符 } while (*str != 0){ if ((*str < '0') || (*str > '9')){//如果当前字符不是数字 break; //则退出循环 } temp = temp * 10 + (*str - '0'); //如果当前字符是数字则计算数值 没有考虑溢出 str++; //移到下一个字符 } if (*ptr == '-'){ //如果字符串是以“-”开头,则转换成其相反数 temp = -temp; } return temp; }
int转换为字符串
void int2str(int n, char *str){
char buf[10] = "";
int i = 0;
int len = 0;
int temp = n < 0 ? -n : n; // temp为n的绝对值
if (str == NULL){
return;
}
while (temp){
buf[i++] = (temp % 10) + '0'; //把temp的每一位上的数存入buf
temp = temp / 10;
}
len = n < 0 ? ++i : i; //如果n是负数,则多需要一位来存储负号
str[i] = 0; //末尾是结束符0
while (1){
i--;
if (buf[len - i - 1] == 0){
break;
}
str[i] = buf[len - i - 1]; //把buf数组里的字符拷到字符串
}
if (i == 0){
str[i] = '-'; //如果是负数,添加一个负号
}
}
相关文章推荐
- 【经验总结】C#常用线程同步方法应用场景和实现原理
- 常用字符串函数实现(面试题)
- Atitit.数据索引 的种类以及原理实现机制 索引常用的存储结构
- 常用RAID级别原理和Linux中软RAID实现方式
- 常用的两种web单点登录SSO的实现原理
- Taglib原理和实现 第六章:标签内常用方法总结
- 自己编写代码实现常用字符串函数的功能
- 实现字符串的一些常用字符串函数
- iOS-本地推送和远程推送,常用的三方推送和常用的测试方法,推送实现和原理详解
- 推荐系统的常用算法原理和实现
- 【经验总结】C#常用线程同“.NET研究”步方法应用场景和实现原理
- tomcat以及常用web容器线程池的实现原理
- C#常用的CRUD操作实现原理
- 模拟实现常用字符串函数
- C语言标准库string.h中常用的字符串函数的实现
- 一起谈.NET技术,【经验总结】C#常用线程同步方法应用场景和实现原理
- sqlserver中实现split分割字符串函数常用的
- C语言常用字符串函数的实现一
- Atitit.数据索引 的种类以及原理实现机制 索引常用的存储结构
- 模拟实现常用字符串函数