csp 201604-3 路径解析

图1
解题思路:
题目的重点是在于对字符串的处理。很明显的一个分割处理的标志位是符号’/’,因此我们对每个字符串按照’/‘进行分割读取(read函数部分)。read函数负责将代表文件路径的字符串分割到一个string类型的数组当中。通过对’/‘的位置的读取很容易将每个以’/‘为分隔符的子串加入到数组当中。注意几个连续的’/‘都要跳过当做一个进行处理。若第一个字符为’/‘则代表起始位置为根目录,存在数组中的是空字符串。main函数中首先处理当前目录路径,因为当前目录依然可能是没有被规范化的路径。然后依次循环处理每一个路径字符串。对于每一个路径的第一个子串需要单独处理,如果为空或者为’.‘则当前路径给到结果数组。如果为空串将空串加入结果数组(代表根目录),如果为’…‘则当前路径给到结果数组,然后在当前路径大小大于一时pop_back出一个目录用来取得上一目录(但评测用例似乎没有考虑这一点,即当前目录不会是根目录),其他情况将当前路径给到结果数组,然后结果数组中加入第一个子串即可。然后循环对其他的子串进行分类处理。如果为’…’,则在结果数组大小大于一时pop_back出一个目录用来取得上一目录,只要不为’.’,就将当前子串加入到结果数组当中。最后进行输出的操作,如果结果数组大小为一,只可能是空串,代表根目录,输出’/后换行即可退出当前循环进入下一次循环。否则依次遍历结果数组,打印字符串即可,注意用函数c_str(),最后输出换行符。
注意事项:
1、特别注意对字符串的处理,情况比较复杂,需要认真分类讨论,几个连续的’/'都要跳过当做一个进行处理。
2、可能直接在当前目录的基础上给出后续文件路径,比如当前目录为/d1,然后给出的路径为f1,则输出路径为/d1/f1。
3、根目录可能依然需要规格化处理。
4、很重要的一个问题是因为后面要读取字符串,所以前面cin(或者scanf)以后要用getchar读掉缓冲区的回车。用getline的话则不需要,因为getline读入一行以后结束符并不会放在缓冲区中。
5、注意读每一个文件路径时使用getline而不是cin,cin遇到空格、换行等会跳过,getline不会,因此cin在遇到空串时会跳过,而空串表示的是当前目录。因此用cin只能得90分。第一个字符串当前目录不会有这个问题,因为它本身就代表当前目录,因而不可能是一个空串。
总结:
一道并不困难的题目,主要考察对于字符串的处理,因为需要考虑的情况比较多,所以需要细心地分类处理,csp中这种字符串处理问题还挺常见,比如最近的一道化学方程式问题,所以对字符串的处理方法还是需要掌握。
参考代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
using namespace std;
vector<string> current;//current directory
void read(string &s,vector<string> &v){
    int i,j=0;
    for (i=0; i<s.size(); i=j) {
        j=(int)s.find('/',i);
        if(j!=string::npos)
            v.push_back(s.substr(i,j-i));
        else v.push_back(s.substr(i));
        while (j<s.size()&&s[j]=='/') {
            j++;// ignore '/'
        }
    }
}
int main(int argc, const char * argv[]) {
    int n;
    cin>>n;
    getchar();
    string c;
    cin>>c;
    getchar();
    read(c, current);
    while (n--) {
        vector<string> v;//input
        vector<string> result;//answeår
        getline(cin,c);
        //cin>>c;
        read(c, v);
        if(v.empty()||v[0]==".")//current directory
            result=current;
        else if(v[0]=="")
            result.push_back("");
        else if (v[0]=="..")
        {
            result=current;
            if(current.size()>1)result.pop_back();
        }
        else
        {result=current;result.push_back(v[0]);}
        for (int i=1; i<v.size(); i++) {
            if(v[i]=="..")
            {if(result.size()>1)result.pop_back();}
            else if(v[i]==".")continue;
            else result.push_back(v[i]);
        }
        if(result.size()==1)
          // &&result[0]==""
       {cout<<'/'<<endl;continue;}
        for (int i=1; i<result.size(); i++) {
            printf("/%s",result[i].c_str());
        }
        cout<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值