手撕字符串函数(C++面试必备)
strcpy()
函数功能:只能拷贝字符串,它遇到’\0’就结束拷贝。
char* strcpy(char* dst,const char* src) ;
#include<iostream>
#include<cstring>
#include<assert.h>
using namespace std;
char* strcpy(char* dst,const char* src)
{
assert(dst != NULL && src != NULL);
char *ret = dst;// 保存目标字符串的首地址
while ((*dst++ = *src++)!='\0');
return ret;
}
int main()
{
freopen("walk.out","w+",stdout);
char dst[100];
memset(dst,'\0',sizeof dst);
char src[66] = "Hello, World";
strcpy(dst, src);
cout<<dst;
return 0;
}
strcpy存在潜在的问题:内存重叠
若存在内存重叠,我们有如下写法:
char* strcpy(char* dst, char* src)//内存重叠
{
assert((dst != NULL && src != NULL));
char* ret = dst;
int size = strlen(src) + 1;
if (dst >= src && dst < src + size)//这个dst的内存在src的范围内,即出现可内存重叠
{
dst = dst + size - 1;
src = src + size - 1;
while (size--)
{
*dst-- = *src--;//将src的值从后向前赋值,赋给dst
}
}
else
{
while (size--)
{
*dst++ = *src++;
}
}
return ret;
}
memcpy()和memmove()
memcpy/memmove函数功能:内存拷贝,可拷贝任何数据类型的对象和指定拷贝的数据长度。memcpy对于需要复制的内容没有限制,下述也是memmove的实现。
#include<iostream>
#include<cstring>
using namespace std;
void *memcpy(void *dest, const void *src, size_t n) {
if (!dest || !src)
return NULL;
char *d = (char *) dest;
const char *s = (const char *) src;
if (d > s && d < s + n)
{
d = d + n - 1;
s = s + n - 1;
while (n--)
*d-- = *s--;
}
else
{
while (n--)
*d++ = *s++;
}
return dest;
}
int main()
{
//freopen("walk.out","w+",stdout);
const char src[50] = "http://www.runoob.com";
char dest[50];
memcpy(dest, src, strlen(src)+1);
cout<<dest;
return 0;
}
strcmp()
函数功能: 比较两个字符串,正数就是srt1大,负数就是srt2大,反之相等!
int strcmp(const char* str1,const char* str2) ;
int strcmp(const char* str1,const char* str2) {
while(*str1==*str2&&*str1!='\0') {
str1++;
str2++;
}
return *str1-*str2;
}
strcat()
函数作用:将src字符串追加到dest中。
char* strcat(char* dest,const char* src)
;
char* strcat(char* dest,const char* src) {
char* d = dest;
while(*d!='\0') ++d;
while(*src!='\0') {
*d++=*src++;
}
*d='\0';
return dest;
}
strsplit()
字符串分割函数
void split(vector<pair<const char *, size_t>> &a, const string &line, const char sep);
a为分割后的字符串数组,line为待分割字符串,sep为分割的依据
#include <iostream>
#include <cstring>
#include <vector>
#include <assert.h>
using namespace std;
void split(vector<pair<const char *, size_t>> &a, const string &line, const char sep)
{
const size_t size = line.size(); //需要分割的字符串
const char *str = line.c_str();
int l = 0, r = 0;
for (int i = 0; i < size; i++)
{
if (str[i] == sep) //按sep分割
{
a.push_back(make_pair(str + l, r)); //分割后的目标数组
l = i + 1;
r = 0;
}
else
{
r++;
}
}
if (r > 0) //假如右端点存在,且不为0
{
a.push_back(make_pair(str + l, r));
}
}
C++实现一个String类
String类包括构造函数,析构函数,拷贝构造函数,赋值运算符重载
实现如下:
#include<bits/stdc++.h>
using namespace std;
class String
{
public:
//构造函数
String(const char* str=""):_str(new char[strlen(str)+1])
{
strcpy(_str,str);
}
//析构函数
~String(){
delete[] _str;
_str=nullptr;
}
//拷贝构造函数
String(const String& s):_str(nullptr)
{
String tmp(s._str);
swap(_str, tmp._str);
}
//赋值运算符重载
String &operator=(const String s)
{
String tmp(s._str);
swap(_str,tmp._str);
return *this;
}
private:
char* _str;
};
分别用指针和引用交换两个数
代码实现如下:
#include<iostream>
using namespace std;
void swap(int *a,int *b) //指针交换两个数
{
int tmp=*a;
*a=*b;
*b=tmp;
}
void swap1(int &a,int &b) //引用交换两个数
{
int tmp=a;
a=b;
b=tmp;
}
int main()
{
int a=10,b=20;
int c=40,d=50;
swap(&a,&b);
swap1(c,d);
cout<<"a: "<<a<<", b: "<<b;
cout<<"\nc: "<<c<<", d: "<<d;
return 0;
}