解题思路:
题目的重点是在于对字符串的处理。很明显的一个分割处理的标志位是符号’/’,因此我们对每个字符串按照’/‘进行分割读取(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;
}