字符串

来源:互联网 发布:守望先锋的衰落 知乎 编辑:程序博客网 时间:2024/06/05 05:55

基础知识

字符串是由零个或多个字符组成的有限串行。
子串的定义:串中任意个连续字符组成的子序列,并规定空串是任意串的子串,任意串是其自身的子串。
在做关于字符串的题时,一定要注意指向字符串的指针为空(NULL)和空字符串(“\0”)这两种不同的情况。参见:What is the difference between NULL, ‘\0’ and 0

C++中字符串的使用方法

  • 1. C++中通常通过char*/const char* 类型的指针来操纵C语言中的风格字符串。
    C/C++中常用的字符串处理函数:
函数 用法说明 strlen(s) 返回s的长度,不包括字符串结束符null strcmp(s1, s2) 比较两个字符串s1和s2是否相同。若s1与s2相等,返回0;若s1大于s2,返回正数;若s1大于s2,返回负数 strcat(s1, s2) 将字符串s2连接到s1后,并返回s1 strcpy(s1, s2) 将s2复制给s1,并返回s1 strncat(s1, s2, n) 将字符串s2的前n个字符连接到s1后,并返回s1 strncpy(s1, s2, n) 将字符串s2的前n个字符复制给s1,并返回s1

.

  • 2. 另外,C++中string类方便了对字符串的各种操作。参考:C++字符串和string类

字符的输入/输出

单个字符可直接使用char c; while(cin>>c){...},不过这样会跳过空格;若不想跳过任何字符可使用while(cin.get(c)) {...}
字符串输入可使用char str[10]; while(cin >> str) {...},这样依然是遇到空格即结束;若要遇到回车结束可使用cin.get(str, 20, '\n')
字符串输出可使用char a[10] = "helloyu"; cout << a;

应用:反转单词顺序VS左旋转字符串

题目一: 输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串“I am a student.”,则输出“student a am I”。
思路:两次翻转字符串的解法。
代码实现
C++版:

int ReverseString(char* begin, char* end) {    if (begin == NULL || end == NULL) return 1;    while (begin<end) {        char temp = *begin;        *begin = *end;        *end = temp;        ++begin;        --end;    }    return 0;}int ReverseSentence(char* sentence) {    if (sentence == NULL) return 1;   //字符串指向空指针    int len = strlen(sentence);    if (len == 0) return 0;   //字符串长度为零    char* begin = sentence;    char* end = begin+len-1;    ReverseString(begin, end);    end = begin;    while (*begin != '\0') {        if (*begin == ' '&& end==begin)  //开头即为空格,或连续空格的情况        {            ++begin; ++end;        }        if (*end == ' ') {             ReverseString(begin, --end);            ++end; ++end;            begin = end;        }        else if (*end == '\0') {            ReverseString(begin, --end);            break;        }        else {            ++end;        }    }    return 0;}

python版:

import sysimport refor line in sys.stdin.readlines():    input_str = line.strip('\n')    reverse_first = re.split(r'\s+',input_str[::-1])    reverse_second = [i[::-1] for i in reverse_first]    reverse_sentence = ' '.join(reverse_second)    print(reverse_sentence)

测试用例
注意下面测试示例中如果使用char* 的方式来定义的话,a是一个常量字符串。所以应该使用字符数组的方法来定义。参考:未经处理的异常:0xC0000005:读取/写入位置冲突——从去掉字符串所有空格说起

    char a[] = "I am a student.";  //此处不能使用char* a来定义,因为那样生成的是一个常量字符串    char b[] = "I";    char c[] = "";    char d[] = "   ";

题目二: 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如输入字符串“abcdefg”和数字2,该函数将返回左旋转2位得到的结果为“cdefgab”。
思路:针对题目一的算法进行知识迁移。
代码实现

int ReverseString(char* begin, char* end) {    if (begin == NULL || end == NULL) return 1;    while (begin<end) {        char temp = *begin;        *begin = *end;        *end = temp;        ++begin;        --end;    }    return 0;}int LeftRotationSentence(char* sentence, int k) {    if (sentence == NULL) return 1; //指向NULL    int len = strlen(sentence);    if (k >= len || k<0) return 1;  //k不合法输入    if (k == len - 1 || k == 0) return 0;  //原有顺序,不用移动    if (len == 0) return 0;  //空字符串    char* firstStart = sentence;    char* firstEnd = sentence + k - 1;    char* secondStart = sentence + k;    char* secondEnd = sentence + len - 1;    ReverseString(firstStart, firstEnd);    ReverseString(secondStart, secondEnd);    ReverseString(firstStart, secondEnd);    return 0;}

测试用例

    char a[] = "I am a student.";    LeftRotationSentence(a, 4);    LeftRotationSentence(a, 0);    char b[] = "I";    LeftRotationSentence(b, 1);    char c[] = "";    LeftRotationSentence(c, 4);

应用:正则表达式匹配

题目:请实现一个函数用来匹配包含‘.’‘*’的正则表达式。模式中的字符‘.’表示任意一个字符,而‘*’表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串“aaa” 与模式“aaa”“ab*ac*a”匹配,但与 “aa.a”“ab*a”均不匹配。
分析:
对于‘.’比较好处理。对于‘*’ 其基本思想是:先假设其出现0次试试,不成功的话对其进行至少出现1次匹配。至少出现1次的匹配方案是:先判断出现一次是否合理,若不合理则匹配失败,若合理则将str指针移动至下一位但pattern保持原地不动,往下递归进行。
另外,此题中还要注意++pattern和pattern+1的区别。要同时考虑到空字符串指向字符串的指针为空这两种不同情况。
代码实现

bool match(char* str, char* pattern) {    if (str == NULL || pattern == NULL) return false;    return matchCore(str, pattern);}//此函数中注意++pattern和pattern+1的区别bool matchCore(char* str, char* pattern) {    if (*str == '\0' && *pattern == '\0') return true; //两字符串均为空的情况    else if (*str != '\0' && *pattern == '\0') return false;  //当str=""pattern=".*"不能直接判定为false    if ('*' == *(pattern + 1)) {  //pattern下一位存在且为“*”号        bool result = false;        result = matchCore(str, pattern+2);  //假设“*”匹配0次          if (!result) {            if (*pattern == '.' || *pattern == *str)                result = matchCore(str+1, pattern);  //先匹配一次            else                result = false;        }        return result;    }    //pattern下一位不存在 或 下一位不为“*”号    if (*pattern == '.' || *pattern == *str)        return matchCore(str+1, pattern+1);    else        return false;}

测试用例

    char a[] = "aaa";    char b[] = "a.a";    char c[] = "ab*ac*a";    char d[] = "aa.a";    char e[] = "ab*a";    char* f = NULL;    cout << match(a, b) << endl;  //匹配    cout << match(a, c) << endl;    cout << match(a, d) << endl;  //不匹配    cout << match(a, e) << endl;    cout << match(a, f) << endl;

应用:串的模式匹配

题目: 在字符串中查找子串。给定一个字符串A,要求在A中查找一个字串B。如主串A=”ababcabcacbab”,要你在A中查找子串(模式串)B=”abcac”。
分析:两种方法。法1:最基础的BF算法,复杂度O((m-n+1)*n);法2:KMP算法,复杂度O(m+n)。
代码实现
暴力匹配法:

char* strFind(char* string, char* substring) {    assert(string!=NULL && substring!=NULL);    int m = strlen(string);    int n = strlen(substring);    if(m<n) return NULL;    for(int i=0; i<=m-n; i++) {  //时间复杂度为O((m-n+1)*n)        int j=0;        for( ; j<n; j++) {            if(string[i+j] != substring[j]) break;        }        if(j == n) return string+i;    }    return NULL;}

python版:

import sysimport refor line in sys.stdin.readlines():    input_str, pattern_str = line.strip('\n').split(' ')    for m in re.finditer(pattern_str, input_str):        print(m.start())

应用:判断回文数

思路一:数字取反,判断是否相等。C++代码

#include<iostream>using namespace std;int main() {    int num;    while (cin >> num) {        int copyNum=num;        int reverseNum=0;        while (copyNum != 0) {            reverseNum *= 10;            reverseNum += copyNum % 10;            copyNum /= 10;        }        if (reverseNum == num) cout << "True" << endl;        else cout << "False" << endl;    }    return 0;}

思路二:转换为字符串,判断是否相等。python代码

def palindrome(num):    return str(num) == str(num)[::-1]
0 0