[原创]由结构二级指针所想到的

好久没有敲代码了,于是这两天找个题(求两个字符串的最长公共子串)练练。用的是最简单也最笨的方法,即扫描一个短串,用长串来匹配。本意是想练练结构体二级指针的,用结构来存储所有的公共子串,结果误打误撞发现了一些问题。

如上图,我分别画出了二级指针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 }

 

 

posted @ 2013-04-01 22:44  XpowerLord  阅读(630)  评论(0编辑  收藏  举报