zoukankan      html  css  js  c++  java
  • [原创]由结构二级指针所想到的

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

    如上图,我分别画出了二级指针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 }
    如原创文章,转载请注明:转自http://www.cnblogs.com/xpowerlord/
  • 相关阅读:
    pku2992 Divisors
    pku3090 Visible Lattice Points
    pku3615 Cow Hurdles
    禁止 verifier.dll 监控程序
    运行ogreSDK的samples
    #pragma pack(n) 啥时候可以不再忘记?
    游戏开发流程图。
    希望可以尽快的写篇自己的成果。
    windows与OS X下的std::string
    VS2008鼠标右键不灵敏,TFS的Local Path无法打开对应文件夹
  • 原文地址:https://www.cnblogs.com/xpowerlord/p/2994478.html
Copyright © 2011-2022 走看看