0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

字符串硬核暴力破解法讲解

FPGA之家 来源:SoWhat1412 作者:SoWhat1412 2021-04-04 11:50 次阅读

1 暴力破解法

在主串A中查找模式串B的出现位置,其中如果A的长度是n,B的长度是m,则n 》 m。当我们暴力匹配时,在主串A中匹配起始位置分别是 0、1、2….n-m 且长度为 m 的 n-m+1 个子串。

64be54d2-8ecb-11eb-8b86-12bb97331649.png

暴力匹配

对应代码是:

#include《stdio.h》

#include《string.h》

int cnt=0;

int index(char s[], char sub[])

{

int i=0;

int j=0;

while(i《strlen(s))

{

if(s[i]==sub[j])

{ //单个字符相等的话 i和j都向后搜索

i++;

j++;

}

else

{ //有字符不匹配的话,i从上一次的下一个位置开始,模式串j再从0开始

i=i-j+1;

j=0;

}

if(j==strlen(sub))

{

cnt++;

return i-strlen(sub)+1;

}

}

return -1;

}

int main()

{

// s=“abcdabefgabefa”,sub=“abe”,返回 5。

char s[20],sub[10];

gets(s);

gets(sub);

printf(“%d

”,cnt);

printf(“%d

”,index(s,sub));

return 0;

}

如果主串是bbb…bbb,模式串是bbbbc,那每个串都要比较m次,一共是(n-m+1)*m次。时间复杂度很大 = O(n*m),一般简单匹配时候可用此法。

2 Rabin-Karp 算法

算法思路:对主串的 n-m+1 个子串分别求哈希值,然后跟模板串的哈希值对比,如果一样再逐个对比字符串是否一样。

650d01b8-8ecb-11eb-8b86-12bb97331649.png

Rabin-Karp算法

但是中间数据的Hash值计算是可以优化的,我们以简单的字符串匹配举例,把a-z映射到0~25上。然后按照26进制计算一个串的哈希值,比如:

654bbd18-8ecb-11eb-8b86-12bb97331649.png

Hash计算

但是你会发现相邻的两个子串数据之间是有重叠的,比如dab跟abc重叠了ab。这样哈希下一个数据的Hash值其实可以借鉴下上一个数据的值推导得出:

659306fa-8ecb-11eb-8b86-12bb97331649.png

优化计算哈希值

RK算法的时间复杂度包含两部分,第一部分是遍历所有子串计算Hash值,时间复杂度是O(n)。第二部分是比较哈希值,这部分时间复杂度也是O(n)。

这个算法的核心就是尽量减少哈希值相等的情况下数据不一样从而进行的比较,所以哈希算法要尽可能的好,如果你感觉用123对应字母abc容易碰撞,那用素数去匹配也是OK的,反正目的是一样的, 你可以认为这是一种取巧的办法来处理字符串匹配问题。

3 Boyer-Moore 算法。

Boyer Moore算法是一种非常高效的字符串匹配算法,它的性能是著名的 KMP 算法的 3 到 4 倍。它不太好理解,但确是工程中使用最多的字符串匹配算法。以前我们匹配字符串的时候是一个个从前往后挪动来逐次比较,BM 算法核心思想是在模式串中某个字符与主串不能匹配时,将模式串往后多滑动几位,来减少不必要的字符比较。

65c83078-8ecb-11eb-8b86-12bb97331649.png

移动比较对比

整体而言BM算法还是挺复杂的相比前面两种,主要包含坏字符规则跟好后缀规则。

3.1 坏字符规则

坏字符规则意思是根据模式串从后往前匹配,当我们发现某个字符没法匹配的时候。我们把这个没有匹配的主串中的字符叫作坏字符。

65f9601c-8ecb-11eb-8b86-12bb97331649.png

坏字符

找到坏字符c后,在模式串中继续查找发现c跟模式串任何字符无法匹配,则可以直接将模式串往后移动3位。继续从模式串尾部对比。

662a5d8e-8ecb-11eb-8b86-12bb97331649.png

移动2格

此时发现坏字符是g,但在模式串中有个g存在,不能再往后移动3个了,移动的位置是2个。再继续匹配。那有啥规律呢?

发送不匹配时,坏字符对应的模式串字符下标位置Si,如果坏字符在模式串中存在,取从后往前最先出现的坏字符下标记为Xi(取第一个是怕挪动太大咯),如果坏字符在模式串中不存在则Xi = -1。此时模式串往后移动位数= Si - Xi。

