上一篇的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个时,将退出。

     // preprocess.
while ( index < len )
{
// merge duplicate character -- '/'
for ( cnt = ;
index < len && path[index] == '/';
++index, ++cnt );
if ( cnt > )
{
tmp_path[top++] = '/';
} // delete only dot
for ( cnt = ;
index < len && path[index] == '.';
++index, ++cnt );
// Case 1: delete one dot.
if ( top > && tmp_path[top - ] == '/' && cnt == )
{
++index;
}
// Case 2: copy two dots.
else if ( cnt == )
{
index -= cnt;
}
// Case 3: if more than two dots, it is error.
else if ( cnt > )
{
fprintf( stderr, "Error.\n" );
// Remember: after free memory, this function could leave.
free( tmp_path ), tmp_path = NULL;
free( result ), result = NULL;
return NULL;
} // copy other characters.
while ( index < len && path[index] != '/' )
{
tmp_path[top++] = path[index++];
}
}

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

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

         // Case 1: the number of '.' is 2;
if ( top > && cnt == )
{
--top;
while ( --top > && result[top] != '/' );
}
// Case 2: "game.gif"
else if ( top > && result[top - ] != '/' && cnt == )
{
result[top++] = '.';
}
// Case 3: "/../../../" -> "/"
else if ( top == )
{
++top;
}

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

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h> char *normalize_path( const char *path )
{
char *result = NULL;
char *tmp_path = NULL;
int top = ;
int cnt = ;
int index = ;
int len = ; assert( path != NULL && path[index] != '\0' && path[index] == '/' );
len = strlen( path );
result = (char *) malloc( sizeof(char) * (len + ) );
assert( result != NULL ); tmp_path = (char *) malloc( sizeof(char) * (len + ) );
if ( tmp_path == NULL )
{
free( result ), result = NULL;
return NULL;
} // preprocess.
while ( index < len )
{
// merge duplicate character -- '/'
for ( cnt = ;
index < len && path[index] == '/';
++index, ++cnt );
if ( cnt > )
{
tmp_path[top++] = '/';
} // delete only dot
for ( cnt = ;
index < len && path[index] == '.';
++index, ++cnt );
// Case 1: delete one dot.
if ( top > && tmp_path[top - ] == '/' && cnt == )
{
++index;
}
// Case 2: copy two dots.
else if ( cnt == )
{
index -= cnt;
}
// Case 3: if more than two dots, it is error.
else if ( cnt > )
{
fprintf( stderr, "Error.\n" );
// Remember: after free memory, this function could leave.
free( tmp_path ), tmp_path = NULL;
free( result ), result = NULL;
return NULL;
} // copy other characters.
while ( index < len && path[index] != '/' )
{
tmp_path[top++] = path[index++];
}
} // other operators.
tmp_path[top] = '\0';
len = top;
for ( index = , top = ; index < len; )
{
// copy other characters except '.'
while ( index < len && tmp_path[index] != '.' )
{
result[top++] = tmp_path[index++];
} // count of point
for ( cnt = ; index < len && tmp_path[index] == '.'; ++index, ++cnt ); // Case 1: the number of '.' is 2;
if ( top > && cnt == )
{
--top;
while ( --top > && result[top] != '/' );
}
// Case 2: "game.gif"
else if ( top > && result[top - ] != '/' && cnt == )
{
result[top++] = '.';
}
// Case 3: "/../../../" -> "/"
else if ( top == )
{
++top;
} }
result[top] = '\0'; // free memory
free( tmp_path ), tmp_path = NULL; return result;
} void output( const char *path )
{
char *result = NULL; result = normalize_path( path );
printf( "Original is %s\nResult is %s\n\n", path, result );
free( result ), result = NULL; free( result );
result = NULL;
} int main()
{
char *path1 = "/home/news/./../tmp/game/../";
char *path2 = "/../../../abc";
char *path3 = "/game/gif.big";
char *path4 = "///abc//..//edf/game.f"; output( path1 );
output( path2 );
output( path3 );
output( path4 ); return ;
}

normalize_path

