1. 程式人生 > >CCF CSP 201604-3 路徑解析

CCF CSP 201604-3 路徑解析

#問題描述   在作業系統中,資料通常以檔案的形式儲存在檔案系統中。檔案系統一般採用層次化的組織形式,由目錄(或者資料夾)和檔案構成,形成一棵樹的形狀。檔案有內容,用於儲存資料。目錄是容器,可包含檔案或其他目錄。同一個目錄下的所有檔案和目錄的名字各不相同,不同目錄下可以有名字相同的檔案或目錄。   為了指定檔案系統中的某個檔案,需要用路徑來定位。在類 Unix 系統(Linux、Max OS X、FreeBSD等)中,路徑由若干部分構成,每個部分是一個目錄或者檔案的名字,相鄰兩個部分之間用 / 符號分隔。   有一個特殊的目錄被稱為根目錄,是整個檔案系統形成的這棵樹的根節點,用一個單獨的 / 符號表示。在作業系統中,有當前目錄的概念,表示使用者目前正在工作的目錄。根據出發點可以把路徑分為兩類:   1. 絕對路徑:以 / 符號開頭,表示從根目錄開始構建的路徑。   2. 相對路徑:不以 / 符號開頭,表示從當前目錄開始構建的路徑。

例如,有一個檔案系統的結構如下圖所示。在這個檔案系統中,有根目錄 / 和其他普通目錄 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 行,每行包含一個字串,表示需要進行正規化操作的路徑。 #輸出格式   共 P 行,每行一個字串,表示經過正規化操作後的路徑,順序與輸入對應。 #樣例輸入 7 /d2/d3 /d2/d4/f1 …/d4/f1 /d1/./f1 /d1///f1 /d1/ /// /d1/…/…/d2 #樣例輸出 /d2/d4/f1 /d2/d4/f1 /d1/f1 /d1/f1 /d1 / /d2 #評測用例規模與約定   1 ≤ P ≤ 10。   檔案和目錄的名字只包含大小寫字母、數字和小數點 .、減號 - 以及下劃線 _。   不會有檔案或目錄的名字是 . 或 … ,它們具有題目描述中給出的特殊含義。   輸入的所有路徑每個長度不超過 1000 個字元。   輸入的當前目錄保證是一個經過正規化操作後的路徑。   對於前 30% 的測試用例,需要正規化的路徑的組成部分不包含 . 和 … 。   對於前 60% 的測試用例,需要正規化的路徑都是絕對路徑。 #原始碼

/*目前該題的思路是化繁為簡,把相對路徑轉化為絕對路徑來處理,
查詢上一級目錄用find來查詢*/

#include <iostream>
#include <fstream> 
#include <cstring>
#include <map>
#include <vector> 

using namespace std;

int main()
{
	freopen("input/analyse.txt","r",stdin);
	int p;
	string pwd;
	cin>>p;
	cin.get();
	getline(cin,pwd); 
	while(p--)
	{
		string dir,output="/";
		getline(cin,dir);
		if(dir==""){  //考慮字串為空的情況 
			cout<<pwd<<endl;
			continue;
		}
		if(dir[0]!='/')
		{
			dir=pwd+"/"+dir;  //將相對路徑轉化為絕對路徑 
		}
		dir+="/";
		size_t lpos=0;
		size_t rpos=dir.find('/',1);
		while(rpos!=string::npos)
		{
			if(rpos-lpos==1){
				lpos=rpos;
				rpos=dir.find('/',lpos+1);
				continue;
			}
			string temp;
			temp=dir.substr(lpos+1,rpos-lpos-1);
			if(temp==".."){
				size_t fpos=output.rfind('/');
				size_t spos=output.rfind('/',fpos-1);
				if(fpos!=spos){  //當前路徑不為根路徑 
					output.erase(spos+1,string::npos);
				}
			}
			else if(temp!="."){
				output+=temp+"/";
			}
			lpos=rpos;
			rpos=dir.find('/',lpos+1);
		}
		if(output.length()!=1)
			output.erase(output.length()-1);
		cout<<output<<endl;
	}
	
	return 0;
}