• [算法 笔记]2014年去哪儿网 开发笔试(续)第一题BUG修正


      上一篇的blog地址为:http://www.cnblogs.com/life91/p/3313868.html

      这几天又参加了一个家公司的笔试题,在最后的编程题中竟然出现了去哪儿网开发的第一题,也就是简化路径值。但是这次做题后,我发现我上次写的那个简化源码有很多问题,并且在这次笔试过程中也没有答对。闲话说完了,进入正题。

       上次源码出现的BUG

      1. 将连续重复的多个’/’字符视为一个。例如,”/abac/def//////ef”->”/abac/def/ef”。

      2. 根目录的开始字符为’/’,并且根目录的上级目录以及上上级目录都是本身。例如,”/../../../”->”/”。

      3. 字符’.’作为后缀名的分割符号出现。例如,”/abc/ef.gif”->”/abc/ef.gif”

      4. 以字符’/’作为起始字符。

      上述是上次源码出现的BUG。在修正这些BUG中,将增加一个临时空间用于存储原始路径。在拷贝过程中将连续重复出现的’/’变为一个’/’,并且删除”/./”这种情况。同时检查参数路径是否合法,目前仅考虑一种情况:当’.’个数超过2个时,将退出。

     1     // preprocess.
     2     while ( index < len )
     3     {
     4         // merge duplicate character -- '/'
     5         for ( cnt = 0;
     6                 index < len && path[index] == '/';
     7                 ++index, ++cnt );
     8         if ( cnt > 0 )
     9         {
    10             tmp_path[top++] = '/';
    11         }
    12 
    13         // delete only dot
    14         for ( cnt = 0;
    15                 index < len && path[index] == '.';
    16                 ++index, ++cnt );
    17         // Case 1: delete one dot.
    18         if ( top > 0 && tmp_path[top - 1] == '/' && cnt == 1 )
    19         {
    20             ++index;
    21         }
    22         // Case 2: copy two dots.
    23         else if ( cnt == 2 )
    24         {
    25             index -= cnt;
    26         }
    27         // Case 3: if more than two dots, it is error.
    28         else if ( cnt > 2 )
    29         {
    30             fprintf( stderr, "Error.
    " );
    31             // Remember: after free memory, this function could leave.
    32             free( tmp_path ), tmp_path = NULL;
    33             free( result ), result = NULL;
    34             return NULL;
    35         }
    36 
    37         // copy other characters.
    38         while ( index < len && path[index] != '/' )
    39         {
    40             tmp_path[top++] = path[index++];
    41         }
    42     }

     

      请注意:在异常退出函数时,需要将已分配的两个内存空间释放掉,并且将原始的指针指向NULL。防止内存泄漏问题。

      在后续的处理过程中,使用栈的思想来处理。当遇到连续的两个’.’时,将栈中元素弹出。如果当栈中元素全部退出的时候,将重置top节点。

     

     1         // Case 1: the number of '.' is 2;
     2         if ( top > 0 && cnt == 2 )
     3         {
     4             --top;
     5             while ( --top > 0 && result[top] != '/' );
     6         }
     7         // Case 2: "game.gif"
     8         else if ( top > 0 && result[top - 1] != '/' && cnt == 1 )
     9         {
    10             result[top++] = '.';
    11         }
    12         // Case 3: "/../../../" -> "/"
    13         else if ( top == 0)
    14         {
    15             ++top;
    16         }            

     

      完整的源码并提供简单的测试源码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <assert.h>
      5 
      6 
      7 char *normalize_path( const char *path )
      8 {
      9     char *result    = NULL;
     10     char *tmp_path  = NULL;
     11     int top         = 0;
     12     int cnt         = 0;
     13     int index       = 0;
     14     int len         = 0;
     15 
     16     assert( path != NULL && path[index] != '' && path[index] == '/' );
     17     len = strlen( path );
     18     result = (char *) malloc( sizeof(char) * (len + 1) );
     19     assert( result != NULL );
     20 
     21     tmp_path = (char *) malloc( sizeof(char) * (len + 1) );
     22     if ( tmp_path == NULL )
     23     {
     24         free( result ), result = NULL;
     25         return NULL;
     26     }
     27 
     28     // preprocess.
     29     while ( index < len )
     30     {
     31         // merge duplicate character -- '/'
     32         for ( cnt = 0;
     33                 index < len && path[index] == '/';
     34                 ++index, ++cnt );
     35         if ( cnt > 0 )
     36         {
     37             tmp_path[top++] = '/';
     38         }
     39 
     40         // delete only dot
     41         for ( cnt = 0;
     42                 index < len && path[index] == '.';
     43                 ++index, ++cnt );
     44         // Case 1: delete one dot.
     45         if ( top > 0 && tmp_path[top - 1] == '/' && cnt == 1 )
     46         {
     47             ++index;
     48         }
     49         // Case 2: copy two dots.
     50         else if ( cnt == 2 )
     51         {
     52             index -= cnt;
     53         }
     54         // Case 3: if more than two dots, it is error.
     55         else if ( cnt > 2 )
     56         {
     57             fprintf( stderr, "Error.
    " );
     58             // Remember: after free memory, this function could leave.
     59             free( tmp_path ), tmp_path = NULL;
     60             free( result ), result = NULL;
     61             return NULL;
     62         }
     63 
     64         // copy other characters.
     65         while ( index < len && path[index] != '/' )
     66         {
     67             tmp_path[top++] = path[index++];
     68         }
     69     }
     70 
     71     // other operators.
     72     tmp_path[top] = '';
     73     len = top;
     74     for ( index = 0, top = 0; index < len; )
     75     {
     76         // copy other characters except '.'
     77         while ( index < len && tmp_path[index] != '.' )
     78         {
     79             result[top++] = tmp_path[index++];
     80         }
     81 
     82         // count of point
     83         for ( cnt = 0; index < len && tmp_path[index] == '.'; ++index, ++cnt );
     84 
     85         // Case 1: the number of '.' is 2;
     86         if ( top > 0 && cnt == 2 )
     87         {
     88             --top;
     89             while ( --top > 0 && result[top] != '/' );
     90         }
     91         // Case 2: "game.gif"
     92         else if ( top > 0 && result[top - 1] != '/' && cnt == 1 )
     93         {
     94             result[top++] = '.';
     95         }
     96         // Case 3: "/../../../" -> "/"
     97         else if ( top == 0)
     98         {
     99             ++top;
    100         }
    101 
    102     }
    103     result[top] = '';
    104 
    105     // free memory
    106     free( tmp_path ), tmp_path = NULL;
    107 
    108     return result;
    109 }
    110 
    111 void output( const char *path )
    112 {
    113     char *result = NULL;
    114 
    115     result = normalize_path( path );
    116     printf( "Original is %s
    Result is %s
    
    ", path, result );
    117     free( result ), result = NULL;
    118 
    119     free( result );
    120     result = NULL;
    121 }
    122 
    123 int main()
    124 {
    125     char *path1 = "/home/news/./../tmp/game/../";
    126     char *path2 = "/../../../abc";
    127     char *path3 = "/game/gif.big";
    128     char *path4 = "///abc//..//edf/game.f";
    129 
    130     output( path1 );
    131     output( path2 );
    132     output( path3 );
    133     output( path4 );
    134 
    135     return 0;
    136 }
    normalize_path

     

     

  • 相关阅读:
    每天写点shell——read的用法
    串口编程(一) :理论基础
    常用算法3
    Linux man C++ 库函数
    网络爬虫(一):配置selenium、pycharm(windows平台)
    C/C++ 类型内存占用详解
    git常用命令总结
    常用算法2
    本地git关联远程github
    python实现float/double的0x转化
  • 原文地址:https://www.cnblogs.com/life91/p/3396941.html
Copyright © 2020-2023  润新知