WEEK6 周记 月模拟题——路径解释_CSP201604-3

一、题意

1.简述

2.样例

Input

7
/d2/d3
/d2/d4/f1
…/d4/f1
/d1/./f1
/d1///f1
/d1/
///
/d1/…/…/d2

Output

/d2/d4/f1
/d2/d4/f1
/d1/f1
/d1/f1
/d1
/
/d2

Hint

在这里插入图片描述

二、算法

主要思路

是一道中级模拟题。思路比较简单,处理字符串较为复杂,如果对于处理字符串的方法很熟悉,这道题应该比较好通过。
思路:利用栈。对于绝对路径,路径栈一开始是空的。对于相对路径,路径栈在一开始则要按顺序压入当前路径中的各个目录。然后以 / / /为分隔符对待正规化的路径进行切分,遇到 “ . . ” “..” .. p o p pop pop栈顶元素,遇到 " . " "." "."或者空(说明是这种情况: " / / / / " "" "////"),则不作任何操作;其他的则直接压入栈。
注意两种边界情况:待正规化的路径为 " / " "/" "/"或者空行,特殊处理即可。


字符串处理方面的技巧

该题可以参考博客:
代码超短的解法
主要要充分利用stringstreamgetline
getline能够处理空行,也就是如果遇到空行,则直接返回一个空串(换句话说也就是结束一次读入),如果是cin,遇到空行不会结束,直到遇到一个能够读的字符,也就是说如果是连续多个\ncin一并忽略,直到遇到不是\n的字符。所以其处理不了空行。
cin遇到换行则停止读入。但是,这个换行还能通过getchar()读进来。所以如果cingetline一块使用的话,需要注意将cin残留的换行读掉,否则如果后面是getline,则读出来是个空串。

三、代码

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <sstream>
#include <stack>
using namespace std;
string curMenu[1010];
int cmidx = 0;

void output(stack<string>& stk){
    if(stk.empty()) return;
    string topstr = stk.top();
    stk.pop();
    output(stk);
    cout<<'/'<<topstr;
}
void clearStream(ostringstream& stream){   //既要清空状态也要清空内容
    stream.clear();
    stream.str("");//清空内容
}
int main() {
    int p;
    cin>>p;
    getchar();  //处理空行
    string str[12];
    getline(cin,str[0],'\n');
    //cin>>str[0];  //当前目录
    const char *sp0 = str[0].c_str();

    //预处理当前目录
    ostringstream stream;
    for (int i = 1; i < str[0].length(); ++i) {
        if(sp0[i]!='/'){
            stream<<sp0[i];
        } else{
            curMenu[cmidx++] = stream.str();
            clearStream(stream);
        }
    }
    if (!stream.str().empty())
        curMenu[cmidx++] = stream.str();

    //处理p个目录
    for (int i = 1; i <= p; ++i) {
        stack<string> stk;
        int isj = 1;  //是否是绝对路径

        getline(cin,str[i],'\n');
        if (str[i].empty()){   //空行
            for (int j = 0; j < cmidx; ++j) {
                stk.push(curMenu[j]);
            }
            //输出
            if (stk.empty()) cout<<'/';
            output(stk);
            cout<<endl;
            continue;
        }

        int lth = str[i].length();
        const char *sp = str[i].c_str();
        if (sp[0]!='/'){  //相对路径
            isj = 0;
            for (int j = 0; j < cmidx; ++j) {
                stk.push(curMenu[j]);
            }
        }

        clearStream(stream);
        bool isok = 0;  //是否可以压栈
        for (int j = isj; j < lth; ++j) {
            string temp;
            if (j == lth-1){
                isok = 1;
                if (sp[j] != '/')
                    stream<<sp[j];
                temp = stream.str();
            }
            else if(sp[j]!='/'){
                stream<<sp[j];
                isok = 0;
            }
            else{  //不是最后一个但是‘/’
                temp = stream.str();
                isok = 1;
                clearStream(stream);
            }

            //压栈
            if(!isok) continue;
            if (temp==".."){
                if(!stk.empty())
                    stk.pop();
            } else if (!temp.empty() && temp!="."){
                stk.push(temp);
            }
        }

        //输出
        if (stk.empty()) cout<<'/';   //如果只有一个/
        output(stk);
        cout<<endl;
    }
    return 0;
}
/*
7
/d2/d3
/d2/d4/f1
../d4/f1
/d1/./f1
/d1///f1
/d1/
///
/d1/../../d2
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值