[算法 笔记]2014年去哪儿网 开发笔试(续)第一题BUG修正的更多相关文章

  1. 算法笔记_108:第四届蓝桥杯软件类省赛真题(JAVA软件开发本科A组)试题解答

     目录 1 世纪末的星期 2 振兴中华 3 梅森素数 4 颠倒的价牌 5 三部排序 6 逆波兰表达式 7 错误票据 8 带分数 9 剪格子 10 大臣的旅费 前言:以下试题解答代码部分仅供参考,若有不 ...

  2. 算法笔记_110:第四届蓝桥杯软件类省赛真题(JAVA软件开发高职高专组部分习题)试题解答

     目录 1 猜年龄 2 组素数 3 第39级台阶 4 核桃的数量 5 打印十字图 6 买不到的数目   前言:以下试题解答代码部分仅供参考,若有不当之处,还请路过的同学提醒一下~ 1 猜年龄 标题: ...

  3. 2014年去哪儿网笔试题--有两个文件context.txt和words.conf,请尝试将他们合并成为一段文字,并打印出来。

    有两个文件context.txt和words.conf,请尝试将他们合并成为一段文字,并打印出来. 这两个文件内容如下: context.txt “并不是每个人都需要$(qunar)自己的粮食,$(f ...

  4. 算法笔记_109:第四届蓝桥杯软件类省赛真题(JAVA软件开发本科B组部分习题)试题解答

    目录 1 马虎的算式 2 黄金连分数 3 有理数类 4 幸运数 5 连号区间数   前言:以下试题解答代码部分仅供参考,若有不当之处,还请路过的同学提醒一下~ 1 马虎的算式 标题: 马虎的算式 小明 ...

  5. 算法笔记_111:第五届蓝桥杯软件类省赛真题(Java本科A组)试题解答

     目录 1 猜年龄 2 李白打酒 3 神奇算式 4 写日志 5 锦标赛 6 六角填数 7 绳圈 8 兰顿蚂蚁 9 斐波那契 10 波动数列   前言:以下试题解答代码部分仅供参考,若有不当之处,还请路 ...

  6. 算法笔记_112:第五届蓝桥杯软件类省赛真题(Java本科B组)试题解答

     目录 1 武功秘籍 2 切面条 3 猜字母 4 大衍数列 5 圆周率 6 奇怪的分式 7 扑克序列 8 分糖果 9 地宫取宝 10 矩阵翻硬币   前言:以下试题解答代码部分仅供参考,若有不当之处, ...

  7. 算法笔记_199:第二届蓝桥杯软件类决赛真题(C语言本科)

    前言:以下代码部分仅供参考,C语言解答部分全部来自网友,Java语言部分部分参考自网友,对于答案的正确性不能完全保证. 试题1 数论中有著名的四方定理:所有自然数至多只要用四个数的平方和就可以表示. ...

  8. 算法笔记_207:第五届蓝桥杯软件类决赛部分真题(Java语言C组)

    目录 1 数字拆分 2 稍大的串   前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 数字拆分 正整数可以表示为若干正整数的累加和. 如,对于正整数n=6,可以分划为: 6 5+1 4+2 4+1+ ...

  9. 2014年百度之星程序设计大赛 资格赛第一题 (longlong)

    解题思路: 只要看(A-V)*K 这个公式的更新值是否大于等于A ,大于的话继续循环,否则报错 注意一点,数据会爆int WA代码: #include<stdio.h> int main( ...

随机推荐

  1. 也谈SWD接口协议分析

    这几日看到坛里有几个关于SWD协议相关的文章,自己也尝试了下,有点体会,也有些疑惑,写出来与大家分享和交流下.    以下我的模拟SWD接口的板子简称为Host,目标MCU(即我要连接的板子)简称为T ...

  2. Samba 服务使用的端口和协议(是一组TCP UDP协议的组合,主要使用CIFS协议,有一个Java例子)

    Samba服务所使用的端口和协议: 1)Port 137 (UDP) - NetBIOS 名字服务 : nmbd 2)Port 138 (UDP) - NetBIOS 数据报服务 3)Port 139 ...

  3. 常用Linux命令小结

    常用Linux命令小结 Linux下有很多常用的很有用的命令,这种命令用的多了就熟了,对于我来说,如果长时间没有用的话,就容易忘记.当然,可以到时候用man命令查看帮助,但是,到时候查找的话未免有些临 ...

  4. scroll 事件绑定

    var animateBlock={        isVisiable:function(el,wh,st,delta){            delta=delta||200;          ...

  5. wust 1061 链表的合并

    怒刷存在感! ~从此wustoj踏上ty博客这样高端霸气上档次的地方啊啦啦~ 只是顺便看了下保研复试题,原来觉得链表好讨厌,现在数据结构学的没办法了,写了个大概是标准的链表合并的写法吧... #inc ...

  6. weblogic11g 节点管理器 nodemanager

    Weblogic 节点管理器  nodemanager 一.Weblogic  规划 : Server名称 端口 ip 备注 xyyadmin 7001 10.10.54.74 管理server ap ...

  7. python 捕获 shell/bash 脚本的输出结果

    #!/usr/bin/python## get subprocess module import subprocess ## call date command ##p = subprocess.Po ...

  8. leetcode Database3(Nth Highest Salary<—>Consecutive Numbers<—>Department Highest Salary)

    一.Nth Highest Salary Write a SQL query to get the nth highest salary from the Employee table. +----+ ...

  9. Selenium系列教程(2)

    Selenium RC(Selenium远程控制) Selenium RC是一个用Java编写的,允许用户使用无论哪种编程语言对基于Web的应用程序构建测试脚本的工具.Selenium RC克服了Se ...

  10. Codeforces Round #206 div1 C

    CF的专业题解 : The problem was to find greatest d, such that ai ≥ d,  ai mod d ≤ k holds for each i. Let ...