好久没有敲代码了,于是这两天找个题(求两个字符串的最长公共子串)练练。用的是最简单也最笨的方法,即扫描一个短串,用长串来匹配。本意是想练练结构体二级指针的,用结构来存储所有的公共子串,结果误打误撞发现了一些问题。
如上图,我分别画出了二级指针seq_p以及一级指针seq_p[0]、seq_p[1]的内存示意图,由图可知,虽然seq_p[0]的值等于*seq_p的值,但seq_p[1]的值并不等于(*seq_p)+1的值,因为(*seq_p)+1的值为*seq_p的值加上一个结构(8个字节)的偏移量,而内存是按字节编址的,因此(*seq_p)+1的值为0x551848≠0x5518b0。因此,如果之前是用seq_p[i]来malloc空间的话,之后用((*seq_p)+i)->seq来存储公共子串便会出现内存访问不到的段错误,反之亦然,务必保持前后一致,这里笔者建议使用seq_p[i]的形式。
由此得出结论,若p为二级指针,则p[i]的值不一定等于(*p)+i的值;若p为一级指针,则p[i]的值等于(*p)+i的值,这是因为为一级指针malloc空间的时候,分配的空间是连续的。
核心函数代码如下。
View Code
1 #include "findSeq.h" 2 typedef struct SEQ_type { 3 char *seq; 4 int len; 5 } SEQ; 6 7 void findSeq(const char *s1, const char *s2) { 8 const char *temp1 = NULL; 9 const char *temp2 = NULL; 10 11 //使得temp1存取较短的字符串 12 if (strlen(s1) < strlen(s2)) { 13 temp1 = s1; 14 temp2 = s2; 15 } else { 16 temp1 = s2; 17 temp2 = s1; 18 } 19 20 //用结构体二级指针,用字符串数组指针会简单些,其实用结构体一级指针就可以了 21 SEQ **seq_p = NULL; 22 if ((seq_p = (SEQ **) malloc(strlen(temp1) * sizeof(SEQ *))) == NULL ) { 23 printf("malloc error"); 24 return; 25 } 26 int i = 0; 27 for (i = 0; i < strlen(temp1); i++) { 28 if ((seq_p[i] = (SEQ *) malloc(sizeof(SEQ))) == NULL ) { 29 printf("seq malloc error"); 30 return; 31 } else 32 ; 33 } 34 for (i = 0; i < strlen(temp1); i++) { 35 if (((seq_p[i])->seq = (char *) malloc( 36 (strlen(temp1) + 1) * sizeof(char))) == NULL ) { 37 printf("Malloc Error"); 38 return; 39 } else 40 ; 41 42 (seq_p[i])->len = 0; 43 } 44 //按较短的字符串来扫描较长的字符串从而发现最长公共子串 45 const char *c1 = temp1; 46 const char *c2 = temp2; 47 char *tmp = NULL; 48 int seqCnt = 0; 49 i = 0; 50 while (c1 != '\0') { 51 tmp = (seq_p[i])->seq; 52 while (*c1 != *c2 && *c2 != '\0') { 53 c2++; 54 } 55 if (*c2 == '\0') { 56 c1++; 57 c2 = temp2; 58 continue; 59 } 60 while (*c1 == *c2 && *c1 != '\0') { 61 *(tmp++) = *c1; 62 (seq_p[i])->len++; 63 c1++; 64 c2++; 65 } 66 *tmp = '\0'; 67 seqCnt++; 68 if (*c1 == '\0') 69 break; 70 else { 71 int backNum = strlen((seq_p[i])->seq); 72 while (backNum-- != 1) { 73 c1--; 74 } 75 c2 = temp2; 76 i++; 77 } 78 } 79 //排序,使得子串由长到短排列 80 int tempForChange = 0; 81 i = 0; 82 int j = 0; 83 while (i < seqCnt - 1) { 84 j = i + 1; 85 while (j < seqCnt) { 86 if (seq_p[i]->len < seq_p[j]->len) { 87 tempForChange = seq_p[i]; 88 seq_p[i] = seq_p[j]; 89 seq_p[j] = tempForChange; 90 } 91 j++; 92 } 93 i++; 94 } 95 //输出最长公共子串 96 for (i = 0; i < seqCnt; i++) { 97 if (seq_p[i]->len == seq_p[0]->len) 98 printf("%s\n", seq_p[i]->seq); 99 else 100 break; 101 } 102 //释放指针 103 for (i = 0; i < strlen(temp1); i++) 104 { 105 free(seq_p[i]); 106 seq_p[i] = NULL; 107 } 108 109 free(seq_p); 110 free(tmp); 111 seq_p = NULL; 112 tmp = NULL; 113 114 }