66780caa-8ecb-11eb-8b86-12bb97331649.png

坏字符移动规则

如果碰到极致的主串=cccdcccdcccd,模式串=cccc,那此时时间复杂度是O(n/m)。

6685a518-8ecb-11eb-8b86-12bb97331649.png

最优解

但是不要高兴太早!下面这种情况可能导致模式串不往后移动,反而往前移动哦!

66da5126-8ecb-11eb-8b86-12bb97331649.png

往前移动?

所以此时BM算法还需要用到好后缀规则。

3.2 坏字符代码

为避免每次都拿怀字符从模式串中遍历查找,此时用到散列表将模式串中每个字符及其下标存起来,方便迅速查找。

接下来说下散列表规则,比如一个字符是一个字节,用大小为256的数组记录每个字符在模式串出现位置,数组中存储的是模式串出现的位置,数组下表是字符对应的ASCII值。

670fc2b6-8ecb-11eb-8b86-12bb97331649.png

哈希规则坏字符规则:

// 全局变量 SIZE

private static final int SIZE = 256;

// b=模式串数组,m是模式串数组长度,sl是哈希表,默认-1

private void generateBC(char[] b, int m, int[] sl) {

for (int i = 0; i 《 SIZE; i++) {

sl[i] = -1; // 初始化sl

}

for (int i = 0; i 《 m; ++i) {

int ascii = (int)b[i];

sl[ascii] = i;

}

}

接下来先不考虑好后缀规则跟坏字符的负数情况,先大致写出 BM 算法代码。

678cb28a-8ecb-11eb-8b86-12bb97331649.png

坏字符BM

public int bm(char[] a, int n, char[] b, int m) {

// 记录模式串中每个字符最后出现的位置

int[] sl = new int[SIZE];

// 构建坏字符哈希表

generateBC(b, m, sl);

// i表示主串与模式串对齐的第一个字符

int i = 0;

while (i 《= n - m) {

int j;

for (j = m - 1; j 》= 0; j--) {

if (a[i+j] != b[j]) break;

}

if (j 《 0) {

// 匹配成功,返回主串与模式串第一个匹配的字符的位置

return i;

}

//将模式串往后滑动j-bc[(int)a[i+j]]位

i = i + (j - sl[(int)a[i+j]]);

}

return -1;

}

3.3 好后缀规则

好后缀跟坏后缀道理类似,从后往前匹配,直到遇到不匹配的字符x,那主串x之前的就叫好后缀。

67e040d0-8ecb-11eb-8b86-12bb97331649.png

好后缀定义

此时移动的规则如下:

如果好后缀在模式串中找到了,用x框起来,然后将x框跟好后缀对齐继续匹配。

6823c94a-8ecb-11eb-8b86-12bb97331649.png

找到了移动规则

找不到的时候,如果直接移动长度是模式串m位,那极有可能过度了!而过度移动存在的原因就是,比如你找了好后缀u,u在模式串中整体没找到,但是u的子串d是可以跟模式串匹配上的啊。

687c28e2-8ecb-11eb-8b86-12bb97331649.png

过度移动

所以此时还要看好后缀的后缀子串是否跟模式串中的前缀子串匹配,从好后缀串的后后缀子串中找个最长能跟模式串的前缀子串匹配的然后滑动到一起,比如上面的d。

然后分别计算坏字符往后滑动位数跟好后缀往后滑动此时,两者取其大作为模式串往后滑动位数,这种情况下还可以避免坏字符的负数情况。

3.4 好后缀代码

好后缀的核心其实就在于两点:

在模式串中,查找跟好后缀匹配的另一个子串。

在好后缀的后缀子串中,查找最长的、能跟模式串前缀子串匹配的后缀子串。

3.4.1 预处理工作

上面两个核心点可以在代码层面用暴力解决,但太耗时!我们可以在匹配前通过预处理模式串,预先计算好模式串的每个后缀子串,对应的另一个可匹配子串的位置。

先看如何表示模式串中不同的后缀子串,因为后缀子串的最后个字符下标为m-1,我们只需记录后缀子串长度即可,通过长度可以确定一个唯一的后缀子串。

68a51d24-8ecb-11eb-8b86-12bb97331649.png

子串表示

再引入关键的变量suffix数组。suffix 数组的index表示后缀子串的长度。下标对应的数组值存储的是

