11,576,891 members (57,926 online)

# Stack based path conversion.

, 6 Apr 2007 38.5K 707 35
 Rate this:
The following article explains a stack based method to convert absolute path to relative and vice versa.

## Introduction

The following article explains a simple algorithm to convert absolute path to relative and relative to absolute. Sample code also can be found along with the article. This code can be used free of cost but at your on risk. (Test the functions properly before using.)

The code works for windows as well as Linux. A description of the algorithm is given below.

## Absolute path to relative path (Abs2Rel)

Abs2Rel path function takes absolute path as input and returns relative path.

```//------------------------------------------------------------------------------
// Method        : Abs2Rel
// Description        : Convert absolute path to relative path.
// Parameter        : pcAbsPath - Input - Absolute path
// Parameter        : pcRelPath - Output - Relative path
// Parameter        : pcCurrDir - Input - Current Dir/Reference dir path
// Return        : Relative path
// Author        : Boby Thomas Pazheparampil April 2006
//------------------------------------------------------------------------------
char * Abs2Rel(char *pcAbsPath, char *pcRelPath, char* pcCurrDir)

```

### Operation.

Following sequence will explain the conversion process.

For example consider the abs path "/cygdrive/d/boby/india/boby.txt", and reference directory "/cygdrive/d/try/path_conv"

Step 1: First extract the path parameters into stacks.

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 boby.txt india path_conv boby try d d cygdrive cygdrive

Step 2: Push the size difference of stacks into output stack. If the absolute path stack size is more, push the actual content of the stack "tmpStackAbsPath" into the stack "tmpStackOutput". If the size of the stack "tmpStackCurrPath" is more, add an ellipse ("..") into output path "pcRelPath".

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 india path_conv boby try d d cygdrive cygdrive boby.txt

Step 3: Compare the tops of stacks "tmpStackAbsPath" and "tmpStackCurrPath". If it is matching, add into queue for later possible use. (If there is a mismatch in lower layers of stack, this queue will be used). If it is not matching like in the example above, contents of queue will be pushed to output stack. After pushing queue to "tmpStackOutput", top of "tmpStackAbsPath" will be pushed to stack "tmpStackOutput". Also an ellipse will be added to "pcRelPath", the output relative path.

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 boby try d d india cygdrive cygdrive boby.txt

pcRelPath = "..\"

Step 4: Repeat the same process till the end of stacks.

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 boby D d india cygdrive cygdrive boby.txt

pcRelPath = "..\..\"

Step 5: Repeat the same process till the end of stacks.

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 d boby india cygdrive cygdrive boby.txt

pcRelPath = "..\..\"

Step 6: Repeat the same process till the end of stacks.

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 cygdrive d boby india boby.txt

pcRelPath = "..\..\"

Step 7: Once the "tmpStackAbsPath" and "tmpStackCurrPath" are exhausted, move the content of "tmpStackOutput" to the output string pcRelPath .

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 cygdrive d india boby.txt

pcRelPath = "..\..\boby\"

Step 8: Once the "tmpStackAbsPath" and "tmpStackCurrPath" are exhausted, move the content of "tmpStackOutput" to the output string pcRelPath .

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 cygdrive d boby.txt

pcRelPath = "..\..\boby\India\"

Step 9: Continue the process till the "tmpStackOutput" exhausts.

tmpStackAbsPath tmpStackCurrPath tmpStackOutput tmpMatchQueue

 cygdrive d

pcRelPath = "..\..\boby\india\ boby.txt"

## Relative path to absolute path (Rel2Abs)

Abs2Rel path function takes absolute path as input and returns relative path.

```//------------------------------------------------------------------------------
// Method        : Rel2Abs
// Description    : Convert absolute path to relative path.
// Parameter    : pcRelPath - Input - Relative path
// Parameter    : pcAbsPath - Output - Absolute path
// Parameter    : pcCurrDir - Input - Current Dir/Reference dir path
// Return        : Absolute path
// Author        : Boby Thomas Pazheparampil April 2006
//------------------------------------------------------------------------------

char * Rel2Abs(char *pcRelPath, char *pcAbsPath, char* pcCurrDir)

```

### Operation.

Following sequence will explain the conversion process.

For example consider the relative path "../../boby/../temp.txt" and reference directory "/cygdrive/d/try/path_conv"

Step 1: First extract the relative path into queue "tmpQueueRelPath".

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt .. boby .. ..

Step 2: Then convert the reference path into stack "tmpStackCurrPath".

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt .. boby .. path_conv .. try d cygdrive

