上一篇的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] != '