@codefinder -> dringend!
-
Hallo, codefinder.
Darf ich Dich vielleicht etwas fragen, bezüglich deines Templates für zeichensatzunabhängige. rekursive Ordnersuche
(
http://www.c-plusplus.net/forum/viewtopic-var-t-is-168044-and-highlight-is-*rekursiv*.html
)
Ich könnte ja auch einfach abtippen, aber würde gerne einige Fragen zum Konzept stellen.
Ist das möglich?
Danke.
-
Hoi, lol joar, dann frag doch
...
-
Zu erst mal:
....bool(__cdecl* pFileProc)(CPCSTRG pFilePath, void* pData), void* pvUserData)Was bitte ist __cdecl* pFileProc, und warum so gecastet?
In der ganzen Funktion kommt das unten noch einmal vor, aber meinst du damit die WndProc?Was übergibst du mit pData und mit pUserData?
if(strSrc[strSrc.length()] == SIGN('\\')) strSrc.erase(strSrc.rfind(SIGN('\\'), cString::npos), strSrc.length()); if(strSrc.rfind(STRING("\\*"), cString::npos) == cString::npos) strSrc.append(cString(STRING("\\*")), 0, 3);Guckst hier, ob Elternpfad ( also Argument) irgendwo n '\' hat, ja?
Wenn dem so ist, löschte das, ja?
Nun , was machste dann? Mit .rfind?
Das peil ich net.......
genauso wie dann das:strSrc.erase(strSrc.rfind(SIGN('*'), cString::npos)); und dann strSearchArg.append(cString(STRING("\\*")), 0, 3);Klingen die letzten drei codezeilen nicht widersprüchlich?
append, erase, append?
Wozu?und nochmal dies:
pFileProc((strSrc + cString(win32FinData.cFileName)).c_str(), pvUserData))watt soll denn diese FileProc sein?
----
Hoffe, du fühlst dich nicht gestört durch diese Fragerei.Danke schonmal.
-
me-S-on schrieb:
Was bitte ist __cdecl* pFileProc, und warum so gecastet?
__cdecl ist eine sog. Aufrufkonvention. Diese bestimmt wie die Parameter einer Funktion aufs Stack gepusht bzw. gepoppt werden (und wer das tut...). Speziell bei dieser werden die Parameter von links nach rechts auf das Stack gepusht; die aufgerufene Funktion sorgt selbstständig dafür, dass diese Einträge vom Stack wieder entfernt. (Der Return-Wert wird dabei immer im EAX-CPU-Register abgelegt.)
Gecastet wird hier gar nichts, obwohls so aussieht
. Der folgende Codeabschnitt bildet einen Parameter der Funktion (also Typ und Name): bool(__cdecl* pFileProc)(CPCSTRG pFilePath, void* pData). Der Variablenname ist dabeipFileProc. Dieser wird auch als Funktionszeiger bezeichnet. Jeder Funktionsname kann nämlich auch als Zeiger auf abzuarbeitenden Code verstanden werden, über welchen dann zu diesem Code gesprungen wird (ASM-Jump-Commands). Du übergibst hier also einen Zeiger auf eine von Dir definierte Funktion, die dann von meiner 'Suchfunktion' aufgerufen wird - immer dann, wenn eine Datei gefunden wird.
In der WinAPI gibt es dieses Prinzip sehr oft. Dabei wird lediglich eine etwas übersichtlicher Schreibweise über eine Typendefinition verwendet, auf die ich aber bewusst verzichtet habe, in etwa so:// Typendefinition: typedef bool(__cdecl* PFILEHANDLER)(CPCSTRG,void*); // Zeiger auf Funktion mit 2 Parametern; Typ ist festgelegt // Die Funktion sähe dann zum Beispiel so aus: bool ScanFoldersForFiles(CPCSTRG pszFolderParent, PFILEHANDLER pFileProc, void* pvUserData) { /* ... */ }Hier sollte auch klar werden, dass es kein Cast ist
. WNDPROC (ein Win32-Datentyp) ist damit vergleichbar. Du kannst Dir ja mal die Defintion in den Windows-Headern anschauen.me-S-on schrieb:
In der ganzen Funktion kommt das unten noch einmal vor, aber meinst du damit die WndProc?
Wie gesagt, das Prinzip ist vergleichbar mit einer WNDPROC. Dies hat aber nichts mit der WndProc Deines Fensters zu tun!
me-S-on schrieb:
Was übergibst du mit pData und mit pUserData?
pData ist der 2. Parameter der Funktion die Du erst definieren und deren Zeiger Du dann übergeben musst. Dies ist also kein Paremeter der Funktion 'ScanFoldersForFiles'! An pUserData kannst Du einen beliebigen Zeiger übergeben. Diese Daten stehen dann bei jedem Aufruf von dieser pFileProc-Funktion (die Du definieren musst und von meiner 'ScanFoldersForFiles'-Funktion aufgerufen wird) im 2. Parameter 'pData'. Damit verhindert man die Verwendung von globalen Variablen. Auch dieses Prinzip findet man oft in der WinAPI wieder. Vergleiche die Funktion EnumWindows, siehe letzter Parameter.
Man könnte diese Funktion auch so schreiben:BOOL EnumWindows( BOOL (CALLBACK* lpEnumFunc)(HWND hwnd, LPARAM lParam), LPARAM lParam ); // Hinweis: CALLBACK ist als __stdcall definiert, eine etwas andere Aufrufkonvention.me-S-on schrieb:
if(strSrc[strSrc.length()] == SIGN('\\')) strSrc.erase(strSrc.rfind(SIGN('\\'), cString::npos), strSrc.length()); if(strSrc.rfind(STRING("\\*"), cString::npos) == cString::npos) strSrc.append(cString(STRING("\\*")), 0, 3);Guckst hier, ob Elternpfad ( also Argument) irgendwo n '\' hat, ja?
Wenn dem so ist, löschte das, ja?
Nun , was machste dann? Mit .rfind?
Das peil ich net.......Ich schreib Dir den Code einfach nochmal mit Kommentaren hin, glaube damit versteht man es am einfachsten:
/* Prüfen, ob am *Ende* des zu durchsuchenden Pfades ein '\' steht: */ if(strSrc[strSrc.length()] == SIGN('\\')) // Operator [] ist für die Klasse std::string überladen; length gibt die Länge zurück, ohne '\0' // Falls gefunden: löschen: strSrc.erase(strSrc.rfind(SIGN('\\'), cString::npos), strSrc.length()); /* Prüfen, ob am *Ende* des zu durchsuchenden Pfades ein '\*' steht: */ if(strSrc.rfind(STRING("\\*"), cString::npos) == cString::npos) strSrc.append(cString(STRING("\\*")), 0, 3); // Falls *nicht*, dann anfügenNun zum Sinn der Sache
: Damit sorge ich dafür, dass man folgende Pfade problemlos übergeben kann, es handelt sich also um Bedienkomfort der Funktion
:C:\demo\test\C:\demoC:\demo\*
In jedem Fall bastelt sich meine Funktion den String so zurecht, dass sie damit arbeiten kann. (Außer im letzten, der ist schon perfekt.) Das '\*' am Ende sorgt dafür, dass nach allen Dateien gesucht wird, die Auslese findet dann in der von Dir definierten Funktion statt. Daher ist die Funktion auch ziemlich universell
.me-S-on schrieb:
genauso wie dann das:
strSrc.erase(strSrc.rfind(SIGN('*'), cString::npos)); und dann strSearchArg.append(cString(STRING("\\*")), 0, 3);Klingen die letzten drei codezeilen nicht widersprüchlich?
append, erase, append?
Wozu?Nein, das ist nicht widersprüchlich
. Wie Dir vllt. schon aufgefallen ist, arbeitet die Funktion rekursiv. Das heißt immer wenn ein Ordner gefunden wird, beginnt ein geschachtelter Funktionsaufruf, die Funktion ruft sich also selbst mit dem Pfad zum Unterordner auf.
Dieser Pfad muss aber erst gebastelt werden, da die Windows-Enumeration nur den Dateinamen (bzw. den Orndernamen) angibt. Der neue Pfad ergibt sich also aus dem vorherigenStartverzeichnis + '\' + NameDesGefundenenOrdners. Vergleiche meinen Code hier:strSearchArg = strSrc /*modifiziertes Startverzeichnis*/ + cString(win32FinData.cFileName) /*gefundener Ordnername*/;Da aber der Pfad des Startverzeichnisses am Ende noch ein \* besitzt, muss dieses erst entfernt werden, aber (wichtig!) erst nach der Initialisierung mit der FindFirstFile-Funktion, sonst wäre es ja sinnlos:
hFile = FindFirstFile(strSrc.c_str(), &win32FinData); // Initialisierung if(hFile == INVALID_HANDLE_VALUE) return (false); strSrc.erase(strSrc.rfind(SIGN('*'), cString::npos)); // '\*' entfernen, falls weitere rekursive Aufrufe folgen bzw. ein Pfad für eine gefundene Datei zusammengesetzt werden mussme-S-on schrieb:
und nochmal dies:
pFileProc((strSrc + cString(win32FinData.cFileName)).c_str(), pvUserData))watt soll denn diese FileProc sein?
Hier wird die oben (hoffe ich relativ ausführlich/verständlich) erläuterte Funktion, die von Dir definiert wurde und deren Zeiger dann in 'pFileProc' ist, aufgerufen, da eine Datei gefunden wurde. Parameter sind eben der Pfad zur gefundenen Datei und der von Dir übergebenen Zeiger auf beliebige Daten (
void*) (der natürlich auch einfach NULL sein kann).me-S-on schrieb:
Hoffe, du fühlst dich nicht gestört durch diese Fragerei.
Nein überhaupt, ist kein Problem
.Huji, ist ja ganz schön lang geworden, naja sollte eigentlich alles drin sein...
-
Jetzt aber mal im ernst ... dein cString usw. ist bescheuert ^^ Mehr als das ...
#include <tchar.h> #include <string> typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR> > tstring;aja und dann auch
typedef bool(__cdecl* PFILEHANDLER)(const tstring&, void*);usw ...
-
(D)Evil schrieb:
Jetzt aber mal im ernst ... dein cString usw. ist bescheuert ^^ Mehr als das ...
#include <tchar.h> #include <string> typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR> > tstring;typedef std::basic_string<TCHAR> tstring;warum nicht so??
-
ähem , öh eh, .....
Alles klar!
Also, mit anderen Worten bool (__cdecl) ist nur eine Eigenart des Stack-push- und -poppens ( zum Glück bin ich gerade intensiv parallel am Assembler dran!!!
) für die Parameter ,die in der pFileProc übergeben werden .
Oder?
So wie wenn ich eine Funktion an execve() übergebe..
Dann packe ich die Parameter nacheinander in bx,cx,dx, AUSSER die beiden Elemente das Arrays im 2. Parameter von execve; die holt sich die Funktion schön ausm Stack...... ist das vergleichbar?
Also, dieser pFileProc.... ein Zeiger auf den Anfang einer Funktion ....., ich mein, ich weiss, dass man auch in der wndclass das lpfnWndProc-Member so mit einer Funktion initialisiert.... also den Namen derer ohne Klammern entspricht einem Zeiger auf diese, das Program holt sie sich dann schon.
-Ne?
Und dann noch Userdata und pUser data....
->
Zusammengefasst:
pFileProc, pUserData und UserData sind einfach Funktionen, die du in deinem Programm benutzt, daher haste die mit gepostet.
Einfach dein Code, zwingend erforderlich sind die ja nicht bei jedem, ne?
Ok, wenn ich nun die Elemente
-TVINSERTSTRUCT
-HTREEVIEW
- char * ppath;
- char * actpath
- char *newpath
- char *dev_root
nicht alle global machen will, mache ich eine
Funktion global bekannt, welche notwendige Schritte und Variablen übernimmt, um ins TreeVew zu inserten und Images zuzufügen, mache die Suche aber in dieser SerachFolderForFile Funktion.
Dabei übergebe ich dieser einen Pointer auf die vorige Funktion, und SPARE MIR DAMIT TATSÄCHLICH GLOBALE VARIABLEN?????