Step 3: Take entries from the front of the queue "tmpQueueRelPath". If it is an ellipse, pop out the last entry in the stack "tmpStackCurrPath". If the front entry in the queue "tmpQueueRelPath" is not ellipse, push the entry into stack "tmpStackCurrPath".

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt .. boby .. try d cygdrive

Step 4: Continue the same process until the queue "tmpQueueRelPath" exhausts.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt .. boby d cygdrive

Step 5: Continue the same process until the queue "tmpQueueRelPath" exhausts.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt .. boby d cygdrive

Step 6: Continue the same process until the queue "tmpQueueRelPath" exhausts.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt d cygdrive

Step 7: Continue the same process until the queue "tmpQueueRelPath" exhausts.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt d cygdrive

Step 8: Once the queue "tmpQueueRelPath" exhausts, pop the content of the stack "tmpStackCurrPath" and push it to the stack "tmpStackOutput".

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 d cygdrive temp.txt

Step 9: Repeat the process till the stack "tmpStackCurrPath" exhausts.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 d cygdrive temp.txt

Step 10: Repeat the process till the stack "tmpStackCurrPath" exhausts.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 cygdrive d temp.txt

Step 11: Once the stack "tmpStackCurrPath" is empty, take the content into absolute return path string.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 d temp.txt

pcAbsPath = "/cygdrive/"

Step 12: Repeat the process till stack "tmpStackOutput" is empty.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

 temp.txt

pcAbsPath = "/cygdrive/d/"

Step 13: Repeat the process till stack "tmpStackOutput" is empty.

tmpQueueRelPath tmpStackCurrPath tmpStackOutput

pcAbsPath = "/cygdrive/d/ temp.txt"

## Summary

We can think of lots of different methods for the above implementation. Feedback about this method will be greatly appreciated. Contact me at bobypt@gmail.com.

boby

D

d

india

cygdrive

cygdrive

boby.txt

pcRelPath  = “..\..\”

Step 5: Repeat the same process till the end of stacks.

tmpStackAbsPath                tmpStackCurrPath                  tmpStackOutput                    tmpMatchQueue

 d boby india cygdrive cygdrive boby.txt

pcRelPath  = “..\..\”

Step 6: Repeat the same process till the end of stacks.

tmpStackAbsPath                tmpStackCurrPath                  tmpStackOutput                    tmpMatchQueue

 cygdrive d boby india boby.txt

pcRelPath  = “..\..\”

Step 7: Once the “tmpStackAbsPath” and “tmpStackCurrPath” are exhausted, move the content of “tmpStackOutput” to the output string pcRelPath .

tmpStackAbsPath                tmpStackCurrPath                  tmpStackOutput                    tmpMatchQueue

 cygdrive d india boby.txt

pcRelPath  = “..\..\boby\”

Step 8: Once the “tmpStackAbsPath” and “tmpStackCurrPath” are exhausted, move the content of “tmpStackOutput” to the output string pcRelPath .

tmpStackAbsPath                tmpStackCurrPath                  tmpStackOutput                    tmpMatchQueue

 cygdrive d boby.txt

pcRelPath  = “..\..\boby\India\”

Step 9: Continue the process till the “tmpStackOutput” exhausts.

tmpStackAbsPath                tmpStackCurrPath                  tmpStackOutput                    tmpMatchQueue

 cygdrive d

pcRelPath  = “..\..\boby\india\ boby.txt”

## Relative path to absolute path (Rel2Abs)

Abs2Rel path function takes absolute path as input and returns relative path.

```//------------------------------------------------------------------------------
// Method        : Rel2Abs
// Description    : Convert absolute path to relative path.
// Parameter    : pcRelPath - Input - Relative path
// Parameter    : pcAbsPath - Output - Absolute path
// Parameter    : pcCurrDir - Input - Current Dir/Reference dir path
// Return        : Absolute path
// Author        : Boby Thomas Pazheparampil April 2006
//------------------------------------------------------------------------------

char * Rel2Abs(char *pcRelPath, char *pcAbsPath, char* pcCurrDir)

```

### Operation.

Following sequence will explain the conversion process.

For example consider the relative path “../../boby/../temp.txt" and reference directory “/cygdrive/d/try/path_conv”

Step 1: First extract the relative path into queue “tmpQueueRelPath”.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt .. boby .. ..

Step 2: Then convert the reference path into stack “tmpStackCurrPath”.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt .. boby .. path_conv .. try d cygdrive

Step 3: Take entries from the front of the queue “tmpQueueRelPath”. If it is an ellipse, pop out the last entry in the stack “tmpStackCurrPath”. If the front entry in the queue “tmpQueueRelPath” is not ellipse, push the entry into stack “tmpStackCurrPath”.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt .. boby .. try d cygdrive

