Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   ExtractFilePath für C++ (https://www.delphipraxis.net/104272-extractfilepath-fuer-c.html)

Matze 30. Nov 2007 14:30


ExtractFilePath für C++
 
Hallo zusammen,

verzweifelt versuche ich schon die ganze Zeit das Anwendungsverzeichnis zu ermitteln, doch es will nicht so recht. Versucht habe ich es nach langem Suchen schließlich so:

Code:
char * CMusikManager::SongpfadErmitteln(void)
{
   char * pLetzteBackslashPos;
   unsigned int letzteBackslashPos;
   char programPfad[256];
   char songpfad[256];

   // Pfad zur Anwendung
   GetModuleFileNameA(NULL, programPfad, 256);

   // Exe-Namen entfernen
   pLetzteBackslashPos = strrchr(programPfad, '\\');
   letzteBackslashPos = (int)(pLetzteBackslashPos - programPfad + 1);
   strncpy(songpfad, programPfad, letzteBackslashPos);

   // "\Songs\" anhängen
   strcat(songpfad, "\\Songs\\");

   return songpfad;
}
Wenn ich mir das ausgeben lasse, schaut es jedoch so aus:

Code:
Anwendungspfad:
d:\Eigene Dateien\FHTE\Vorlesungen\Software Engineering1\Projekt_2\MusikManager\
Debug\MusikManager.exe

Anwendungsverzeichnis:
d:\Eigene Dateien\FHTE\Vorlesungen\Software Engineering1\Projekt_2\MusikMa
nager\Debug\╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠d:\Eigene Dateien\FHTE\Vorlesungen\Software Engine
ering1\Projekt_2\MusikManager\Debug\MusikManager.exe

Endgültiger Pfad:
d:\Eigene Dateien\FHTE\Vorlesungen\Software Engineering1\Projekt_2\MusikM
anager\Debug\╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠d:\Eigene Dateien\FHTE\Vorlesungen\Software Engin
eering1\Projekt_2\MusikManager\Debug\MusikManager.exe\Songs\
Ich vermute, im String bzw. Char-Array ist Zufalls-Zeugs enthalten, da ich die Länge auf 256 Zeichen festgelegt habe. Evtl. muss ich nur irgendwi ein #0 anhängen, doch das weiß ich nicht genau.
Was mache ich falsch bzw wie mache ich es richtig?

Herauskommen sollte am Ende dieser Pfad:
d:\Eigene Dateien\FHTE\Vorlesungen\Software Engineering1\Projekt_2\MusikManager\Debug\Songs\

Es grüßt Matze

SirThornberry 30. Nov 2007 14:35

Re: ExtractFilePath für C++
 
uj, was machst du denn hier?
Code:
letzteBackslashPos = (int)(pLetzteBackslashPos - programPfad + 1);
programPfad ist doch ein Array und plötzlich rechnest du damit?
Zudem solltest du die Rückgabe von GetModuleFileNameA auswerten.
Dann vom letzten zeischen rückwärts bis auf 0 oder den ersten Backslash gehen

Matze 30. Nov 2007 14:41

Re: ExtractFilePath für C++
 
Ich habe gelesen, um vom Pointer auf den Index zu kommen, muss man das so rechnen. Verstanden habe ich das, um ehrlich zu sein, nicht.

Das steht so in der MS-Doku:

Code:
// Search backward.
pdest = strrchr( string, ch );
result = (int)(pdest - string + 1);
if ( pdest != NULL )
   printf( "Result:  last %c found at position %d\n", ch, result );
else
   printf( "Result:\t%c not found\n", ch );

SirThornberry 30. Nov 2007 14:44

Re: ExtractFilePath für C++
 
ich hab dir mal fix ExtractFilePath in c geschrieben:
Code:
void extract_file_path(char* path)
{
    int i;
    for (i = strlen(path) - 1; (i >= 0) && (path[i] != '\\'); i--);
    path[i+1] = 0;
}

shmia 30. Nov 2007 14:44

Re: ExtractFilePath für C++
 
Gibt es in C++ denn keine String-Klassen ?
Ich würde gerade in C++ Stringklassen immer diesen alten Techniken von C (char - Buffer fester Grösse) vorziehen.
Mit Stringklassen sind Buffer Overuns quasi unmöglich und die Qualität wird gesteigert.

DeddyH 30. Nov 2007 14:47

Re: ExtractFilePath für C++
 
Jens, kann das sein, dass da ein Fehler drin ist?
Code:
void extract_file_path(char* path)
{
    int i;
    for (i = strlen(path) - 1; (i >= 0) && (path[i] != '\\'); i--); //dieses Semikolon gehört IMO weg
    path[i+1] = 0;
}

SirThornberry 30. Nov 2007 14:49

Re: ExtractFilePath für C++
 
um das ganze mal auf c-ebene fertig zu stellen:
Code:
extract_file_path(programPfad);
strcat(programPfad, "Songs\\");

Matze 30. Nov 2007 14:51

Re: ExtractFilePath für C++
 
Hallo,

Zitat:

Zitat von shmia
Gibt es in C++ denn keine String-Klassen ?

bei einer .NET-Anwendung ja (wobei das die Klassen von .NET sind). Sonst weiß ich es nicht genau.

Danke Jens. Das ist natürlich ein Weg, der einem im Normalfall ale erstes kommt, das komplett manuell zu lösen. Ich dachte nur, es geht auch einfacher. Ich werde das aber mal mit deinem Code versuchen. :)