Ich habe, ( ich bin ja am testen, einen HAUFEN GLOBALER) .Wenn ich das so richtig entnommen habe. ----
-----
-Die char-cut and replace-Angelegenheit habe ich gestern ebenfalls scheinbar hinbekommen...... allerdings mit mehr oder weniger ANSI-C. Ich habe keine objektorientierten Methoden aus der <string> benutzt.
Könnte ich allerdings mal tun.
Nun schmiert das zwar nach dem dritten Unterordner ab( mit errorcode 6_ Invalid handle) aber das krich ich auch noch hin.
Hope so!
-------------------------------------------------------------------------------
Diese Posts vom (D)Evil !
Echt, nomen ost omen.
Aber ihr beide könnt Euch sicher miteinander messen
-------
codefinder, kanste meine Zusamenfassung noch kurz bejahen, oder verneinen, in den Fragen, die noch kamen?, also die, wo das "
" hinter steht?
Dann wärs das fast.....
danke sehr bisher!
-
@me-S-on: Warum schreibst du so chaotisch?

-
(D)Evil schrieb:
Jetzt aber mal im ernst ... dein cString usw. ist bescheuert ^^ Mehr als das ...
#include <tchar.h> #include <string> typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR> > tstring;Naja^^, kommt aufs Gleiche raus, wobei man natürlich durchgehend cString/tstring verwenden sollte, jupp:
(D)Evil schrieb:
aja und dann auch
typedef bool(__cdecl* PFILEHANDLER)(const tstring&, void*);usw ...
konsekutiv
...Auch wenn ichs nicht geschrieben habe, stimme ich dem trotzdem zu :
CodeFinder|logged out schrieb:
@me-S-on: Warum schreibst du so chaotisch?
me-S-on schrieb:
Also, mit anderen Worten bool (__cdecl) ist nur eine Eigenart des Stack-push- und -poppens ( zum Glück bin ich gerade intensiv parallel am Assembler dran!!! ) für die Parameter ,die in der pFileProc übergeben werden .
Oder?
Joar.
me-S-on schrieb:
Also, dieser pFileProc.... ein Zeiger auf den Anfang einer Funktion ....., ich mein, ich weiss, dass man auch in der wndclass das lpfnWndProc-Member so mit einer Funktion initialisiert.... also den Namen derer ohne Klammern entspricht einem Zeiger auf diese, das Program holt sie sich dann schon.
-Ne?
Genau, das ist damit vergleichbar.
me-S-on schrieb:
Und dann noch Userdata und pUser data....
->
Zusammengefasst:
pFileProc, pUserData und UserData sind einfach Funktionen, die du in deinem Programm benutzt, daher haste die mit gepostet.
Einfach dein Code, zwingend erforderlich sind die ja nicht bei jedem, ne?
Nein, nur pFileProc ist ein Funktionszeiger. pUserData ist ein Parameter der Funktion 'ScanFoldersForFiles'.
me-S-on schrieb:
Ok, wenn ich nun die Elemente
-TVINSERTSTRUCT
-HTREEVIEW
- char * ppath;
- char * actpath
- char *newpath
- char *dev_root
nicht alle global machen will, mache ich eine
Funktion global bekannt, welche notwendige Schritte und Variablen übernimmt, um ins TreeVew zu inserten und Images zuzufügen, mache die Suche aber in dieser SerachFolderForFile Funktion.
Dabei übergebe ich dieser einen Pointer auf die vorige Funktion, und SPARE MIR DAMIT TATSÄCHLICH GLOBALE VARIABLEN?????
Ich habe, ( ich bin ja am testen, einen HAUFEN GLOBALER) .Wenn ich das so richtig entnommen habe. ----
ALSO ANBRÜLLEN BRAUCHST DU MICH NICHT
. Und ähm, kp was Du damit sagen willst ... . Drück Dich mal etwas verständlicher aus ... 
me-S-on schrieb:
-Die char-cut and replace-Angelegenheit habe ich gestern ebenfalls scheinbar hinbekommen...... allerdings mit mehr oder weniger ANSI-C. Ich habe keine objektorientierten Methoden aus der <string> benutzt.
Könnte ich allerdings mal tun.Ich finde OOP besser als Prozedurale. Aber das ist Ansichtssache. Arbeite einfach mal mit beiden und finde damit heraus, womit Du besser klar kommst
.me-S-on schrieb:
Nun schmiert das zwar nach dem dritten Unterordner ab( mit errorcode 6_ Invalid handle) aber das krich ich auch noch hin.
Also bei mir funktioniert die Funktion eigentlich problemlos.
me-S-on schrieb:
Diese Posts vom (D)Evil !
Echt, nomen ost omen.
Aber ihr beide könnt Euch sicher miteinander messen
Ne, ne (D)Evil ist Kollega
...er hat ja Recht, man sollte konsequent cString verwenden...glaub das hatte bei mir n internen Grund, dass ichs nicht gemacht hab. Also, wenns bei Dir passt, solltest Du auch, wie (D)Evil geschrieben hat, ne konstante Referenz auf ein cString-Objekt verwenden
.
-
Danke!
Ich meinte mit:Nein, nur pFileProc ist ein Funktionszeiger. pUserData ist ein Parameter der Funktion 'ScanFoldersForFiles'.
me-S-on schrieb:
Ok, wenn ich nun die Elemente
-TVINSERTSTRUCT
-HTREEVIEW
- char * ppath;
- char * actpath
- char *newpath
- char *dev_root
nicht alle global machen will, mache ich eine
Funktion global bekannt, welche notwendige Schritte und Variablen übernimmt, um ins TreeVew zu inserten und Images zuzufügen, mache die Suche aber in dieser SerachFolderForFile Funktion.
Dabei übergebe ich dieser einen Pointer auf die vorige Funktion, und SPARE MIR DAMIT TATSÄCHLICH GLOBALE VARIABLEN?????
Ich habe, ( ich bin ja am testen, einen HAUFEN GLOBALER) .Wenn ich das so richtig entnommen habe. ----
ALSO ANBRÜLLEN BRAUCHST DU MICH NICHT
. Und ähm, kp was Du damit sagen willst ... . Drück Dich mal etwas verständlicher aus ... 
Dieszbezüglich_
Wie gesagt, das Prinzip ist vergleichbar mit einer WNDPROC. Dies hat aber nichts mit der WndProc Deines Fensters zu tun!
me-S-on schrieb:
Was übergibst du mit pData und mit pUserData?pData ist der 2. Parameter der Funktion die Du erst definieren und deren Zeiger Du dann übergeben musst. Dies ist also kein Paremeter der Funktion 'ScanFoldersForFiles'! An pUserData kannst Du einen beliebigen Zeiger übergeben. Diese Daten stehen dann bei jedem Aufruf von dieser pFileProc-Funktion (die Du definieren musst und von meiner 'ScanFoldersForFiles'-Funktion aufgerufen wird) im 2. Parameter 'pData'. Damit verhindert man die Verwendung von globalen Variablen. Auch dieses Prinzip findet man oft in der WinAPI wieder. Vergleiche die Funktion EnumWindows, siehe letzter Parameter.
Man könnte diese Funktion auch so schreiben:Um also meiner Suchfunktion lokaloe Variablen einer anderen Funktion zu übergeben und somit globale zu sparen...
...
ach , pFileProc ist ja die Funktion nd pUser Data deren Parameter....
:
----------------------------------
Fälschlicherweise wollte ich fragen:
Fall ich einer Funktion ein Funktion als Parameter übergebe, die NUR anhand ihres Namens den Zeiger übergibt...... habe ich dann in der Funktion, die aufruft, die Parameter des Funktionszeigers zur Verfügung, SO ALS OB sie global wären?
-----------
Know what i mean?
...
naja, ich glaube ich habe mich da verhaspelt.
---
Das ich NICHT deinen code nehme und auch nicht den , der vom OP, sollteste wissen, nur ich hänge fest, und daher muss ich forschen, weisste?
Danke, bis zum nächsten Prob!
Einen schönen Tag noch.
-
CodeFinder|logged out schrieb:
@me-S-on: Warum schreibst du so chaotisch?