好后缀在模式串中匹配的起始下标值:

68f4db66-8ecb-11eb-8b86-12bb97331649.png

suffix数组定义

比如此处后缀子串c在模式串中另一个匹配开始位置为2, 后缀子串bc在模式串中另一个匹配开始位置为1 后缀子串dbc在模式串中另一个匹配开始位置为0, 后缀子串cdbc在模式串中只出现了一次,所以为-1。

69450a5a-8ecb-11eb-8b86-12bb97331649.png

prefix 数组

这里需注意,我们不仅要在模式串中查找跟好后缀匹配的另一个子串,还要在好后缀的后缀子串中查找最长的能跟模式串前缀子串匹配的后缀子串。比如下面:

698b3048-8ecb-11eb-8b86-12bb97331649.png

最长模式匹配

用suffix只能查找跟好后缀匹配的另一个子串。但还需要个 boolean 类型的prefix数组来记录模式串的后缀子串是否能匹配模式串的前缀子串。

接下来重点看下如何填充suffix跟prefix数组,拿下标从 0 到 i 的子串与整个模式串,求公共后缀子串,其中i=[0,m-2]。如果公共后缀子串的长度是 k,就suffix[k]=j,其中 j 表示公共后缀子串的起始下标。如果 j = 0,说明公共后缀子串也是模式串的前缀子串,此时 prefix[k]=true。

69f13514-8ecb-11eb-8b86-12bb97331649.png

suffix跟prefix数组

// b=模式串,m=模式串长度,suffix,prefix 数组 如上定义

private void generateGS(char[] b, int m, int[] suffix, boolean[] prefix) {

//初始化

for (int i = 0; i 《 m; i++) {

suffix[i] = -1;

prefix[i] = false;

}

// b[0, i]

for (int i = 0; i 《 m - 1; i++) {

int j = i;

// 公共后缀子串长度

int k = 0;

// 与b[0, m-1]求公共后缀子串,并且会有覆盖现象产生。

while (j 》= 0 && b[j] == b[m-1-k]) {

--j;

++k;

//j+1表示公共后缀子串在b[0, i]中的起始下标

suffix[k] = j+1;

}

//如果公共后缀子串也是模式串的前缀子串

if (j == -1) prefix[k] = true;

}

}

3.4.2 正式代码

有了suffix跟prefix数组后,看下移动规则。假设好后缀串长度=k,如果k != 0,说明有好后缀,接下来通过suffix[k]的值来判断如何移动。

suffix[k] != -1,不等于时说明匹配上了,模式串后移 j-suffix[k]+1 位,其中 j 表示坏字符对应的模式串中的字符下标。

suffix[k] = -1,等于时说明好后缀没匹配上,那就看下子串的匹配情况,好后缀的后缀子串长度是 b[r, m-1],其中 r = [j+2,m-1],后缀子串长度 k=m-r,如果 prefix[k] = true,说明长度为 k 的后缀子串有可匹配的前缀子串,这样我们可以把模式串后移 r 位。

如果都没匹配上,那就直接将模式串后移m位。

// a跟n 分别表示主串跟主串长度。

// b跟m 分别表示模式串跟模式串长度。

public int bm(char[] a, int n, char[] b, int m) {

// 用来记录模式串中每个字符最后出现的位置

int[] sl = new int[SIZE];

// 构建坏字符哈希表

generateBC(b, m, sl);

int[] suffix = new int[m];

boolean[] prefix = new boolean[m];

// 构建 suffix 跟 prefix 数组

generateGS(b, m, suffix, prefix);

int i = 0; // j表示主串与模式串匹配的第一个字符

while (i 《= n - m) {

int j;

// 模式串从后往前匹配

for (j = m - 1; j 》= 0; --j) {

// 坏字符对应模式串中的下标是j

if (a[i+j] != b[j]) break;

}

if (j 《 0) {

// 匹配OK ,返回主串与模式串第一个匹配的字符的位置

return i;

}

// 坏字符计算所得需移动长度

int x = j - sl[(int)a[i+j]];

int y = 0;

// j 《 m-1 说明有好的匹配上了

if (j 《 m-1) {

y = moveByGS(j, m, suffix, prefix);

}

i = i + Math.max(x, y);

}

return -1;

}

// j = 坏字符对应的模式串中的字符下标

// m = 模式串长度