Gruß

SirThornberry 30. Nov 2007 14:53

Re: ExtractFilePath für C++
 
ganz wichtig:
Code:
return songpfad;
das solltest du unterlassen. Das ist wie in Delphi ein NoGo.
Adressen auf lokale Variablen gibt man nicht zurück. Vielleicht lag da ja dein Fehler.

Ahh, jetzt verstehe ich deinen Ausgangsquelltext. Ja, man kann das Array doch abziehen. Verständlicher ist es wenn du anstelle des Arrays dort die Adresse des Arrays nimmst (&array[0])

Mit deinen Funktionen würde es so aussehen
Code:
programPfad[strrchr(programPfad, '\\') - &programPfad[0]] = 0;
strcpy(songpfad, programPfad);
strcat(songpfad, "\\songs\\");
wobei songpfad eben keine lokale variable sein darf wenn du diese mit return zurück gibst. Übergebe diese Variable lieber als Parameter

Matze 30. Nov 2007 15:01

Re: ExtractFilePath für C++
 
:shock: stimmt! Das ist mir gar nicht aufgefallen. Ich vermisse den "string"-Datentyp in C++. Dieses Char-Pointer-Gefummel ist nervig. Irgendwie muss ich das aber zurückgeben können, ich wüsste jedoch nicht, wie ich das anders machen kann. Eine zeichenkette ist nunmal ein Pointer auf einen Char bzw. auf ein Char-Array.

Nachdem ich deinen Code so abgeändert habe:

Code:
for (int i = strlen(pfad) - 1; (i > 0) && (pfad[i] != '\\'); i--)
{
   pfad[i] = 0;
}
geht er. :)

DeddyH 30. Nov 2007 15:04

Re: ExtractFilePath für C++
 
Hab ich doch gesagt, das Semikolon war zuviel :mrgreen:

Matze 30. Nov 2007 15:05

Re: ExtractFilePath für C++
 
Unter anderem ja. ;)

OregonGhost 30. Nov 2007 15:05

Re: ExtractFilePath für C++
 
Zitat:

Zitat von Matze
Ich vermisse den "string"-Datentyp in C++.

Code:
#include <string>

using std::string;
Was spricht dagegen? :)

SirThornberry 30. Nov 2007 15:05

Re: ExtractFilePath für C++
 
bei mir hat mein source so funktioniert wie ich ihn gepostet hab. Es genügt die abschließende 0 nur ans Ende zu hängen (man muss ja nicht alles mit 0 überschreiben)

@DeddyH: Das Semikolon gehört dort hinn. Denn ich zähle nur i runter und erst wenn ich die richtige position erreicht habe wird die abschließende 0 gesetzt. Die Schleife ist also richtig und funktioniert auch.

Matze 30. Nov 2007 15:08

Re: ExtractFilePath für C++
 
Hi

Zitat:

Zitat von OregonGhost
Code:
#include <string>

using std::string;
Was spricht dagegen? :)

Ein echter String :love: :mrgreen: Danke!

Das ist ja gleich viel schöner. Nur komisch, dass der C++-Highlighter "string" nicht hervorhebt, das verwirrt etwas. Ich schreibe das gleich um. :)

@Jens: Bei mir war am Ende ein "M" zuviel, also "...\M".

SirThornberry 30. Nov 2007 15:11

Re: ExtractFilePath für C++
 
ok, dann muss das "+1" hinter der schleife aber nur weg (aber komisch das es bei meinen Tests trotzdem so funktioniert)

OregonGhost 30. Nov 2007 15:15

Re: ExtractFilePath für C++
 
std::string ist kein Schlüsselwort, sondern eine Klasse, daher keine Hervorhebung.
Wenn du da was formatiertes reinschreiben willst, ist übrigens eventuell std::stringstream einen Blick wert.

Matze 30. Nov 2007 15:19

Re: ExtractFilePath für C++
 
Das werde ich mir alles mal näher ansehen, damit scheint ja einiges möglich zu sein.
Schade, dass es kein Schlüsselwort ist, aber da muss ich mich eben dran gewöhnen.

SirThornberry 30. Nov 2007 15:27

Re: ExtractFilePath für C++
 
ich habe meine extract_file_path funktion nochmal angeschaut und sie funktioniert richtig mit dem +1

Zudem ist
Code:
for (i = strlen(path) - 1; (i >= 0) && (path[i] != '\\'); i--);
path[i+1] = 0;
das gleiche wie
Code:
for (i = strlen(path) - 1; (i >= 0) && (path[i] != '\\'); i--)
  path[i] = 0;
