《王道程序员求职宝典》第二章、字符串

pdf地址:https://blog.csdn.net/qq_23905237/article/details/93722388

第二章、字符串

1.c风格字符串:没啥好说的

2.一些标准库提供的字符串处理函数

strlen函数:

自定义函数实现strlen的功能:

#include <iostream>
#include <assert.h>
#include <string.h>
using namespace std;

int strlen_1(const char *str)
{
	assert(str != NULL);
	int len = 0;
	while(*(str++) != '\0')
		len++;
	return len;
}

int strlen_2(const char *str)
{
	assert(str != NULL);
	return *str == '\0' ? 0 : (1 + strlen_2(++str));
}

int main()
{
	char *a = "hhh";
	cout << strlen_1(a) << endl;
	cout << strlen_2(a) << endl;
	return 0;
}

n = 4    x[4] == '\0'  *x = '\0' x++

所以就显而易见了

strcmp函数:

自定义实现:

int strcmp(const char *str1, const char *str2)
{
	assert(str1 != NULL && str2 != NULL)
	int ret = 0;
	while(!(ret = *(unsigned char *)str1 - *(unsigned char *)str2) && *str1)
	{
		str1++;
		str2++;
	}
	if(ret < 0)
		ret = -1;
	else
		ret = 1;
	return ret;
}

strcat和strcpy函数:

自定义实现strcat:

char *strcat(char *strDest, const char *strSrc)
{
	char *adr = strDest;
	assert(strDest != NULL && strSrc != NULL);
	while(*strDest)
	{
		strDest++;
	}
	while(*strDest++ = *strSrc++);
	return adr;
}

自定义实现strcpy:

char *strcpy(char *strDest, const char *strSrc)
{
	assert(strDest != NULL && strSrc != NULL);
	char *adr = strDest;
	while((*strDest++ = *strSrc++) != '\0'))
	return adr;
}

memcpy函数:

void *memcpy(void *dest, const void *src, size_t n);

请简述strcpy和memcpy的区别?

1).复制的内容不同,strcpy只能复制字符串,而memcpy能够复制任意内容。

2).strcpy不需要指定长度。

3)用途不同

memset函数:

void *memset(void *s, int ch, size_t n);

2.字符串的包含问题

1)串的模式匹配算法:查找子串

使用最基础的算法(BF算法)

char *strFind(const char *str, const char *substr)
{
	assert(str != NULL && substr != NULL);
	int m = strlen(str);
	int n = strlen(substr);
	if(m < n)
		return NULL;
	for(int i = 0; i <= m - n; i++)
	{
                int j = 0;
		for(; j < n; j++)
		{
			if(str[i + j] != substr[j])
				break;
		}
		if(j == n)
			return str + i;
	}
	return NULL;
}

KMP算法:

原理参考:http://www.cnblogs.com/SYCstudio/p/7194315.html

算法复杂度为O(M+N)

//计算next数组的函数
void get_nextval(char const *ptrn, int plen, int *nextval)
{
	int i = 0;
	nextval[i] = -1;
	int j = -1;
	while(i < plen - 1)
	{
		if(j == -1 || ptrn[i] == ptrn[j])
		{
			++i;
			++j;
			nextval[i] = j;
		}
		else
		{
			j = nextval[j];
		}
		
	}
}

//改进的计算next数组的函数
void get_nextval(char const *ptrn, int plen, int nextval)
{
	int i = 0;
	nextval[i] = -1;
	int j = -1;
	while(i < plen - 1)
	{
		if(j == -1 || ptrn[i] == ptrn[j])
		{
			++i;
			++j;
			if(ptrn[i] != ptrn[j])
				nextval[i] = j;
			else
			{
				nextval[i] = nextval[j];
			}
		}
		else
		{
			j = nextval[j];
		}	
	}
}

int kmp_search(const char *src, int slen, const char *patn, int plen, const int  *nextval, int pos)
{
	int i = pos, j = 0;
	while(i < slen && j < plen)
	{
		if(j == -1 || src[i] == patn[j])
		{
			++i;
			++j;
		}
		else
		{
			j = nextval[j]; //当匹配失败时直接用p[j_next]与s[i]比较
		}
	}
	if(j >= plen)
		return i - plen;
	else
		return -1;	
}

3.字符串的移位包含问题:

其实就是s1s1中求是否包含s2

4.字符串转换为数字

atoi函数 itoa函数

#include <stdlib.h>

int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
long long atoq(const char *nptr);
char *itoa( int value, char *string,int radix);

以及c++11

std::string to_string(int value);
std::string to_string(long int value);
std::string to_string(long long int value);
std::string to_string(unsigned int value);
std::string to_string(unsigned long long int value);
std::string to_string(float value);
std::string to_string(double value);
std::wstring to_wstring(int value);
std::wstring to_wstring(long int value);
std::wstring to_wstring(long long int value);
std::wstring to_wstring(unsigned int value);
std::wstring to_wstring(unsigned long long int value);
std::wstring to_wstring(float value);
std::wstring to_wstring(double value);
std::string str = "1000";
int val = std::stoi(str);
long val = std::stol(str);
float val = std::stof(str);
atoi: 将字符串转换为 int
atol: 将字符串转换为long
atoll:将字符串转换为 long long
atof: 将字符串转换为浮点数

宽窄字符转换

