JAVA CCF-201604-3 路径解析

欢迎访问我的CCF认证解题目录

 

题目描述

 

思路过程

整理一下题目规则

  • 绝对路径:以“/”开头
  • 相对路径:以“..”或“.”开头
  • 空字符串表示当前目录
  • 对于“.”,如果在开头,则替换为当前目录,如果不在开头,则没意义
  • 对于“..”,如果在开头,则替换为当前目录的上一级目录,如果不在开头,则表示目前所在目录的上一级目录
  • 根目录的上一级目录为根目录
  • 连续的“///”相当于“/”
  • 输出时要去掉结尾的“/”,如果只有“/”,则不用去除

这个题目我第一次写没有满分,只得了70分。思路如下:

用father变量表示当前目录,用ffather表示当前目录的上一目录,而后读入所有的路径,对于每个路径,判断是否为空字符串,如果是,则str=father,如果是以“..”开头,则str = ffather+str(去除了前面两个..),如果是以“.”开头,则str = 当前目录+str。最后去除“.”和重复的“/”。

输出的话,对于每个路径(经过上面的步骤,现在只需考虑“..”),查找“..”的下标,如果找到,用temp记录“..”后面的内容,接着判断是否为两层结构,如果是的话,str就去掉一层“/”后加上temp,如果不是,则str直接为“/”+temp。最后输出时检测是否为“/”结尾

没错,我直接在原有字符串上硬刚w(゚Д゚)w,跟后面的满分思路差远了

 

错误的地方:判断开头部分,我只是判断开头是否为“..”和“.”,如果开头是“...”呢?而且我判断的时候也没有加上等于号,如果刚好是两位(..)和一位(.)我也没进行判断(╯‵)╯︵┻━┻

总结:对于匹配,我只处理了前面部分,后面如果有相同的前缀我也一样处理

70分代码

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		in.nextLine();
		String father = in.nextLine();
		String ffather = "/";
		if ( father.matches("/[^/]+/.+") ) {//当前目录有两层
			ffather = father.substring(0, father.lastIndexOf('/') );
		}
		String[] str = new String[n];
		for ( int i = 0; i < str.length; i++ ) {
			str[i] = in.nextLine();
			
			//空字符串
			if ( str[i].equals("") ) str[i] = father;
			
                        //这里开始错了,是>=,不是>,而且我只判断了前两位,如果名字为“...”就错了
                        //而且如果是“...”的话,输出也是错的
			//以“..”开头
			if ( str[i].length() > 2 && str[i].substring(0, 2).equals("..") ) {
				if ( str[i].length() > 3 ) str[i] = ffather + str[i].substring(2);
				else str[i] = ffather;
			} 
			//如果开头是.,则替换
			else if ( str[i].length() > 1 && str[i].charAt(0) == '.' ) {
				if ( str[i].length() > 2 ) str[i] = father+str[i].substring(1);
				else str[i] = father;
				
			}
			
			str[i] = str[i].replaceAll("/\\.(?!\\.)", "");//删除“/.”
			str[i] = str[i].replaceAll("/+", "/");//删除重复“//”
		}
		
		//没有连续的“//”,没有以“.”和“..”开头,没有空字符串,都是以“/”开头
		//没有“.”,只需处理“..”
		for ( int i = 0; i < str.length; i++ ) {
			for ( int index = str[i].indexOf(".."); index != -1; index = str[i].indexOf("..")) {
				String temp = "";//“..”后面的内容
				//获取“..”后面的内容
				if ( str[i].length() > index + 2 ) temp = str[i].substring(index+2);
				
				//去除“..”的前一目录
//				System.out.println(str[i].substring(0, str[i].lastIndexOf("/", index)));
				if ( str[i].substring(0, str[i].lastIndexOf("/", index)).matches("/[^/]+/.+") ) {
					str[i] = str[i].substring(0, str[i].lastIndexOf("/", index-2))+temp;
				} else str[i] = "/"+temp;
				
				//去除连续的“//”
				str[i] = str[i].replaceAll("/+", "/");
			}
			
			//输出去掉结尾的“/”
			if ( str[i].length() > 1 && str[i].charAt(str[i].length()-1) == '/' ) {
				System.out.println(str[i].substring(0, str[i].length()-1));
			} else System.out.println(str[i]);
		}
	}

}

 

100分思路

参考了网上大佬的思路,用path表示当前路径,用str读入路径,如果为空,str=path,如果不是“/”开头,说明不是绝对路径,str=path+'/'+str,去除连续的"/"。此时只需正规化就好了。

用split分割字符串,定义一个向量数组,分割完后,遍历数组。

如果是"."就跳过,如果是".."且向量数组的大小大于0,就删除最后一个(上一目录),如果不是"..",就加入向量数组

接着按格式输出就ok了,网上大佬就是大佬,思路好简洁,想起我的硬刚,留下了学渣的眼泪/(ㄒoㄒ)/~~。

 

100分代码

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		in.nextLine();
		String path = in.nextLine();//当前路径
		
		for ( int i = 0; i < n; i++ ) {
			String str = in.nextLine();
			if ( str.equals("") ) str = path;//空字符串
			if ( str.charAt(0) != '/' ) str = path + '/' + str;//不是绝对路径
			str = str.replaceAll("/+", "/");//去除连续的“/”
			String[] temp = str.split("/");
			ArrayList<String> ans = new ArrayList<String>();
			for ( int j = 1; j < temp.length; j++ ) {
				//j=1开始,第一个是“”,跳过,若当前目录为“/”的话,分割完后length==0,不影响
				if ( temp[j].equals(".") ) continue;//读者可以思考一下这个为什么不可以省略
				else if ( temp[j].equals("..") && ans.size() > 0 ) ans.remove(ans.size()-1);
				else if ( !temp[j].equals("..") ) ans.add(temp[j]);
			}
			
			System.out.print("/");//读者可以思考一下为什么不直接放for循环里
			for ( int j = 0; j < ans.size(); j++ ) {
				if ( j != 0 ) System.out.print("/");
				System.out.print(ans.get(j));
			}
			System.out.println();
		}
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值