Autor |
Beitrag |
Stephan202
      
Beiträge: 16
|
Verfasst: Mo 11.07.11 22:43
Hallo,
habe einen Code, der aus einer txt-Datei ein Array machen soll. Das Ganze lief soweit für
2 Spalten und beliebig viele Zeilen. Nun habe ich versucht, das ganze für beliebig viele Spalten umzuprogrammieren.
Das Compilieren funktioniert, nicht aber das Ausführen des Codes.
Hier ist die Funktion, die die Datei ausliest:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| public string[,] tabelle(string pfad, string trennzeichen) { string[,] table={{"",""},{"",""}}; try { string[] fileContent = File.ReadAllLines(pfad); int linecount=fileContent.GetLength(0); string zeile; for (int i = 0; i < linecount; i++) { zeile=fileContent[i]; string[] datensatz=Regex.Split(zeile, trennzeichen); int j =0; foreach (string wort in datensatz) { table[i,j]=datensatz[j]; j=j+1;Print(table[i,j]); } } } catch (System.Exception excep) { MessageBox.Show(excep.Message); } return table; } |
Irgendwie werden die Daten damit nicht korrekt ausgelesen.
Wer kann helfen?
Vielen Dank schon im Vorraus!
Moderiert von Kha: C#-Tags hinzugefügt
|
|
Flitzs
      
Beiträge: 123
Erhaltene Danke: 7
Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
|
Verfasst: Mo 11.07.11 23:04
Hallo!
Schau dir mal die Zeilen 4 und 28 genauer an.
Kürzer bzw. eleganter geht das übriges mit LINQ:
C#-Quelltext 1: 2: 3:
| var table = from line in File.ReadAllLines("<Pfad>") select from wort in line.Split('<Trennzeichen>') select wort; |
lg Flitzs
|
|
Stephan202 
      
Beiträge: 16
|
Verfasst: Di 12.07.11 20:06
Hi,
weiss trotzdem nicht, was man bei meinem Script ändern muss, damit es läuft.
Das es was mit der Indizierung/Dimensionierung zu tun hat, dachte ich mir schon.
Würden Deine 3 Codezeilen den gesamten Code meinerseits ersetzen und
aus einer mehrzeligen textdatei mit mehreren Spalten, separiert durch ein Trennzeichen,
ein 2D-Array einlesen oder ist das nur ein Fragment?
|
|
Flitzs
      
Beiträge: 123
Erhaltene Danke: 7
Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
|
Verfasst: Di 12.07.11 21:47
Das Problem mit Array ist, dass sie was ihre Größe angeht, konstant sind.
Stephan202 hat folgendes geschrieben : |
C#-Quelltext 1: 2:
| string[,] table={{"",""},{"",""}}; |
|
Du legst hier ein 2*2 Array an. Somit kannst du auch nicht mehr als 2 Zeilen mit jeweils 2 Wörtern einlesen. Du müsstest also zuerst ermitteln, wie viele Zeilen/Wörter du benötigst (sofern die Anzahl nicht immer gleich ist) und dann entsprechend das Array so dimensionieren, dass die Daten Platz haben.
Übrigens kann man ein leeres Array auch mit
C#-Quelltext 1:
| string[,] table = new string[2,2]; |
erzeugen.
Stephan202 hat folgendes geschrieben : |
C#-Quelltext 1:
| j=j+1;Print(table[i,j]); |
|
Du erhöhst zuerst j um 1 (Inkrementierungen um 1 kannst du übriges auch mit dem ++-Operator durchführen) und greifst dann auf den j-ten Index im Array zu. Dieser ist aber ja noch nicht belegt, also zuerst Print dann Inkrementieren.
Meine 3 Zeilen ersetzen deinen gesamten Code, abgesehen von der Fehlerbehandlung, Print und der Funktionsdefinition/Return. Allerdings gibt er ein string[][] anstatt einem string[,] zurück. Wenn du unbedingt ein mehrdimensionales Array verwenden möchtest, musst du eben den oben beschriebenen Weg nehmen. Außerdem verwende ich Listen, da ihre Größe flexibel ist und daher das Problem wie bei den Arrays nicht auftritt. Wenn du aber unbedingt mit Arrays arbeiten möchtest, kann du die Listen auch in Array konvertieren (.ToArray())
lg Flitzs
|
|
Stephan202 
      
