Ist Pfad local



  • also ich hab mir jetzt das mit den strings ein wenig angeschaut und ausprobiert..

    es geht einfach nicht..

    int sizeOfString = (suchdir.GetLength()+1);
    	LPTSTR lpsz = new TCHAR[sizeOfString];
    	_tcscpy_s(lpsz, sizeOfString, suchdir);
    
    hFile = _findfirst(lpsz, &c_file ))
    

    könnte mir nicht jemand ein paar tips geben wie ich das denn machen soll, damit es funktioniert? ich bekomms nicht gebacken und es ist sicher nur ne kleinigkeit



  • hallo nochmal,

    ich hab jetzt ewig rumprobiert und hab jetzt die Funktion FindFirstFile() genommen, dort kann ich einfach einen cstring verwenden.

    jetzt hab ich aber die nächste konvertierungshürde

    remove((m_strDefaultDirectory+_T("\\")+FindFileData.cFileName)); // geht nicht error C2664: 'std::remove': Konvertierung des Parameters 1 von 'ATL::CStringT<BaseType,StringTraits>' in 'const char *' nicht möglich
    
    RemoveDirectory((m_strDefaultDirectory+_T("\\")+FindFileData.cFileName)); // funktioniert sehr wohl
    

    kann mir bitte jemand helfen, ich weiß nicht wo ich diese konvertierungsgrundlagne lernen soll.ich lern eigentlich nur durch probieren und anwenden. in der fh hatten wir sowas noch nie. hier haben wir immer nur komische pattern programmiert...



  • noch etwas

    remove((m_strDefaultDirectory+"\\"+FindFileData.cFileName));
    // hier bekomm ich keinen compiler fehler aber er löscht mir die ordner nicht...
    

    ich werde noch verrückt mit den konvertierungen, CString, string, char, const char* da checkt doch keiner mehr durch und ich weiß auch nicht wie ich das lernen soll. hab sehr lang gegoogelt und kollegen gefragt die sind sich da meist auch nciht so sicher. kann mir jemand bitte helfen?



  • So ganz unrecht hatte der "Grundlagen lernen"-Typ nicht.
    Ich versuchs mal.
    Ein char ist ein 8-bit signed int (außer wenn du im C-Forum bist).
    Den ersten 128 Werten des chars wird per ASCII-Encoding (www.asciitable.com) ein Zeichen zugeordnet. Ein einzelnes Zeichen macht noch keinen String, deshalb brauchst du mehrere, ein char * bietet sich an, der auf eine Reihe von chars zeigt. Das ist der C-Style mit Strings umzugehen. Die WinAPI besteht aus C-Funktionen, also funktioniert das.
    Nun gibt ein char nur 256 Zeichen her. Das heißt chinesisch ist nicht und schon Umlaute sind nicht portabel. Daher hat Windows eine Art UTF16 eingeführt und dazu gleich wchar_t. Das ist dasselbe wie ein char, nur halt mit 16 Bit und 64k Werten. Dementsprechend gibt es ein wchar_t * um einen String zu bauen. Nun gibt es sowas wie char *s = "Hallo" schon. Für wchar_t benutzt man wchar_t *ws = L"Hallo". Dann gibt es noch TCHAR und _T("Hallo"), das sind nur Macros, die zwischen der char und der wchar_t-Variante wechseln, je nachdem ob Unicode eingestellt ist.
    Ein string ist eine Klasse aus der C++-Bibliothek. Benutzt intern chars. Die WinAPI kann kein C++ und kann daher mit string-Klassen auch nichts anfangen. Es gibt die MFC, die die WinAPI in Klassen steckt. Wenn du nun aber einen string s hast, kannst du einfach s = "hallo" benutzen und dann mit s.c_str() auf den char * zugreifen, den Windows versteht. wstring ist dasselbe, nur mit wchar_t intern. Warum Windows kein tstring definiert ist mir unklar, aber man würde einfach sowas schreiben:

    #ifdef _UNICODE
    #define tstring wstring
    #else
    #define tstring string
    #endif
    

    Die WinAPI-Funktionen verstehen sowohl chars als auch wchar_ts. Man muss ihnen aber sagen, welches man benutzt. Es gibt FindFirstFileA für ASCII = char *, dann gibt es FindFirstFileW für wchar_t *, dann gibt es FindFirstFile das je nach Unicode-Einstellung als FindFirstFileA oder FindFirstFileW definiert wird.
    Ich habe keinen Plan was ein CStringT ist.
    Dann gibt es da noch Arrays von chars (char s[100] = "Hallo";), was kompatibel mit char * ist (Ein Array hat zusätzlich die Länge, die bei Umwandlung in einen Pointer weggeschmissen wird. Andersrum gehts nicht, aus einen char * kann man kein char[] machen, da die Länge weg ist und man sie auch nicht manuell angeben kann).
    Und zuletzt das nette const, dass da sagt, dass die Daten, auf die der const Pointer zeigt, nicht verändert werden sollen.
    Beispiel: strcpy(char *, const char 😉 kopiert ein String in einen anderen. Der erste String wird überschrieben, kann also nicht const sein. Von dem zweiten String wird nur gelesen, der kann also const sein. Man kann als ersten Parameter keinen const char * übergeben, da dann strcpy nicht mehr weiß, was es tun soll. Man kann aber sehr wohl einen char * als zweiten Parameter übergeben. strcpy überschreibt den String der gelesen wird nicht, obwohl er dürfte, aber das ist kein Problem.

    Nächstes: String Operationen

    char *s = "Hallo";
    s[2] = 'o'; //crash
    

    "Hallo" ist eine Konstante, die nicht überschrieben werden kann und s zeigt nur auf "Hallo".

    char s[100] = "Hallo";
    s[2] = 'o'; //funktioniert
    

    "Hallo" ist eine Konstante, s ist ein Array von 100 chars, in dem am Anfang "Hallo" drin steht, und dieses Array kann man verändern.

    char *s = "Hallo";
    char *s2 = "du";
    char *s3 = s + " " + s2; //völliger schwachsinn
    

    Mit s + " " würden zwei Pointer addiert werden, die dann irgendwo hin zeigen. Das ist so großer Schwachsinn, dass es in C und C++ nicht erlaubt ist.

    char *s = "Hallo";
    char *s2 = "du";
    char s3[100];
    sprintf(s3, "%s %s", s, s2); //so gehts richtig
    

    Klassen in C++ überladen ihre Operatoren. Es ist auch in C++ Quatsch Pointer oder Objekte zu addieren, daher treten Funktionen an die Stelle.

    string s = "Hallo";
    s += " du"; //Funktionsaufruf!!!
    

    Du solltes rausfinden was ein CStringT ist und wir man daraus einen char * oder wchar_t * macht, dann funktioniert auch dein Code.

    Ich hoffe das hilft für den Anfang.



  • vielen lieben dank für deine antwort, das hilft mir auf jedenfall weiter. ich habe das zwar schon so ähnlich gelesen doch nicht so gut erklärt bekommen.
    allerdings tun sich bei mir wieder fragen auf..

    warum geht dann:

    RemoveDirectory((m_strDefaultDirectory+_T("\\")+FindFileData.cFileName));
    

    und liefert mir das gewünschte ergebnis?

    Du solltes rausfinden was ein CStringT ist und wir man daraus einen char * oder wchar_t * macht, dann funktioniert auch dein Code.

    Das ist ja mein Problem, ich weiß nicht wie ich das herausfinden soll wie ich das daraus mache 😞



  • ich verzweifle noch, hab zwar zwischendruch was anderes machen müssen doch jetzt hab ich schon wieder ein problem... entweder bin ich zu dumm das alles zu checken oder des ist so kompliziert....

    CString strPathToDelete;
    strPathToDelete = _T("C:\\Downloadordner\\*");
    	SHFILEOPSTRUCT sh;   
    	sh.hwnd = NULL;   
    	sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; 
    	sh.wFunc = FO_DELETE;                 
    	sh.pFrom = strPathToDelete;  // löscht nur dateeien wenn ich _T("C:\\Downloadordner\\*"); hart hinschreibe... in der variable geht snicht wieso auch immer        
    	sh.pTo = NULL; 
    	sh.hNameMappings = NULL; 
    	sh.lpszProgressTitle = NULL; 
    
    	if (SHFileOperation (&sh) == 0)
    


  • Es ist nicht kompliziert. Das ist genau dasselbe Problem wie vorher. Lies dir mal http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795(v=vs.85).aspx durch. Da steht was dieses sh.pFrom eigentlich ist. Es ist ein char * oder wchar_t * je nach Unicode-Einstellung. Ein CString ist kein wchar_t *. Deswegen funktioniert es nicht. Und selbst _T("C:\\Downloadordner\*") ist falsch. Es muss ein doppelt Null-terminierter String sein. _T("C:\\Downloadordner\*") ist nicht doppelt Null-terminiert, es ist pures Glück dass dahinter noch eine 0 kommt und es funktioniert. _T("C:\\Downloadordner\*\0") wäre korrekt, und das kannst du auch als TCHAR * in einer Variablen übergeben.

    Ich habe nun etwas über CStrings gelesen.

    http://msdn.microsoft.com/en-us/library/awkwbzyc.aspx schrieb:

    CString does not store character data internally as a C-style null-terminated string. Instead, CString tracks the length of character data so that it can more securely watch the data and the space it requires.

    ...

    To use a CString object as a C-style string, cast the object to LPCTSTR. In the following example, the CString returns a pointer to a read-only C-style null-terminated string.

    Das heißt er schmeißt die schöne doppel-Null einfach weg und es geht direkt mit CStrings überhaupt nicht. Du müsstest eine kleine Funktion schreiben:

    TCHAR *CString2TCHAR(const CString s){ //jeder Aufruf überschreibt den String des letzen Aufrufs!!!
    	static TCHAR buffer[1024]; //funktioniert nicht bei Strings länger als 1022 Zeichen
    #ifdef _UNICODE
    	buffer[swprintf(buffer, _T("%s"), (LPCTSTR)s)] = 0;
    #else
    	buffer[sprintf(buffer, _T("%s"), (LPCTSTR)s)] = 0;
    #endif
    	return buffer;
    }
    


  • nwp3 schrieb:

    TCHAR *CString2TCHAR(const CString s){ //jeder Aufruf überschreibt den String des letzen Aufrufs!!!
    	static TCHAR buffer[1024]; //funktioniert nicht bei Strings länger als 1022 Zeichen
    #ifdef _UNICODE
    	buffer[swprintf(buffer, _T("%s"), (LPCTSTR)s)] = 0;
    #else
    	buffer[sprintf(buffer, _T("%s"), (LPCTSTR)s)] = 0;
    #endif
    	return buffer;
    }
    

    Die Lösung hat ein paar Schwächen

    1. swprintf kann als Ergebnis -1 zurückliefern

    2. CString darf max. 1024-2 Zeichen lang sein. Müsste man sicherstellen!

    3. Statisches Array bindet dauerhaft 1024-2 Zeichen und wird ständig überschrieben, was u.U. zu seltsamen Effekten führt (multithreading ?).

    Vorschlag:

    TCHAR *CString2TCHAR(const CString s)
    {
    	LPTSTR lpszData = new TCHAR[s.GetLength()+2]();
    	_tcscpy(lpszData , s);
    
    	return lpszData;
    	// delete[] lpszData;   // don't forget to do this
    }
    

    Bem: Die Doppelnull hier realisiert mit +2.



  • Vorschlag:

    TCHAR *CString2TCHAR(const CString s)
    {
    	LPTSTR lpszData = new TCHAR[s.GetLength()+2]();
    	_tcscpy(lpszData , s);
    
    	return lpszData;
    	// delete[] lpszData;   // don't forget to do this
    }
    

    Bem: Die Doppelnull hier realisiert mit +2.[/quote]

    Vielen Dank ich versuche das später nochmal.
    ABER: Ich tu mir auch so schwer, da in dem Projekt irgendwas anderes eingestellt ist und eingestellt sein muss!

    Ich muss bei CStrings immer _T("") benutzen. ich hab auch schon versucht zu reserchieren warum das so ist, aber auf eine zufriedenstellende lösung bin ich noch nicht gestoßen. 😞
    Es geht wohl darum nur Unicode zu verwenden und kein ANSI.

    Mal ne frage für dummys.. könnte ich nicht einfach auch

    CString test = _T("test");
    test.insert(test.GetLength(), _T("\0"))
    

    sagen anstatt der funktion?? Oder ist das was anderes?



  • also einfach nur eine null an das ende des strings in der variable zu schreiben hat nix gebracht, ich muss die funktion benutzen.

    kann mir jemand erklären warum? ich dachte die funktion macht nichts anderes wie die 0 an das ende...

    der beitrag indem jemand das geschrieben hat wurde irgendwie gelöscht 😞



  • also

    CString test = _T("C:\\testordner\\*\n"); // geht nicht
    
    SHFILEOPSTRUCT sh;   
    sh.hwnd = NULL;   
    sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; 
    sh.wFunc = FO_DELETE;                 
    sh.pFrom = test;   // CString2TCHAR(test); wenn ich das benutze funktionierts       
    sh.pTo = NULL; 
    sh.hNameMappings = NULL; 
    sh.lpszProgressTitle = NULL; 
    
    if (SHFileOperation (&sh) == 0
     {...........}
    

    kann mir bitte jemand erklären wie das ist, weil ich will ja nicht nur das der code funktioniert ich würde gern daraus etwas lernen und mit nehmen, aber so richtig verstehe ich das nicht...

    was ich auch immer noch nciht so kapiere, wann delete ich? am besten im destruktor der klasse oder?



  • ich mein natürlich \0 sorry

    CString test = _T("C:\\testordner\\*\0");
    


  • Du brauchst offensichtlich einen TCHAR* und hast einen CString, oder ?

    Der ausführliche Ausflug von nwp3 in Stringverarbeitung reicht nicht ?

    nwp3 schrieb:

    So ganz unrecht hatte der "Grundlagen lernen"-Typ nicht.
    Ich versuchs mal.

    ...

    Du solltes rausfinden was ein CStringT ist und wie man daraus einen char * oder wchar_t * macht, dann funktioniert auch dein Code.

    Sowohl TCHAR alsauch CString haben den Vorteil, das es egal ist ob Unicode oder nicht. Um da allerdings den String reinzubekommen wird _T("..") oder TEXT("..")
    (oder notfalls auch L"..") wohl benötigt.



  • danke für die antwort... ich google auch ein wenig, da ich das einfach verstehen will jetzt.

    // Our CString object.
    CString String = "HelloWorld";
    
    // Get the internal buffer pointer of CString.
    LPTSTR pString = String.GetBuffer( 0 );
    ...
    
    // Use the pString and then release it.
    String.ReleaseBuffer();
    

    Warum geht das dann nicht in meinem Fall?



  • intern schrieb:

    ich mein natürlich \0 sorry

    CString test = _T("C:\\testordner\\*\0");
    

    Wie wärs mit

    CString test( _T("C:\\testordner\\*\0"));
    

    Wenn man sich das aber mal im Debugger ansieht fehlt die NULL zwar, aber

    int x = test.GetLength();
    

    zählt die Null offensichtlich mit.

    Es geht dann auch:

    test += TCHAR(0);
    


  • intern schrieb:

    ich mein natürlich \0 sorry

    CString test = _T("C:\\testordner\\*\0");
    

    geht doch ?

    Ob die Null allerdings nach der Konvertierung von CString in TCHAR noch da
    wäre eine andere Frage.

    Gibt es denn einen plausiblen Grund warum du nicht gleich ein TCHAR-Array nimmst bei dem duch den Speicher dynamisch verwaltest?

    Wie nwp3 ja bereits angemerkt hat, haben konstante Strings ein paar Einschränkungen.



  • also ich habe das programm zum weiterarbeiten hier bekommen, das steht schon so. ist ziemlich groß für meine verhältnisse.

    es gibt einfach einen standart pfad der aus einer datei gelesen wird und in CString gespeichert wird und hier und da verwendet wird.

    Jetzt geht es darum den Inhalt des Ordner zu löschen.

    CString test = _T("C:\\testordner\\*\0"); // gibt keinen compilerfehler aber meine löschfunktion geht nicht...
    
    CString test( _T("C:\\testordner\\*\0"));
    
    			SHFILEOPSTRUCT sh;   
    			sh.hwnd = NULL;   
    			sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; 
    			sh.wFunc = FO_DELETE;                 
    			sh.pFrom = test; //das geht auch nicht(strPathToDelete);          
    			sh.pTo = NULL; 
    			sh.hNameMappings = NULL; 
    			sh.lpszProgressTitle = NULL; 
    
    			if (SHFileOperation (&sh) == 0)
    

    es geht wirklich nur mit der vorgeschlagenen funktion. oder wenn ich einfach sage

    sh.pFrom = _T("C:\\testordner\\*\0")
    

    ich suche auch schon nach literatur dazu aber leider finde ich nichts 😞



  • und verrückt werde ich auch, denn das geht jetzt

    strPathToDelete = _T("C:\\Download\\*");
    			strPathToDelete += _T('\0');
    
    			SHFILEOPSTRUCT sh;   
    			sh.hwnd = NULL;   
    			sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; 
    			sh.wFunc = FO_DELETE;                 
    			sh.pFrom = strPathToDelete; //CString2TCHAR(strPathToDelete);          
    			sh.pTo = NULL; 
    			sh.hNameMappings = NULL; 
    			sh.lpszProgressTitle = NULL; 
    
    			if (SHFileOperation (&sh) == 0)
    

    was ist denn daran jetzt anderst? strPathToDelete += _T('\0');



  • Hallo,

    zunächst das hier:

    intern schrieb:

    CString test( _T("C:\\testordner\\*\0"));
    
    			SHFILEOPSTRUCT sh;   
    			sh.hwnd = NULL;   
    			sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; 
    			sh.wFunc = FO_DELETE;                 
    			sh.pFrom = test; //das geht auch nicht(strPathToDelete);          
    			sh.pTo = NULL; 
    			sh.hNameMappings = NULL; 
    			sh.lpszProgressTitle = NULL; 
    			
    			if (SHFileOperation (&sh) == 0)
    

    kann nicht funktionieren, weil bei

    CString test( _T("C:\\testordner\\*\0"));
    

    test nur alle Zeichen bis zum ersten Null-Byte bekommt (die "Null" ist nicht enthalten, obwohl geschrieben, weil der Konstruktor zur "Füllung" des internen Zeichenspeichers hier nur alle Zeichen liest, bis die erste "Null" kommt, der Zeichenspeicher enthält also die "Null" nicht), eine zweite "Null", die erforderlich ist, gibt es hier nicht, nur eine, die bei

    sh.pFrom = test
    

    von CString hier "erzeugt" wird.

    Hier:

    intern schrieb:

    oder wenn ich einfach sage

    sh.pFrom = _T("C:\\testordner\\*\0")
    

    ich suche auch schon nach literatur dazu aber leider finde ich nichts 😞

    liegt der Fall ganz anders, weil kein CString benutzt wird, es gibt keine Funktion hier (oben schon, weil dort ein Konstruktor "aufgerufen" wird, der nach einer bestimmten Regel die Zeichen analysiert), die erst alle Zeichen in einen bestimmten Bereich kopieren muss, hier liegen die Zeichen mit der explizit geschriebenen "Null" und mit einer "Null", die vom Compiler noch zusätzlich angefügt wird, in einem Speicherbereich, also alles so, wie es sein soll.

    Und das hier:

    intern schrieb:

    und verrückt werde ich auch, denn das geht jetzt

    strPathToDelete = _T("C:\\Download\\*");
    			strPathToDelete += _T('\0');
    			
    
    			SHFILEOPSTRUCT sh;   
    			sh.hwnd = NULL;   
    			sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; 
    			sh.wFunc = FO_DELETE;                 
    			sh.pFrom = strPathToDelete; //CString2TCHAR(strPathToDelete);          
    			sh.pTo = NULL; 
    			sh.hNameMappings = NULL; 
    			sh.lpszProgressTitle = NULL; 
    			
    			if (SHFileOperation (&sh) == 0)
    

    was ist denn daran jetzt anderst? strPathToDelete += _T('\0');

    klappt, weil durch Hinzufügen eines einzelnen ("Null-")Zeichens der interne Zeichenzähler um eins erhöht wird (es wird eine andere Funktion, nicht der Konstruktor wie oben, aufgerufen, die "Null"-Zeichen nicht "ablehnt"), die "Null" also mit erfasst wird und in den internen Zeichenspeicher übertragen wird. Eine zweite "Null" wird wieder, wie oben schon erklärt, von CString bereit gestellt.

    MfG,

    Probe-Nutzer


Anmelden zum Antworten