private int moveByGS(int j, int m, int[] suffix, boolean[] prefix) {

// 好后缀长度

int k = m - 1 - j;

if (suffix[k] != -1) {

// 好后缀可以匹配上,返回需移动长度

return j - suffix[k] + 1;

}

// 有匹配到好后缀子串的模式串前缀子串

for (int r = j+2; r 《= m-1; ++r) {

if (prefix[m-r] == true) {

return r;

}

}

// 没找到直接 移动最大值

return m;

}

3.5 复杂度分析

整个BM算法用到了额外的 sl、suffix、prefix三个数组,其中sl数组大小跟字符集大小有关,suffix 数组和 prefix 数组的大小跟模式串长度 m 有关。如果处理字符集很大的字符串匹配问题,bc 数组对内存的消耗就会比较多。

因为好后缀和坏字符规则是独立的,如果我们运行的环境对内存要求苛刻,可以只使用好后缀规则,不使用坏字符规则,这样就可以避免 bc 数组过多的内存消耗。不过,单纯使用好后缀规则的 BM 算法效率就会下降一些了。

BM 算法的时间复杂度分析起来是非常复杂,一般在3n~5n之间。

4 KMP 算法

KMP算法跟BM算法类似,从前往后匹配,把能匹配上的叫好前缀,不能匹配上的叫坏字符。

6a30f3c0-8ecb-11eb-8b86-12bb97331649.png

KMP匹配定义

遇到坏字符后就要进行主串好前缀后缀子串跟模式串的前缀子串进行对比,问题是对于已经比对过的好前缀,能否找到一种规律,将模式串一次性滑动很多位?

6a9e78d2-8ecb-11eb-8b86-12bb97331649.png

暴力破解

思路是将主串中好前缀的后缀子串和模式串中好前缀的前缀子串进行对比,获取模式串中最大可以匹配的前缀子串。一般把好前缀的所有后缀子串中,最长的可匹配前缀子串的那个后缀子串,叫作最长可匹配后缀子串。对应的前缀子串,叫作最长可匹配前缀子串。假如现在最长可匹配后缀子串 = u,最长可匹配前缀子串 = v,获得u跟v的长度为k,此时在主串中坏字符位置为i,模式串中为j,接下来将模式串后移j-k位,然后将待比较的模式串位置j = j-k进行比较。

6b0696ba-8ecb-11eb-8b86-12bb97331649.png

KMP算法移动

4.1 Next 数组存在意义

那最长可匹配前缀跟后缀我们用模式串就可以求解了。仿照BM算法,预先计算好就行。在KMP算法中提前构造个next数组。其中next数组的下标用来存储前缀子串最后一个数据的index,对应的value保存的是这个字符串的后缀子串集合跟前缀子串集合的交集。

干说可能不太好理解,我们以“abababca”为例。它的部分匹配表(Partial Match Table)数组如下:

6b3cf44e-8ecb-11eb-8b86-12bb97331649.png

Next数组

接下来对value值的获取进行解释,如果字符串A和B,存在A=BS,其中S是任意的非空字符串,那就称B为A的前缀。例如”what”的前缀包括{“w”,“wh”,“wha”},我们把所有前缀组成的字符串的前缀集合。同样可以定义后缀A=SB, 其中S是任意的非空字符串,那就称B为A的后缀,例如“Potter”的后缀包括{“otter”, “tter”, “ter”, “er”, “r”},然后把所有后缀组成字符串的后缀集合。要注意字符串本身并不是自己的后缀。

PMT数组中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。例如,对于“aba”,它的前缀集合为{“a”, “ab”},后缀集合为{“ba”, “a”}。两个集合的交集为{“a”},那么长度最长的元素就是字符串“a”了,长度为1,所以“aba”的Next数组value = 1,同理对于“ababa”,它的前缀集合为{“a”, “ab”, “aba”, “abab”},它的后缀集合为{“baba”, “aba”, “ba”, “a”}, 两个集合的交集为{“a”, “aba”},其中最长的元素为“aba”,长度为3。

我们以主串“ababababca”中查找模式串“abababca”为例,如果在j处字符不匹配了,那在模式串[0,j-1]的数据串“ababab”中,前缀集合跟后缀集合的交集最大值就是长度为4的“abab”。

6b66be14-8ecb-11eb-8b86-12bb97331649.png

PMT数组使用方法

