上一篇的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. ios开发--第三方整理

    一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地址:https://github. ...

  2. unix:///tmp/supervisor.sock no such file

    运行supervisorctl时保错, 修改/etc/supervisor/supervisor.conf文件 将file=/var/run/supervisor.sock 修改为/tmp/super ...

  3. 计算CRC校验值(CRC16和CRC32)(网络传输检验)

    CRC有非常多的模式,我没有全部都做,目前支持 CRC16-Modbus CRC16-X25 CRC32 使用方法 auto data = QByteArray::fromHex( "01 ...

  4. 笔者带你剖析淘宝TDDL(TAOBAO DISTRIBUTE DATA LAYER)

    注:本文部分内容引用本人博客http://gao-xianglong.iteye.com/blog/1973591   前言 在开始讲解淘宝的TDDL(Taobao Distribute Data L ...

  5. 解决版本冲突-使用SVN主干与分支功能

    解决版本冲突-使用SVN主干与分支功能 1  前言 大多数产品开发存在这样一个生命周期:编码.测试.发布,然后不断重复.通常是这样的开发步骤: 1)    开发人员开发完毕某一版本(如版本A)功能后, ...

  6. Java 数据结构之ArrayList

    ArrayList:数组队列,就是动态数组,可以动态的增加和减少元素.实现了ICollection和IList接口.灵活的设置数组的大小 具体的用法: 1.创建:ArrayList list = ne ...

  7. Win XP 如何禁用系统的自动更新

    想关闭系统的自动更新. 打开[控制面板]/[安全中心],发现“自动更新”和“更改安全中心通知我的方式”,都已成了灰色,无法更改. 网上查了一下,找到了这样一个处理方法:将[服务]中一个名为“Autom ...

  8. OpenMp之false sharing

    关于false sharing的文章,网上一大堆了,不过觉得都不太系统,那么下面着重系统说明一下. 先看看外国佬下的定义: In symmetric multiprocessor (SMP) syst ...

  9. make clean vs make clobber

    make is pretty smart, and picks up what has changed from the last build, so if you run repo sync and ...

  10. 如何理解JAVA的跨平台特性

    1.java的跨平台,是指java在运行时是凌驾于os之上,是在jvm中运行的,跟os没有直接联系. 2.java跨平台主要是由java的编译方式决定的,因为java是通过jvm先编译再执行,它编译的 ...