Beiträge: 16
|
Verfasst: Mi 13.07.11 00:10
Danke für die Infos.
Warum funktioniert eigentlich Zeile 9 und 21 in meinem vorherigen Codestück, wenn Arrays immer dimensioniert werden müssen?
Ich hab den Code jetzt geändert und vor der Dimensionierung von table die Ermittlung der korrekten Spaltenzahl eingebaut.
Nun kann ich zwar via Print die Werte anzeigen, aber die Weiterverarbeitung der eingelesenen Tabelle wirft einen
Indexfehler. Ich versteh nicht warum. Es ist doch nach wie vor ein m*n Array?
Vorher war der Code für fixe 2 Datenspalten geschrieben, da hats noch funktioniert mit der Weiterverarbeitung.
Das eingelesenen Text-File ist jeweils das Gleiche. Hier der aktuelle Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| public string[,] tabelle(string pfad, string trennzeichen) { string[,] table={{"",""},{"",""}}; try { string[] fileContent = File.ReadAllLines(pfad); int linecount=fileContent.GetLength(0); string[] datensatz=Regex.Split(fileContent[0], trennzeichen); int rowcount=0; foreach (string wort in datensatz) {rowcount++;} table = new string[linecount,rowcount]; string zeile; for (int i = 0; i < linecount; i++) { zeile=fileContent[i]; datensatz=Regex.Split(zeile, trennzeichen); int j =0; foreach (string wort in datensatz) { table[i,j]=datensatz[j]; j=j+1; } } } catch (System.Exception excep) { MessageBox.Show(excep.Message); } return table; } |
Moderiert von Th69: C#-Tags hinzugefügt
|
|
Th69
      

Beiträge: 4799
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 13.07.11 09:38
Hallo Stephan,
bei den Methoden File.ReadAllLines und Regex.Split übernehmen diese selber die Erzeugung (und passende Dimensionierung) des String-Arrays. Als Anwender dieser Methode verarbeitet man ja nur den Rückgabewert.
Wenn man aber selber ein Array erzeugt, so muß man eben im voraus die passende Dimension(en) angeben ehe man mittels des Index-Operators Daten dort hineinspeichern kann.
Flexibler geht es mit einer List<string> (aus System.Collections.Generic) da diese sich intern bei Bedarf selbständig vergrößert:
C#-Quelltext 1: 2: 3: 4: 5:
| List<string> list = new List<string>(); for(int i=0; i<10; i++) list.Add("Hallo"); |
Und 2-dimensionale Listen sind ebenfalls möglich: List<List<string>>.
Dabei muß man nur beachten (ähnlich wie bei String[][]), daß man für die Unterlisten ebenfalls Speicher anfordern muß:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| List<List<string>> list2 = new List<List<string>>(); for(int i=0; i<10; i++) { List<string> list = new List<string>(); for(int j=0; j<5; j++) list.Add("Hallo");
list2.Add(list); |
Nun enthält list2 10 Unterlisten mit jeweils 5 String-Elementen (wobei jede Unterliste auch verschieden viele Elemente enthalten könnte).
|
|
Stephan202 
      
Beiträge: 16
|
Verfasst: Mi 13.07.11 20:01
Danke für die Erklärungen.
Die Lists waren mir im Groben schon bekannt,
im vorliegenden Beispiel war es im definiert zweispaltigen Datensatz
kein Problem, die Arrays vorzudimensionieren.
Da der Code eine Funktion ist, die in weiteren Programmen verwendet wird,
will ich wohl auch weiterhin am Ende ein Array ausgeben.
Allerdings weiss ich noch nicht, warum der zuletzt gepostete Code noch nicht funktioniert,
wenn ich ihn als Unterfunktion in anderen Scripts nutze, wo die vorherige Version problemlos lief.
Ist da noch irgend ein Fehler drin? Ich kann keinen finden.
|
|
Flitzs
      
Beiträge: 123
Erhaltene Danke: 7
Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
|
Verfasst: Mi 13.07.11 20:33
Hallo!
Die Fehlerbeschreibung "funktioniert nicht" ist i.d.R. schlecht
Das einzige mögliche Problem (abgesehen von einigen Schönheitsmakeln und unnötigen Schleifen/Variablen usw.) das mir bei deinem Code von vor drei Posts aufgefallen ist, dass du die Anzahl der Wörter auf Basis der ersten Zeile ermittelst. Wenn jedoch eine der nachfolgenden Zeilen mehr Wörter hat, funktioniert es dann natürlich nicht mehr. Kann das der Fall sein?
Ich gehe natürlich davon aus, dass das Format der Datei passt (Trennzeichen an der richtigen Stelle usw.).
lg Flitzs
|
|
Stephan202 
      
Beiträge: 16
|
Verfasst: Mi 13.07.11 21:16
Hallo,
Nachdem ich den Rechner gestern ausgeschaltet und heute wieder hochgefahren habe lief das Ding wieder.
Hm. Scheint also nicht am Code gelegen zu haben.
Vielen Dank nochmal Euch allen für die gute Hilfe.
Werd mir Eure hilfreichen Kommentare in mein persönl. "C# für Teilzeit-Amateure"-Handbuch kopieren. 
|
|
|