C++ Verständnisfragen

gedon

Lieutenant
Registriert
Apr. 2008
Beiträge
614
Hallo,

ich bin gerade dabei ein kleines Programm mit Visual C++ 2010 zu errstellen. Stufe mich selbst mal als Anfänger ein. Textboxen habe ich mir schon erstellt, die meisten Buttons machen auch schon das was ich will, nur ich verstehe einfach nicht, wie ich einen String (siehe unten) bearbeiten kann und was das ^ dabei zu bedeuten hat.

Hier ein kleiner Ausschnitt aus dem Programm. Ich lasse ein Verzeichnis nach Dateien durchsuchen und füge diese dann Zeilenweise in eine Textbox ein. Das Problem hierbei ist, dass auch der Pfad mit angezeigt wird und außerdem möchte ich nicht jeden Dateityp haben. Wenn das einfach über Filter zu realisieren ist, wäre es natürlich eleganter, aber ich muss so oder so in einem anderen Teil des Programms in der Lage sein Teile des Texts durch einen anderen zu ersetzen.

array<String^>^fileEntries = Directory::GetFiles( E_InputDirectory->Text );

IEnumerator^ files = fileEntries->GetEnumerator();

while ( files->MoveNext() )
{
String^ STemp = safe_cast<String^>(files->Current);
Textfeld->AppendText(STemp + Environment::NewLine);
}

als Bsp. wie die Ausgabe im Textfeld aussieht, wenn im Feld E_InputDirectory C:\Ordner steht
C:\Ordner\test.txt
C:\Ordner\x.mpg
C:\Ordner\y.ts

und so soll es zum Schluss aussehen

Ich dreh mich momentan im Kreis, wäre super wenn mir jemand weiterhelfen könnte.
 
Ich versteh zwar den Algorithmus selbst nicht ganz, da ich wohl noch mehr Anfänger bin, als du, aber vieleicht hilft ja mein Denkanstoß:

Soweit ich mich erinnere, ist ein STRING ja nix anderes, als ein Array von CHAR. Wie wäre es nun also, wenn du dir vor der Ausgabe noch einen Zwischen-Algorithmus einfügst, der die Ausgabe nach in deinem Fall "C:\Ordner\" (den Teil musst du ja vorher schonmal irgendwo ausgelesen haben) durchsucht, und diesen Abschnitt einfach löscht. Somit hättest du zumindest schonmal das Ordner-Problem vom Tisch.
 
@Sun-Devil: Nein, String ist eine Klasse... und die hat sogar Methoden für genau solche Dinge... dort könnte man dann entweder über String-Replace ("C:\Ordner\" durch einen Leerstring ersetzen, oder sich den Teilstring zurückliefern lassen ab "C:\Ordner\".length oder oder oder).

Es gibt aber auch eine ganz andere Möglichkeit:
Ich würde über FileInfo gehen:

Vorsicht, ich mach kein C++/CLI also Code muss nicht ganz passen:
Code:
FileInfo^ fi = gcnew FileInfo(files->Current);
String^ dateiname = fi->Name;
 
Zuletzt bearbeitet:
1668mib schrieb:
@Sun-Devil: Nein, String ist eine Klasse... und die hat sogar Methoden für genau solche Dinge... dort könnte man dann entweder über String-Replace ("C:\Ordner\" durch einen Leerstring ersetzen, oder sich den Teilstring zurückliefern lassen ab "C:\Ordner\".length oder oder oder).

Naja, aber wenigstens die Grundidee war wohl net schlecht ;)
 
Ach ja, und was das Dach (^) zu bedeuten hat, könntem an ja auch selbst nachgooglen. Es geht um die Erweiterung von Microsoft. Es handelt sich dabei um sogenannte Referenztypen, also Klassen, welche nur dynamisch erzeugt werden können und über den Garbage-Collector verwaltet werden (man muss sich nicht um deren Freigabe kümmern).
 
@1668mib: Danke, das mit Replace habe ich jetzt schonmal hinbekommen :)

Wo ist denn jetzt der Vorteil bei FileInfo?

@Sun-Devil: Die String Klasse ist gemeint, aber trotzdem danke
 
Naja bei FileInfo bekommst du ganz egal wo sich die Datei befindet den Dateinamen raus, also wenn du z.B. den Ordnernamen gar nicht kennst - in deinem Fall kennst du ihn natürlich.
 
Achso, da habe ich mich in meinem 1. Beitrag wohl etwas unglücklich ausgedrückt. Ich wollte eigentlich sagen, dass ich mir die Dateien, die in einem bestimmten Verzeichnis liegen, anzeigen lasse.
Aber jetzt zum zweiten Problem, welche Methode von String eignet sich denn am besten, um die Dateien mit best. Dateiendungen herauszufiltern. Bin jetzt auf LastIndexOf gestoßen, wenn ich also den Index von ".mpg" mit der Länge des Strings Vergleiche, müsste ich doch Feststellen können, ob das auch die Dateiendung ist und nicht sowas z.B. datei.mpg.jpg ?
 
