用栈存储之前的目录,每次遇到…/符号之后在栈中寻找应该回退的位置,模拟即可;题目说提到了若路径为空字符串,则正规化操作的结果是当前目录,说明输入中可以读入空的一行,那么应该用getline来读入,否则用cin的话无法读入空行。
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
int main()
{
int p;
string a, b;
cin>>p;
getchar();
getline(cin, a);
vector<string> s, ss;
string temp = "";
for(int i = 1 ; i < a.length() ; ++i)
{
if(a[i] == '/')
{
// cout<<temp<<endl;
s.push_back(temp); //存储当前目录
temp = "";
continue;
}
temp += a[i];
}
// cout<<temp<<endl;
s.push_back(temp);
while(p--)
{
getline(cin, b);
ss.clear();
int flag = 0;
string ans = "/";
for(int i = 0 ; i < b.length() ; ++i)
{
if(b[i] != ' ')
{
flag = 1; //判断是否为空行
break;
}
}
if(flag)
{
stack<string> pre;
stack<int> index;
//cout<<b<<endl;
temp = "";
int ii = 0;
if(b[0] == '/')
ii = 1;
else 如果前几位是../或者./
{
ii = 0;
for(int i = 0 ; i < s.size() ; ++i)
{
pre.push(s[i]); //将当前目录存入栈中
ss.push_back(s[i]);
index.push(i);
}
}
for( ; ii < b.length() ; ++ii)
{
if(b[ii] == '/')
{
//cout<<temp<<" ";
ss.push_back(temp);
temp = "";
continue;
}
temp += b[ii];
}
//cout<<temp<<endl;
ss.push_back(temp);
for(int i = 0 ; i < ss.size() ; ++i)
{
string f = ss[i];
if(f == ".")
{
ss[i] = "";
}
else if(f == "..")
{
if(!pre.empty())
{
string tp = pre.top();
//cout<<"s "<<tp<<endl;
int ind = index.top();
ss[ind] = ""; 回退之后将回退之前的位置清空
pre.pop();
index.pop();
}
ss[i] = "";
}
else
{
//cout<<"d "<<f<<endl;
pre.push(f);
index.push(i);
}
}
string preS = "";
for(int i = 0 ; i < ss.size() ; ++i)
{
if(ss[i] == "")
continue;
if(ss[i] != preS)
ans = ans + ss[i] + "/";
preS = ss[i];
}
if(ans.length() != 1 && ans[ans.length() - 1] == '/')
ans = ans.substr(0, ans.length() - 1); //如果最后一个位置为'/',那么去掉它
}
else
ans = a;
cout<<ans<<endl;
}
}