[算法 笔记]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.\n" );

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] != '\0' && 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.\n" );

 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] = '\0';

 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] = '\0';

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\nResult is %s\n\n", 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

 

 

你可能感兴趣的:(bug)