基于此就可以使用PMT加速字符串的查找了。我们看到如果是在j位失配,那么影响j 指针回溯的位置的其实是第 j−1 位的 PMT 值,但是编程中为了方便一般不直接使用PMT数组而是使用Next数组,Next数组的value其实就是存储的这个前缀的最长可以匹配前缀子串的结尾字符下标,其中如果匹配不到用-1代替。

6bb2a716-8ecb-11eb-8b86-12bb97331649.png

Next数组使用

4.2 KMP 匹配代码

// a = 主串,n=主串长度。b = 模式串,m = 模式串长度

public static int kmp(char[] a, int n, char[] b, int m) {

int[] next = getNexts(b, m);

int j = 0;

for (int i = 0; i 《 n; ++i) {

while (j 》 0 && a[i] != b[j]) {

j = next[j - 1] + 1; // 发现不一样则 保持i 不变 j进行移动

}

if (a[i] == b[j]) {

++j;

}

if (j == m) { // 找到匹配模式串的了

return i - m + 1;

}

}

return -1;

}

至此你会发现只要搞明白了PMT存在的意义,然后顺着思路推Next数组即可。

4.3 Next 数组求解

当要计算next[i]时,前面计算过的next[0~i-1]是否可以被用来快速推导出next[i]呢?

情况一:如果next[i-1] = k-1,那此时b[0,i-1]的最长可匹配前缀子串是b[0,k-1],如果b[0,i-1]的下个字符b[i]跟b[0,k-1]的下个字符b[k]相等,那next[i] = k。

6c062742-8ecb-11eb-8b86-12bb97331649.png

情况二:假设b[0,i]最长可用后缀子串是b[r,i],那b[r,i-1]肯定是b[0,i-1]的可匹配后缀子串,但不一定是最长可匹配后缀子串。比如字符串b = “dexdecdexdex”,此时最长可匹配后缀子串是“dex”,b去掉最后的‘x’成为B,此时虽然“de”是B的可匹配后缀子串,但“dexde”才是最长后缀子串!也就是说b[0, i-1]最长可匹配后缀子串对应的模式串的前缀子串的下一个字符并不等于 b[i]。

6c521972-8ecb-11eb-8b86-12bb97331649.png

那此时看下b[0,i-1]的次长可匹配后缀子串b[x,i-1]对应的可匹配前缀子串b[0,i-1-x] 的下个字符b[i-x] 是否等于b[i],相等那b[0,i]的最长可匹配后缀子串是b[x,i]。

6ca0f416-8ecb-11eb-8b86-12bb97331649.png

那我们来求 b[0, i-1]的次长可匹配后缀子串呢?次长可匹配后缀子串一定被包含在最长可匹配后缀子串中,而最长可匹配后缀子串又对应最长可匹配前缀子串 b[0, y]。此时查找 b[0, i-1]的次长可匹配后缀子串变成了查找b[0, y]的最长匹配后缀子串的问题。

按此思路考察完所有的 b[0, i-1]的可匹配后缀子串 b[y, i-1],直到找到一个可匹配的后缀子串,它对应的前缀子串的下一个字符等于 b[i],那这个 b[y, i]就是 b[0, i]的最长可匹配后缀子串。

6cdc2d4c-8ecb-11eb-8b86-12bb97331649.png

// b = 模式串,m = 模式串的长度

private static int[] getNexts(char[] b, int m) {

int[] next = new int[m];

next[0] = -1;

int k = -1;

for (int i = 1; i 《 m; ++i) {

while (k != -1 && b[k + 1] != b[i]) {

k = next[k];

// 因为前一个的最长串的下一个字符不与最后一个相等,需要找前一个的次长串,

// 问题就变成了求0到next(k)的最长串,如果下个字符与最后一个不等,

// 继续求次长串,也就是下一个next(k),直到找到,或者完全没有

// 最好结合前面的图来看

}

if (b[k + 1] == b[i]) {

++k; // 字符串相等则看下一个

}

next[i] = k; // 数组赋值

}

return next;

}

KMP空间复杂度:该算法只需要一个额外的 next 数组,数组的大小跟模式串相同。所以空间复杂度是 O(m),m 表示模式串的长度。

KMP时间复杂度:next 数组计算的时间复杂度是 O(m) + 匹配时候时间复杂度是 O(n) = O(m+n)

至此,常见的字符串匹配算法正式讲解完毕,其实前面说的都是一个主串,一个模式串。

原文标题:字符串硬核讲解

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 字符串
    +关注

    关注

    1

    文章

    554

    浏览量

    20284