Es gibt doch bestimmt eine String::Split Methode oder so ähnlich. Sodass du den String in ein Array zerlegen kannst (anhand des ".") und dann einfach schaust, ob das letzte Element des Arrays = "jpg" ist.
 
Und ich hätte jetzt einfach gedacht: Länge vom String auslesen und einfach die letzten 3 Positionen vergleichen.
 
@Sun-Devil
Aber eine Dateieindung muss nicht unbedingt 3 Zeichen lang sein. Kann genausogut nur 1, 2, 4, 5, 6, (usw.) oder 0 Zeichen lang sein.

@cx01
Das klappt, man muss nur beachten, dass der Dateiname selbst auch Punkte enthalten kann.
Evtl. hat die Datei auch garkeine Endung. Sind halt Sonderfälle die man nicht vergessen darf.

@TS
Imo ist die Methode von 1668mib auch in diesem Fall am einfachsten.
FileInfo stellt nämlich die Eigenschaft "Extension" zur Verfügung. Einfacher gehts nicht.
So sparst du dir das rumgebastel am Pfad und eventuelle Fehler die daraus entstehen können.
 
Grantig schrieb:
@Sun-Devil
Aber eine Dateieindung muss nicht unbedingt 3 Zeichen lang sein. Kann genausogut nur 1, 2, 4, 5, 6, (usw.) oder 0 Zeichen lang sein.

Das mag ja sein, aber man weiß doch, nach welcher Dateiendung gesucht werden soll. Folglich kann man entsprechend einfach die Dateiandung, nach der gesucht werden soll angeben, das Programm überprüft deren Länge (n) und vergleicht dann eben diese n Stellen des Strings. Oder was auch gehen würde: ein Rückwärts-Vergleich. Sprich statt z.B. nach JPG zu suchen wird geschaut: ist die letzte Stelle ein G, dann ist die vorletzte Stelle ein P und dann die davor ein J (u.s.w. wenn's längere Endungen sind)
 
So, hab mir was zusammengestellt

Code:
DirectoryInfo^ di = gcnew DirectoryInfo( E_InputDirectory->Text );
array<FileSystemInfo^>^fsi = di->GetFileSystemInfos();
Collections::IEnumerator^ myEnum = fsi->GetEnumerator();		   
while ( myEnum->MoveNext() )
{
	   FileSystemInfo^ info = safe_cast<FileSystemInfo^>(myEnum->Current);
	   if(info->Extension==".mpa"||info->Extension==".mpv")
		  Textfeld->AppendText(info->Name + Environment::NewLine);
}

funktioniert auch soweit, solange man ein gültiges Verzeichnis angibt. Das Programm bricht sonst gleich in der obersten Zeile ab. Wie muss denn eine Sicherheitsabfrage aussehen?

Edit: So könnt es gehen...
Code:
try
{
	DirectoryInfo^ di = gcnew DirectoryInfo( E_InputDirectory->Text );
	if ( di->Exists )
	{
		array<FileSystemInfo^>^fsi = di->GetFileSystemInfos();
		Collections::IEnumerator^ myEnum = fsi->GetEnumerator();		   
		while ( myEnum->MoveNext() )
		{
		   FileSystemInfo^ info = safe_cast<FileSystemInfo^>(myEnum->Current);
		   if(info->Extension==".mpa"||info->Extension==".mpv")
			  Textfeld->AppendText(info->Name + Environment::NewLine);
		}					
	}
}
catch ( Exception^ e ) 
{
	Textfeld->AppendText( "Invalid Directory" + Environment::NewLine + e);
}
Ist das jetzt soweit OK oder ist irgendeine Zeile unnötig?
 
Zuletzt bearbeitet:
@Sun-Devil
Warum umständlich, wenns auch einfach geht? ;)

@gedon
sieht soweit gut aus. ( das 2te)

Du könntest noch per Directory::Exists("Verzeichnisname") checken ob das Verzeichnis überhaupt existiert, bevor du ein DirectoryInfo Objekt erstellst.
Dann läufst du nicht immer in eine Exception, wenn das Verzeichnis nicht existert. (Exceptions kosten mehr Performance als ein einfaches Directory::Exists()).
Der try-catch -Block muss aber trotzdem bleiben, da es ja immer noch zu ner AccessDeniedException kommen kann.
 

Ähnliche Themen

Antworten
16
Aufrufe
3.780
Antworten
4
Aufrufe
982
S
Antworten
5
Aufrufe
1.392
S
S
Antworten
4
Aufrufe
996
Zurück
Oben