nichts für ungut aber liegt am vielen kiffen dran

-
darum bitten, mich nicht mit irgendeinr Droge in Verbindung zu bringen, dessen Verwendungn von mir Du Dir nicht absolut sicher bist.
Da ich davon ausgehen kann dass sich (D)Evil hier gerade als ich ausgegeben hat, ist dieser post an Dich gerichtet, Evil.
Unterlasse bitte, mir Soetwas zu unterstellen, gekifft habe ich nie und anderen Krams auch nicht,solche Unterstellungen sind nicht tolerierbar und meines Erachtens auch sehr feige herübergebracht , als nichtregstrierter, der sich als jemand anderer Ausgibt.Wie Du kleiner P.E.N.N.E:R siehst , kann ich auch labern , wie Du , Du laberst aber wie ne englische, Teatime T.U.C.K.E- also ver-p.i.s.s Dich hier aus dem Thread und gebe mit deinem S.c.h.e.i.s.s. vor Kindern in deinem (geistigen) Alter an.
Und: Du würdest jetzt sicher den Admin oder Mod dieser seite holen, DU f.ö.t.z.c.h.e.n... mach doch, aber bring mich nie wieder mit Irgendwelchen verdammten Drogen in Verbindung.

... nicht persönlich.
-
Bist du Hartz 4 Empfenger?
-
Hartz vier.
Und die Kohle für Dich verdient se bei mir.
Schonmal das Wort Arbeit gehört?
So mit Mühe und Steuern?
-