nur das bei zweiter Variante unnötige 0en geschrieben werden.

Wenn du also einen Buchstaben zu viel hattest, hast du wohl hinter die Vorschleife kein Semikolon gemacht.

uligerhardt 30. Nov 2007 16:28

Re: ExtractFilePath für C++
 
Zitat:

Zitat von Matze
Ein echter String :love: :mrgreen: Danke!

Öhm.... kennst du Google? :duck:

Matze 30. Nov 2007 19:51

Re: ExtractFilePath für C++
 
Jupp *g* Nur haben wir gelernt, man müsste Char-Arrays nutzen. Von C# & Co. kenne ich Strings, nur bin ich nicht auf die Idee gekommen, dass es auch einen im Win32-C++ gibt, da uns das, wie gesagt, so gesagt wurde.

static_cast 30. Nov 2007 20:07

Re: ExtractFilePath für C++
 
Vor dem selben Problem stand ich auch schon mal, irgendwie muss man in plain C/C++ das das Quadrat immer zum Rad (um nicht zu sagen das Rad neu erfinden) feilen ;)

Meine Lösung war:
Code:
std::string extractFilePath(const char* fileName)
{
   std::string result("");
   char filePath[MAX_PATH+1];
   ZeroMemory(&filePath,MAX_PATH+1);

   WIN32_FIND_DATA findFileData;
   HANDLE hFind = FindFirstFile(fileName, &findFileData);
   if (hFind != INVALID_HANDLE_VALUE)
   {
      strncpy((char*)filePath,fileName,strlen(fileName) - strlen(findFileData.cFileName) - 1);
      result = filePath;
      FindClose(hFind);
   }

   return result;
}

DMW 30. Nov 2007 20:13

Re: ExtractFilePath für C++
 
Warum einfach, wenns auch umständlich geht :mrgreen:
Außerdem ist deine Lösung hochgradig ineffizient und funktioniert nicht für den Fall, daß der gegebene Pfad eventuell gar nicht auf dem System existiert oder nicht zugreifbar ist.

static_cast 30. Nov 2007 20:24

Re: ExtractFilePath für C++
 
Zitat:

Zitat von DMW
Warum einfach, wenns auch umständlich geht :mrgreen:
Außerdem ist deine Lösung hochgradig ineffizient und funktioniert nicht für den Fall, daß der gegebene Pfad eventuell gar nicht auf dem System existiert oder nicht zugreifbar ist.

Mein Ziel war auch nicht das es performant ist sondern sicher (abgesehen davon sollte das nur eine Anregung sein, wie man das backslashgesuche umgehen kann), und so sparte ich mir gleichzeitig eine Überprüfung ob die Datei existiert. Ich habe die Funktion auch aus meiner tools lib geschnappt und vor dem posten noch etwas angepaßt (auf std::string), in dem namespace sind auch noch Funktionen für den Status etc der von der Funktion gesetzt wird (Fehler Datei gibts nicht usw...), was hier aber eher overhead wär ;)

uligerhardt 30. Nov 2007 20:27

Re: ExtractFilePath für C++
 
Zitat:

Zitat von Matze
Jupp *g* Nur haben wir gelernt, man müsste Char-Arrays nutzen. Von C# & Co. kenne ich Strings, nur bin ich nicht auf die Idee gekommen, dass es auch einen im Win32-C++ gibt, da uns das, wie gesagt, so gesagt wurde.

Irgendwie haben scheinbar alle C++-Lehrenden das Bedürfnis, ihre Opfer erstmal mit Low-level-C zu traktieren. Das ist wahrscheinlich wie bei den Automechanikern, die ja angeblich in der Ausbildung auch imme noch Metallklötze kleinfeilen müssen. :roll:

sniper_w 30. Nov 2007 22:31

Re: ExtractFilePath für C++
 
Code:
#include <windows.h>
#include <iostream>
#include <string>

using std::string;

int main()
{
    char moduleName[1024];

    if(!GetModuleFileName( NULL, moduleName, 1024))
    {
        std::cout << "GetModuleHandle failed!!" << std::endl;
        return 0;
    }
    else
    {
        std::cout << moduleName << std::endl;
    }

    string filePath;

    filePath.assign(moduleName);

    int pos = filePath.find_last_of('\\');
    filePath.erase(pos+1);

    std::cout << filePath << std::endl;

   return 0;
}

Matze 30. Nov 2007 22:37

Re: ExtractFilePath für C++
 
Hui, das ist eine schöne Lösung, danke. :)

Luckie 30. Nov 2007 22:47

Re: ExtractFilePath für C++
 
Da gibt es eine API-Funktion für. Ich vergesse nur immer, wie die heißt und die DLL vergesse ich auch immer. Frag oder such mal im c-plusplus.de Forum.

http://www.c-plusplus.de/forum/viewt...341.html#82341

Oder MSDN-Library durchsuchenPathFindFileName und guck dir auchmal die anderen Path... Funktionen im SDK an.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:35 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz