[算法 笔记]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

 

 

原文地址:https://www.cnblogs.com/life91/p/3396941.html