-
messssson schrieb:
Bist du Hartz 4 Empfenger?
Empfänger
-
... schrieb:
messssson schrieb:
Bist du Hartz 4 Empfenger?
Empfänger
Thx.

-
wenn ich das Ganze z.B.mal so mache:
rec_search(char *path) { char *found; char *fp; char *nextp; HANDLE fh; WIN32_FIND_DATA hfd; fh = FindFirstFile(path,&hfd); // Da habe ich beim ersten Aufruf( der bei mir // in einer for-Schleife für jedes Laufwerk ausgeführt wird) den Jeweiligen // Laufwerksbuchstaben samt "\*" als Parameter, so weit so gut!!! do { if(!((hfd.cFileName[0]=="." && hfd.cFileName[1]== ".") && (hfd.cFileName[2] == 0 || hfd.cFileName[1]=0))) { strcpy(ff,path); found = strstr(ff,"*"); found = ""; strcat(ff,hfd.cFileName); strcat(ff,"\\*"); strcpy(next, ff); rec_search(next); }while(FindNextFile(hfd,&WIN32_FIND_DATA); findClose(fhh); }Also, ich glaube , ich habe es zu Hause so.( nicht ganz sicher bin...)
Ich kann nun den ersten Ordner meines Testlaufwerkes rekursiv durchsuchen und finde auch alle Ordner, die MessageBox ist auch noch in der inneren Schleife vorhanden und gibt mir immer den Übergabeparameter path aus.
Dieser wird schön verlängert und dann wird immer ein Slash und die Wildcard drangepackt.Aber nachdem ich im ersten ordner des Laufwerkes das letzte FirstChild ( wenn ihr das versteht) gefunden habe, schmiert er ab.
Meiner Meinung nach mache ich was an der do-while falsch, oder aber ich , und das glaube ich eher, überschreibe den Pfad, der zur Rekursiven Suche gedacht ist, mit dem jeweiligen Pfad,den das letzte FirstChild empfing.
...
Das irittiert mich schon gewaltig.
Wenn ich erhlich bin, fiel mir von gestern bis heute keine geeignete Möglichkeit ein.... den Übergabeparameter abhängig zu machen von dem Rückgabewert der FindNextFile funktion, ohne den Rst zu stören.Sehr sehr kopfzermürbend.
Hat jemand ne Erklärung, bezüglich des Konzeptes?
-
@me-S-on und co: Muss das hier so ausarten!? Bitte wieder auf normale "töne" zurückfahren...
-
Ich entschuldige mich , aber mir soll keiner, der auch noch zu feige ist, sich zu registrieren , unterstellen, ich würde Drogen nehmen, und sich dann noch als ich ausgeben.
Ab nun kann das Niveau gerne wieder in sanften Klängen weiterlaufen.
Ist halt nur eine Verdeutlichung meines Standpunktes gewesen.
-
@me-S-on:
Hm also das:me-S-on schrieb:
schmiert er ab.
ist etwas unpräzise (Stichwort: Debugger), aber ich tippe trotzdem mal darauf, dass Du n Pufferüberlauf hast, da Du immer weiter kopierst und nie vergrößerst... aber... Warum nimmst Du nicht meine Funktion ? Die funktioniert doch
...