201604-3 3路徑解析
問題描述
試題編號: | 201604-3 |
試題名稱: | 路徑解析 |
時間限制: | 1.0s |
記憶體限制: | 256.0MB |
問題描述: | 問題描述 在作業系統中,資料通常以檔案的形式儲存在檔案系統中。檔案系統一般採用層次化的組織形式,由目錄(或者資料夾)和檔案構成,形成一棵樹的形狀。檔案有內容,用於儲存資料。目錄是容器,可包含檔案或其他目錄。同一個目錄下的所有檔案和目錄的名字各不相同,不同目錄下可以有名字相同的檔案或目錄。 有一個特殊的目錄被稱為根目錄,是整個檔案系統形成的這棵樹的根節點,用一個單獨的 / 符號表示。在作業系統中,有當前目錄的概念,表示使用者目前正在工作的目錄。根據出發點可以把路徑分為兩類: 絕對路徑:以 / 符號開頭,表示從根目錄開始構建的路徑。 相對路徑:不以 / 符號開頭,表示從當前目錄開始構建的路徑。 例如,有一個檔案系統的結構如下圖所示。在這個檔案系統中,有根目錄 / 和其他普通目錄 d1、d2、d3、d4,以及檔案 f1、f2、f3、f1、f4。其中,兩個 f1 是同名檔案,但在不同的目錄下。 對於 d4 目錄下的 f1 檔案,可以用絕對路徑 /d2/d4/f1 來指定。如果當前目錄是 /d2/d3,這個檔案也可以用相對路徑 ../d4/f1 來指定,這裡 .. 表示上一級目錄(注意,根目錄的上一級目錄是它本身)。還有 . 表示本目錄,例如 /d1/./f1 指定的就是 /d1/f1。注意,如果有多個連續的 / 出現,其效果等同於一個 /,例如 /d1///f1 指定的也是 /d1/f1。 本題會給出一些路徑,要求對於每個路徑,給出正規化以後的形式。一個路徑經過正規化操作後,其指定的檔案不變,但是會變成一個不包含 . 和 .. 的絕對路徑,且不包含連續多個 / 符號。如果一個路徑以 / 結尾,那麼它代表的一定是一個目錄,正規化操作要去掉結尾的 /。若這個路徑代表根目錄,則正規化操作的結果是 /。若路徑為空字串,則正規化操作的結果是當前目錄。 輸入格式 第一行包含一個整數 P,表示需要進行正規化操作的路徑個數。 輸出格式 共 P 行,每行一個字串,表示經過正規化操作後的路徑,順序與輸入對應。 樣例輸入 7 樣例輸出 /d2/d4/f1 評測用例規模與約定 1 ≤ P ≤ 10。 |
本題的大意是最輸入的每個字串進行處理,列出需要正規化修改的幾種情況:
1、包含一個.,這種可以直接去掉
2、包含..,這種情況要判斷..的前面是否還有目錄,若沒有目錄,就給他加上當前目錄。然後每遇到一個..就把..的前一個目錄刪掉
3、如果遇到多個/,則只保留一個
4、若結尾是/,則刪掉
5、如果輸入是空串,則表示是當前路徑
然後對每個字串進行上述判斷和操作,需要用量三個函式:find函式,用來查詢字串中是否包含某個子串。rfind函式,與find類似,只是反向查詢,在遇到兩個點時向前查詢目錄時用到。erase函式,用來刪除字串中的一段子串。程式碼如下:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int num,pos;
string cur,line;
cin>>num>>cur;
//後面要用到getline函式,所以這裡用getchar接收一下換行符
getchar();
while(num--)
{
getline(cin,line);
//若遇到了空串,則表示是當前目錄
if(line.empty())
line=cur;
//若輸入的開頭是..則加上當前路徑
else if(line[0]!='/')
line=cur+'/'+line;
//處理..的情況
while((pos=line.find("/../"))!=-1)
{
//判斷..是不是在開頭
if(!pos)
line.erase(0,3);
else
{
//從..出現的位置向前查詢最近的目錄
int pos1=line.rfind("/",pos-1);
line.erase(pos1,pos-pos1+3);
}
}
//處理.的情況,直接刪掉
while((pos=line.find("/./"))!=-1)
line.erase(pos,2);
//處理多個/的情況,直接刪掉
while((pos=line.find("//"))!=-1)
line.erase(pos,1);
//刪掉結尾的/
while(line.size()>1 && line[line.size()-1]=='/')
line.erase(line.size()-1,1);
cout<<line<<endl;
}
return 0;
}