Step 4: Continue the same process until the queue “tmpQueueRelPath” exhausts.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt .. boby d cygdrive

Step 5: Continue the same process until the queue “tmpQueueRelPath” exhausts.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt .. boby d cygdrive

Step 6: Continue the same process until the queue “tmpQueueRelPath” exhausts.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt d cygdrive

Step 7: Continue the same process until the queue “tmpQueueRelPath” exhausts.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt d cygdrive

Step 8: Once the queue “tmpQueueRelPath” exhausts, pop the content of the stack “tmpStackCurrPath” and push it to the stack “tmpStackOutput”.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 d cygdrive temp.txt

Step 9: Repeat the process till the stack “tmpStackCurrPath” exhausts.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 d cygdrive temp.txt

Step 10: Repeat the process till the stack “tmpStackCurrPath” exhausts.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 cygdrive d temp.txt

Step 11: Once the stack “tmpStackCurrPath” is empty, take the content into absolute return path string.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 d temp.txt

pcAbsPath = “/cygdrive/

Step 12: Repeat the process till stack “tmpStackOutput” is empty.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

 temp.txt

pcAbsPath = “/cygdrive/d/

Step 13: Repeat the process till stack “tmpStackOutput” is empty.

tmpQueueRelPath              tmpStackCurrPath                   tmpStackOutput

pcAbsPath = “/cygdrive/d/ temp.txt

## Summary

We can think of lots of different methods for the above implementation. Feedback about this method will be greatly appreciated. Contact me at bobypt@gmail.com.

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

## About the Author

 Software Developer (Senior) DWS Australia