std::wstring wide_str = L"中国人";
std::wstring_convert<std::condecvt<wchar_t, char, std::mbstate_t>>
converter(new std::codecvt<wchar_t, char, std::mbstate_t>("CHS");
std::string narrow_str = converter.to_bytes(wide_str);
std::wstring wstr = converter.from_bytes(narrow_str);
std::cout << narrow_str << std::endl;
wcout.imbue(std::locale("chs"));
std::wcout << wstr << std::endl;
std::cout << wstr.size() << " " << wstr.length() << endl;
std::cout << narrow_str.size() << " " << narrow_str.length() << endl;

itoa c实现:

#include <ctype.h>
#include <stdio.h>
int atoi (char s[]);
int main(void )
{
    char s[100];
    gets(s);
    printf("integer=%d\n",atoi(s));
    return 0;
}
int atoi (char s[])
{
    int i,n,sign;
    for(i=0;isspace(s[i]);i++)//跳过空白符;
    sign=(s[i]=='-')?-1:1;
    if(s[i]=='+'||s[i]==' -')//跳过符号
      i++;
    for(n=0;isdigit(s[i]);i++)
       n=10*n+(s[i]-'0');//将数字字符转换成整形数字
    return sign *n;
}

atoi c实现:转自编程珠玑公众号

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#define NULL_PTR_ERR 1
#define ERANGE 2
int errCode = 0;
int my_atoi(char* str) {
    int negative = 0;
    char c = 0;
    /*计算结果存储*/
    long long ret = 0;
    errCode = 0;
    if(NULL == str)
    {
        errCode = NULL_PTR_ERR;
        return 0;
    }
    /*跳过开始的空格*/
    while(' ' == (*str))
        str++;
    /*跳过空格之后,到达了字符串结尾,则退出*/
    if(0 == *str)
        return 0;
    /*负数*/
    if(*str == '-' )
    {
        negative = 1;
        str++;
    }
    /*正数*/
    else if(*str == '+')
    {
        negative = 0;
        str++;
    }
    /*正数*/
    else if(isdigit(*str))
    {
        negative = 0;
    }
    /*如果不是以上内容,则直接退出*/
    else
    {
        return 0;
    }
    while(isdigit(*str))
    {
        /*计算结果*/
        ret = ret*10 + *str -'0';

        /*如果发现结果大于INT_MAX或者小于INT_MIN,则溢出,返回最值*/
        if(ret > (negative?-(long long )INT_MIN:INT_MAX))
        {
            /*溢出,返回最大值*/
            errCode = ERANGE;
            return negative?INT_MIN:INT_MAX;
        }
        str++;
    }
    /*根据正负号返回正确的结果*/
    return negative?-ret:ret;
}
int main(void)
{
    /*只有一个负号*/
    int result = my_atoi("-");
    printf("-:%d,errCode:%d\n",result,errCode);

    /*空指针*/
    result = my_atoi(NULL);
    printf("NULL:%d,errCode:%d\n",result,errCode);
    /*空字符串*/
    result = my_atoi("      ");
    printf("     :%d,errCode:%d\n",result,errCode);

    /*负数*/
    result = my_atoi("-1");
    printf("  -1:%d,errCode:%d\n",result,errCode);

    /*负数溢出*/
    result = my_atoi("   -11111111111");
    printf("   -11111111111:%d,errCode:%d\n",result,errCode);

    /*正数*/
    result = my_atoi("+123");
    printf("+123:%d,errCode:%d\n",result,errCode);

     /*正数溢出*/
    result = my_atoi("+123111111111111111");
    printf("+123111111111111111:%d,errCode:%d\n",result,errCode);
    return 0;
}

如何写出一个不含bug的itoa和atoi函数其实也挺考功夫的。

一个tx2018年的笔试题

/*
题目描述
有两个用字符串表示的非常大的大整数,算出他们的乘积,也是用字符串表示。不能用系统自带的大整数类型。
输入描述:
空格分隔的两个字符串,代表输入的两个大整数
输出描述:
输入的乘积,用字符串表示
示例1
输入
72106547548473106236 982161082972751393
输出
70820244829634538040848656466105986748
*/
#include<iostream>
#include<string>
using namespace std;
//移位进位法
string Mul(string left, string right)
{
 
    size_t Lsize = left.size();
    size_t Rsize = right.size();
    size_t Size = Lsize + Rsize;
    string res(Size, '0');
 
    int takevoer = 0;//进位
    int offset = 0;//移位
 
    size_t idx = 1, j = 1;
    for (idx = 1; idx <= Rsize; ++idx)
    {
        takevoer = 0;
        int rightnum = right[Rsize - idx] - '0';
        //计算每一位与left相乘
        for (j = 1; j <= Lsize; ++j)
        {
            char resBit = res[Size - j - offset] - '0';
            int num = rightnum * (left[Lsize - j] - '0') + takevoer + resBit;
            takevoer = num / 10;
            res[Size - j - offset] = num % 10 + '0';
        }
        if (takevoer != 0)
            res[Size - j - offset] = takevoer + '0';
        offset++;
    }
 
    //如果没有进位的话,res最高位没有数字
    if (res[0] == '0')
        res.erase(0, 1);
    return res;
}
 
int main()
{
    string s1, s2;
    cin >>s1 >> s2;
    string str=Mul(s1,s2);
    cout << str << endl;
}

关于字符串的题有很多,可以去LeetCode上去刷一刷。

发布了27 篇原创文章 · 获赞 70 · 访问量 9415

猜你喜欢

转载自blog.csdn.net/qq_23905237/article/details/88982065