GetRelativePath (C++)

Determines the relative path of a file name to a reference directory.

Archived content: This source code is currently inactive and may be outdated or no longer maintained or functional.

Wenn der Pfad zu einer Datei abgespeichert werden soll, kann man ihn relativ zu einem definierten Ursprung (z. B. einer Projektdatei, die auf die andere Datei zeigt) oder absolut im gesamten Dateisystem angeben. Je nach Anwendung kann das eine oder das andere praktischer sein. Den absoluten Pfad zu speichern ist kein Kunstwerk, den hat man ja sowieso beim Auswählen oder Öffnen der Datei. Aber den kürzesten relativen Pfad von einer Datei zur anderen zu finden, das erfordert schon mehr Aufwand. Diese Arbeit nimmt die hier vorgestellte GetRelativePath-Funktion ab.

Eine CString-Implementierung ist ebenfalls verfügbar.

Relative Pfade in C#? Weiter zur C#-Version dieser Funktion…

Note on the code quality: The content on this page is possibly a bit outdated. I’m not using C++ anymore for quite some time, but I would like to keep the existing and once useful functions available.

Download

GetRelativePath.cpp2.2 KiBQuelltext der GetRelativePath-Funktion

Contents of the file GetRelativePath.cpp:

// Gets the relative path of strPath (FILE) to strReference (DIRECTORY).
//
// Both filenames must be absolute names or I guarantee for nothing!
// Moreover, strReference must either be a FILE name or end with '\\'.
//
// Dependencies: CString (more dependency functions are included below)
//
// Web: http://unclassified.software/source/getrelativepath
//
CString GetRelativePath(CString strPath, CString strReference)
{
    int iPart;
    int iRemain;
    CString strOut;

    for (iPart = 0; iPart < StringPartCount(strPath, '\\'); iPart++)
    {
        if (StringPart(strPath, '\\', iPart).
            CompareNoCase(StringPart(strReference, '\\', iPart)))
        {
            // both strings differ in part# iPart
            if (iPart == 0)
            {
                // other drive must be specified entirely
                return strPath;
            }
            else
            {
                // first difference anywhere in a subfolder

                // determine number of remaining directory layers to the reference
                iRemain = StringPartCount(strReference, '\\') - 1 - iPart;
                while (iRemain--)
                    strOut += "..\\";

                // differing path
                strOut += strPath.Mid(StringPartBegin(strPath, '\\', iPart));

                return strOut;
            }
        }
    }

    // no difference
    return ShellSplitLast(strPath);
}

// Dependencies:

CString StringPart(CString str, char cDelimiter, int nIndex)
{
    if (str.Find(cDelimiter) == -1) return str;

    int iPos = 0;
    int iEnd;
    CString str2;

    while (nIndex--)
    {
        iPos = str.Find(cDelimiter, iPos) + 1;
        if (!iPos) return str2;
    }

    iEnd = str.Find(cDelimiter, iPos);
    if (iEnd == -1) iEnd = str.GetLength();

    str2 = str.Mid(iPos, iEnd - iPos);

    return str2;
}

int StringPartCount(CString str, char cDelimiter)
{
    if (str.IsEmpty()) return 0;
    return str.Remove(cDelimiter) + 1;
}

int StringPartBegin(CString str, char cDelimiter, int nIndex)
{
    if (str.Find(cDelimiter) == -1) return 0;
    if (str.IsEmpty()) return 0;
    if (nIndex == 0) return 0;

    int iPos = 0;
    while (nIndex--)
    {
        iPos = str.Find(cDelimiter, iPos) + 1;
        if (!iPos) return iPos;
    }

    return iPos;
}

CString ShellGetLast(CString strPath)
{
    int pos = strPath.ReverseFind('\\');
    return strPath.Mid(pos + 1, strPath.GetLength() - pos - 1);
}

CString ShellSplitLast(CString strPath)
{
    int pos = strPath.ReverseFind('\\');
    return strPath.Left(pos);
}

Licence and terms of use

This software is freely available as source code and compiled version, without restrictions (“public domain”). There is no warranty, not even for merchantability or fitness for a particular purpose. I am not liable for any damage caused through appropriate or inappropriate use.

Statistic data

  • Created on 2007-04-02.