## Comments and Discussions

 First Prev Next
 Bug on PC - case sensitive R o n n y9-Jun-07 3:48 R o n n y 9-Jun-07 3:48
 Very useful, but this algorithm is not always correct Shura Kotov29-Aug-06 20:53 Shura Kotov 29-Aug-06 20:53
 The problem is in string comparison type - it should be case not sensitive! The other thing: the class is not supporting an UNICODE. Here is my overwieved class version with UNICODE support, that from my point of view little bit universal (with default current directory parameter): // The class definition: #define path_separator _T("\\") #define path_sep_char _T('\\') typedef queue QueuePtrChar; typedef stack StackPtrChar; class CPathConvertor { public: friend struct pathInitializer; CPathConvertor(); virtual ~CPathConvertor(); static LPCTSTR Relative2Absolute(LPCTSTR pcRelPath, LPTSTR pcAbsPath, LPCTSTR pcCurrDir = _T("")); static LPCTSTR Absolute2Relative(LPCTSTR pcAbsPath, LPTSTR pcRelPath, LPCTSTR pcCurrDir = _T("")); static int Relative2Backup(LPCTSTR pcRelPath, LPTSTR pcBackupPath, LPCTSTR pcBackupDir); protected: static wstring szCurrentDirectory; }; struct pathInitializer { pathInitializer() { TCHAR szCurDir[MAX_PATH]; GetCurrentDirectory(MAX_PATH, szCurDir); CPathConvertor::szCurrentDirectory = szCurDir; } }; // the class implementation wstring CPathConvertor::szCurrentDirectory = _T(""); pathInitializer once; CPathConvertor::CPathConvertor() { } CPathConvertor::~CPathConvertor() { } LPCTSTR CPathConvertor::Relative2Absolute(LPCTSTR pcRelPath, LPTSTR pcAbsPath, LPCTSTR pcCurrDir) { TCHAR acTmpCurrDir[MAX_PATH]; TCHAR acTmpRelPath[MAX_PATH]; if(_tcslen(pcCurrDir)) _tcscpy(acTmpCurrDir, pcCurrDir); else _tcscpy(acTmpCurrDir, szCurrentDirectory.data()); _tcscpy(acTmpRelPath, pcRelPath); QueuePtrChar tmpQueueRelPath; StackPtrChar tmpStackCurrPath; StackPtrChar tmpStackOutPath; TCHAR *sTmp = _tcstok(acTmpRelPath, path_separator); while(sTmp) { tmpQueueRelPath.push(sTmp); sTmp = _tcstok(0, path_separator); } sTmp = _tcstok(acTmpCurrDir,path_separator); while(sTmp) { tmpStackCurrPath.push(sTmp); sTmp = _tcstok(0, path_separator); } while(tmpQueueRelPath.size() > 0) { TCHAR *pcTmp = tmpQueueRelPath.front(); if(0 == _tcsicmp(pcTmp, _T(".."))) tmpStackCurrPath.pop(); else tmpStackCurrPath.push(pcTmp); tmpQueueRelPath.pop(); } while(!tmpStackCurrPath.empty()) { tmpStackOutPath.push(tmpStackCurrPath.top()); tmpStackCurrPath.pop(); } sTmp = pcAbsPath; while(!tmpStackOutPath.empty()) { TCHAR *pcTmp = tmpStackOutPath.top(); while(*pcTmp != _T('\0')) *sTmp++ = *pcTmp++; tmpStackOutPath.pop(); *sTmp++ = path_sep_char; } *(--sTmp) = _T('\0'); return pcAbsPath; } LPCTSTR CPathConvertor::Absolute2Relative(LPCTSTR pcAbsPath, LPTSTR pcRelPath, LPCTSTR pcCurrDir) { TCHAR acTmpCurrDir[MAX_PATH]; TCHAR acTmpAbsPath[MAX_PATH]; if(_tcslen(pcCurrDir)) _tcscpy(acTmpCurrDir, pcCurrDir); else _tcscpy(acTmpCurrDir, szCurrentDirectory.data()); _tcscpy(acTmpAbsPath,pcAbsPath); StackPtrChar tmpStackAbsPath; StackPtrChar tmpStackCurrPath; StackPtrChar tmpStackOutput; QueuePtrChar tmpMatchQueue; TCHAR *sTmp = _tcstok(acTmpAbsPath,path_separator); while(sTmp) { tmpStackAbsPath.push(sTmp); sTmp = _tcstok(0, path_separator); } sTmp = _tcstok(acTmpCurrDir,path_separator); while(sTmp) { tmpStackCurrPath.push(sTmp); sTmp = _tcstok(0, path_separator); } sTmp = pcRelPath; while(tmpStackCurrPath.size() > tmpStackAbsPath.size() ) { *sTmp++ = '.'; *sTmp++ = '.'; *sTmp++ = path_sep_char; tmpStackCurrPath.pop(); } while(tmpStackAbsPath.size() > tmpStackCurrPath.size() ) { TCHAR *pcTmp = tmpStackAbsPath.top(); tmpStackOutput.push(pcTmp); tmpStackAbsPath.pop(); } while(!tmpStackAbsPath.empty()) //while(tmpStackAbsPath.size() > 0) { if(_tcsicmp(tmpStackAbsPath.top(),tmpStackCurrPath.top())== 0 ) tmpMatchQueue.push(tmpStackAbsPath.top()); else { while(!tmpMatchQueue.empty()) //while(tmpMatchQueue.size() > 0) tmpStackOutput.push(tmpMatchQueue.front()); tmpStackOutput.push(tmpStackAbsPath.top()); *sTmp++ = _T('.'); *sTmp++ = _T('.'); *sTmp++ = path_sep_char; } tmpStackAbsPath.pop(); tmpStackCurrPath.pop(); } while(!tmpStackOutput.empty()) //while(tmpStackOutput.size() > 0) { TCHAR *pcTmp = tmpStackOutput.top(); while(*pcTmp != _T('\0')) *sTmp++ = *pcTmp++; tmpStackOutput.pop(); *sTmp++ = path_sep_char; } *(--sTmp) = _T('\0'); return pcRelPath; } Alex Kotliarker Software Engineer Magal Security Systems, Israel
 simple and functional Bila128-Aug-06 6:04 Bila1 28-Aug-06 6:04
 These functions exist in the windows shell and CRT Eric Gur18-Apr-06 10:55 Eric Gur 18-Apr-06 10:55
 Re: These functions exist in the windows shell and CRT Boby Thomas P18-Apr-06 21:53 Boby Thomas P 18-Apr-06 21:53
 Re: These functions exist in the windows shell and CRT Eric Gur19-Apr-06 9:46 Eric Gur 19-Apr-06 9:46
 Another way DavidCrow18-Apr-06 3:17 DavidCrow 18-Apr-06 3:17
 Nice logic prasad_v_k17-Apr-06 19:05 prasad_v_k 17-Apr-06 19:05
 Re: Nice logic Amr Shahin5-Nov-06 21:03 Amr Shahin 5-Nov-06 21:03
 Code is not DBCS-aware Michael Dunn16-Apr-06 6:35 Michael Dunn 16-Apr-06 6:35
 nice logic ismail2315-Apr-06 21:45 ismail23 15-Apr-06 21:45
 Notes YoSilver15-Apr-06 10:33 YoSilver 15-Apr-06 10:33