原文标题:字符串硬核讲解

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    字符串写入数据库报错误的字符串

    在向表中姓名、性别、毕业院校中写入文字时会报错,错误为:错误的字符串值。输入数字能正常写入。错误vi为DB TOOLS insert Data.vi
    发表于 06-21 19:12

    如何提取串口接收字符串数组里的某个字符串

    前几天搞了好久串口发送接收字符串的程序代码,终于搞出来了。还没高兴多久,新的问题又来了。我使用STM8S105K4的UART2口跟蓝牙模块通信的,我发送字符串指令给蓝牙后,蓝牙返回来了十几
    发表于 04-22 06:05

    C语言字符串编译函数介绍

    在C语言中,字符串实际上是使用null字符O'终止的一维字符数组。因此,一个以null结尾的字符串,包含了组成字符串
    的头像 发表于 03-07 16:18 295次阅读
    C语言<b class='flag-5'>字符串</b>编译函数介绍

    PSoC™ 6 UART通信反复发送字符串是为什么?

    我正在尝试使用 UART 代码,但我修改了代码,一次又一次地发送字符串,而这次他只询问用户一次。 所以我想再三询问用户。 我还设置了一个 while (1) 循环,但仍然不起作用。 因此,请提供反复发送新字符串的 uart 示例。
    发表于 03-05 07:26

    USB字符串描述符里面的序列号字符串到底是什么东西?

    在设备描述符里面,有一个表示序列号字符串描述符的编号,请问这个序列号字符串的描述符是什么东西呢? 厂商字符串和设备字符串都能理解,而且在电脑的“设备与打印机”里面都找到了。但请问这个
    发表于 01-24 08:06

    labview扫描字符串怎么用

    LabVIEW 是一种流程化编程语言和开发环境,主要用于控制、测量和监测系统。在 LabVIEW 中,扫描字符串是一项常见的任务,它允许用户按照一定的模式从输入字符串中提取所需的信息。下面我将详细
    的头像 发表于 12-29 10:12 1052次阅读

    labview扫描字符串怎么用

    LabVIEW是一种图形化编程语言,用于开发控制、测量和监控系统。虽然它主要用于工程和科学领域,但也可以用于处理文本和字符串。 在LabVIEW中,可以使用字符串处理函数来扫描字符串。以下是一些常用
    的头像 发表于 12-26 16:58 956次阅读

    字符数组和字符串有没有区别?

    字符数组和字符串有没有区别?
    的头像 发表于 11-30 16:39 391次阅读

    MySQL替换字符串函数REPLACE

    MySQL是目前非常流行的开源数据库管理系统之一,它具有强大的功能和性能。其中之一的字符串函数REPLACE,可以用于替换字符串中的指定字符字符串。在本文中,我们将详细讨论MySQL
    的头像 发表于 11-30 10:44 516次阅读

    c语言字符串定义

    C语言是一种强大而广泛使用的编程语言,字符串是其中一个非常重要的概念。在C语言中,字符串是由一系列字符组成的数组,它可以表示文本、数字等各种类型的数据。在本文中,我们将详尽、详实、细致地介绍C语言
    的头像 发表于 11-24 10:02 1077次阅读

    mysql字符串包含某个字符串

    MySQL是一种开源的关系型数据库管理系统,被广泛用于构建Web应用程序和其他大型数据驱动的应用。在进行MySQL数据库查询时,经常需要使用字符串包含操作,即判断一个字符串是否包含另一个字符串。本文
    的头像 发表于 11-16 14:52 1610次阅读

    怎样进行字符串转数字?

    除了使用sprintf之外,自己写一个字符串转数字的程序应该怎样处理?sprintf的效率很低
    发表于 11-10 07:18

    c语言如何对比字符串是否相同?

    c语言如何对比字符串是否相同把一个字符串变量直接赋值给另一个变量怎么实现
    发表于 11-02 07:45

    怎么把int类型的数据转换成字符串?

    怎么把 int 类型的数据转换成字符串: 看项目有用 micrilib,itoa() 函数 和 sprintf() 能不能用呢?怎么用 比如把 int a=10;转换成字符串 charbuf[]=\"10\";
    发表于 11-01 08:27

    C++字符串string

    string是C++编程语言中的字符串。在C++中字符串处理可以使用c语言字符串形式char *,也可以使用string类格式。
    的头像 发表于 07-10 00:26 969次阅读
    C++<b class='flag-5'>字符串</b>string