| Autor |
Nachricht |
Zoltamor
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
|
Zoltamor Mitglied
02:15:51 19.03.2012 Titel: |
String Array mit qsort sortieren |
Zitieren |
Hallo!
Hoffe ihr könnt mir nochmal helfen, denn jetzt komm ich denk ich wirklich nicht weiter.. Mein Programm sieht bisher so aus:
| C++: | 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 | #include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *datei;
char arr[257]; //da Namen maximal 255 Zeichen lang
char namen[257][257];
int zahler=0;
int i;
datei = fopen("test.txt" , "r");
while(fgets(arr, 257,datei) != NULL)
{
zahler++;
}
fclose(datei);
datei = fopen("test.txt" , "r");
for(i=0;i<zahler;i++)
{
fgets(arr,257,datei);
strcpy(namen[i],arr);
printf("%s", namen[i]);
}
for(i=0;i<zahler;i++)
{
printf("%s", namen[i]);
}
fclose(datei);
return 0;
} | |
die test.txt sieht wie folgt aus:
Mein Ziel ist es jetzt, die Strings im Array namen zu sortieren! Will das mit qsort machen
qsort(namen,sizeof(namen),sizeof(char*),compare_strings);
stimmt dieser Ansatz? und wie muss die Funktion compare_strings jetzt aussehen, damit die Strings alphabetisch sortiert werden -->
MFG Zoltamor |
|
|
|
 |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6873
|
cooky451 Mitglied
02:59:46 19.03.2012 Titel: |
|
Zitieren |
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char strings[256][257];
char (*p)[257] = strings;
for (; p != strings + sizeof(strings) / sizeof(*strings) && fgets(*p, sizeof(*p), stdin) != NULL; ++p);
qsort(strings, p - strings, sizeof(*p), (int (*) (const void*, const void*))strcmp);
while (p-- != strings)
printf("%s", *p);
return 0;
} | |
Viel Spaß damit. Ach ja: http://cdecl.org/ |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
Keksverteilungsbeauftragter
Zuletzt bearbeitet von cooky451 am 17:24:15 19.03.2012, insgesamt 4-mal bearbeitet |
|
 |
Zoltamor
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
|
Zoltamor Mitglied
11:50:28 19.03.2012 Titel: |
|
Zitieren |
Danke schonmal. Hab jetzt probiert das so in meinen Code einzubauen, klappt aber leider nicht. Die erste normale Ausgabe kommt noch, und dann bleibt das Programm stehen und ich kann Eingaben machen, ohne dass es einen Sinn hätte.
Programm sieht jetzt so aus:
| C++: | 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 43 44 45 | #include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *datei;
char arr[257]; //da Namen maximal 255 Zeichen lang
char namen[257][257];
int zahler=0;
int i;
datei = fopen("test.txt" , "r");
while(fgets(arr, 257,datei) != NULL)
{
zahler++;
}
fclose(datei);
datei = fopen("test.txt" , "r");
for(i=0;i<zahler;i++)
{
fgets(arr, 257,datei);
strcpy(namen[i],arr);
printf("%s", namen[i]);
}
char (*p)[257] = namen;
for (; p != namen + sizeof(namen) / sizeof(*namen) && fgets(*p, sizeof(*p), stdin) != NULL; ++p);
{
qsort(namen, p - namen, sizeof(*p), (int (*) (const void*, const void*))strcmp);
while (p-- != namen)
printf("%s", *p);
}
fclose(datei);
return 0;
} | |
Wo ist der Fehler? Und: Kannst du mir (falls du eine Lösung findest) noch kurz erklären, was die macht? Wäre wirklich sehr dankbar
MFG Zoltamor |
|
|
|
 |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6873
|
cooky451 Mitglied
11:59:31 19.03.2012 Titel: |
|
Zitieren |
Würde ich ja, aber du solltest dir zumindest die Mühe machen zu versuchen zu verstehen was mein Programm macht. Offensichtlich hast du es ja nicht mal ausgeführt sondern einfach mal irgendwie in dein Programm kopiert, und dann auch noch falsch.. |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
Keksverteilungsbeauftragter
|
|
 |
Zoltamor
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
|
Zoltamor Mitglied
12:15:19 19.03.2012 Titel: |
|
Zitieren |
Ja hast wohl Recht, entschuldige für das.
Nun gut, dann gehn wirs an:
Hab mir dein Programm jetzt Mal an sich genauer angeschaut, werd aber trotzdem nicht schlau daraus:
Ich hab ein 2dimensionales char Array strings.
In der zweiten Zeile häng ich schon, was passiert da? Hab die Schreibweise einfach noch nicht gesehen! Is das ein Array von Pointern, wo jeder Pointer auf strings verweist? Vielleicht wirds klarer wenn ich Mal weiß, was das is.
MFG Zoltamor |
|
|
|
 |
SeppJ
Moderator
Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17979
|
SeppJ Moderator
12:32:45 19.03.2012 Titel: |
|
Zitieren |
|
 |
Zoltamor
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
|
Zoltamor Mitglied
12:53:00 19.03.2012 Titel: |
|
Zitieren |
Ok, also ein unbenanntes char, das genau dieselben Elemente aufweist wie strings, richtig? Also es zeigt darauf.
die for-Schleife: brauch ich da nirgends Klammern, oder wieso rennt das so?
der qsort Befehl: der Beginn is strings, Anzahl der Elemente is p-strings, Größe der Elemente is die sizeof(*p) und die compare-Funktion (wobei ich nicht genau weiß was die macht)
MFG Zoltamor |
|
|
|
 |
SeppJ
Moderator
Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17979
|
SeppJ Moderator
14:13:22 19.03.2012 Titel: |
|
Zitieren |
| Zoltamor schrieb: | Ok, also ein unbenanntes char, das genau dieselben Elemente aufweist wie strings, richtig? Also es zeigt darauf.
|
Häh, was? Es ist ein Pointer auf ein Array mit 256 char-Elementen. Nicht mehr und nicht weniger. Da es auf den Anfang eines Arrays von diesen 256-char-Arrays zeigt, kann man sich mittels Pointerarithmetik (googlen, falls der Begriff unbekannt ist!) durch die verschiedenen 256-char-Array-Elemente dieses Arrays hangeln.
(Warum machst du deine Arrays eigentlich 257 Zeichen lang, wenn du 255 Zeichen aufnehmen möchtest? 256 würde doch reichen: 255 Zeichen + Nullterminierung. Ich fürchte, du hast die Bedeutung von Arraydefinitionen nicht richtig verstanden)
| Zitat: |
die for-Schleife: brauch ich da nirgends Klammern, oder wieso rennt das so?
|
Du hast die Schleife gar nicht verstanden. Sie ist leer. Achte auf das Semikolon. Deine Klammern da machen überhaupt nichts und die Einrückung passt nicht zur Syntax. So wie cooky451 das formatiert hat, passt das schon. Würde ja auch herzlich wenig Sinn machen, das Sortieren und Ausgeben nochmals in eine Schleife zu packen. (Dir ist klar, dass die Zeilen 10-12 in cooky451s Programm sortieren und ausgeben?)
| Zitat: |
der qsort Befehl: der Beginn is strings, Anzahl der Elemente is p-strings, Größe der Elemente is die sizeof(*p) und die compare-Funktion (wobei ich nicht genau weiß was die macht) | Dann schlag es nach! Wenn man eine Funktion mit komischen Argumenten sieht, dann reimt man sich diese nicht zusammen, sondern guckt in eine Referenz:
http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
(Wobei ich noch erwähnen sollte, dass du es dir richtig zusammengereimt hast)
| Zitat: | comparator
Function that compares two elements. The function shall follow this prototype:
int comparator ( const void * elem1, const void * elem2 );
The function must accept two parameters that are pointers to elements, type-casted as void*. These parameters should be cast back to some data type and be compared.
The return value of this function should represent whether elem1 is considered less than, equal to, or greater than elem2 by returning, respectively, a negative value, zero or a positive value.
| Irgendwie muss qsort ja wissen, wie man zwei Elemente vergleicht. strcmp ist da schon passend von der Funktionalität her (Ein einfaches < würde bei Zeichenketten schließlich nicht funktionieren), man muss die Funktion bloß noch entsprechend casten, damit die Signatur stimmt.
| c.rackwitz schrieb: | | Wenn du selber Code schreibst, musst du ihn auch verstehen. Code ist kein Haufen von wahllos zusammengeschmissenen Buchstaben und Zeichen, Code ist Logik pur. Du musst genau wissen, warum du wo und welches Zeichen setzt. | Das gilt natürlich besonders, wenn man anderer Leute Code übernimmt. |
_________________ Du brauchst Hilfe?, Buchempfehlungen für C++,
Wie man in Fragen den richtigen Code postet,
The Definitive C++ Book Guide and List
Zuletzt bearbeitet von SeppJ am 14:34:38 19.03.2012, insgesamt 4-mal bearbeitet |
|
 |
Zoltamor
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
|
Zoltamor Mitglied
14:34:35 19.03.2012 Titel: |
|
Zitieren |
Ok.
Bezüglich Array-länge: Wird die Null-Terminierung unter Windows oder Linux, 1 von beiden, nicht bei einem als 2 Zeichen angesehen? Hat mir zumindest Mal jemand so erklärt, deshalb noch 1 zusätzlich, vielleicht ist es auch Unsinn?
Da hast du leider recht, die Schleife hab ich wirklich nicht verstanden . Die Abgrenzung mit Semikolon ist mir natürlich bewusst und ich hab sie auch bemerkt, aber den Aufbau verstehe ich trotzdem nicht ganz --> for-Schleife mit Semikolon am Schluss, warum? Normalerweise wenn sie keine {} hat zählt nur die nächste Zeile, aber was hat es hiermit auf sich? Wie du bereits erwähnt hast gehört dies ja nicht zur Schleife dazu. Was die diversen Berechnungen hier aber machen, das ist mir einfach ein Rätsel! Tut mir leid, vielleicht bin ich im Moment einfach wirklich begriffsstützig
qsort hab ich auch vorher schon nachgeschlagen, eh genau dort wo du hinverweist, ich wollte auch nur wissen ob die ersten 3 Parameter so richtig interpretiert sind von mir, und der vierte, naja, der vergleicht praktisch 2 Pointer, aber was für welche?
Ich will ihn auch wirklich verstehen! Es bringt mir für die Zukunft eh nix, jetzt irgendwas zu kopieren, selbst wenn es funktioniert, Erklärungen sind 1000 Mal mehr Wert, das weiß ich
MFG Zoltamor |
|
|
|
 |
SeppJ
Moderator
Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17979
|
SeppJ Moderator
14:51:36 19.03.2012 Titel: |
|
Zitieren |
| Zoltamor schrieb: | Ok.
Bezüglich Array-länge: Wird die Null-Terminierung unter Windows oder Linux, 1 von beiden, nicht bei einem als 2 Zeichen angesehen? Hat mir zumindest Mal jemand so erklärt, deshalb noch 1 zusätzlich, vielleicht ist es auch Unsinn?
| Du denkst an Zeilenumbrüche. Aber auch das spielt im Programm keine Rolle, sondern nur dann, wenn du zum Beispiel Daten (nicht-binär) in eine Datei schreibst. Dann werden in Windows alle '\n'-Zeichen zu einer Zweizeichenkombination (ich glaube \r\n (oder war es \n\r?)) umgewandelt (und zwar automatisch!).| Zitat: |
Da hast du leider recht, die Schleife hab ich wirklich nicht verstanden . Die Abgrenzung mit Semikolon ist mir natürlich bewusst und ich hab sie auch bemerkt, aber den Aufbau verstehe ich trotzdem nicht ganz --> for-Schleife mit Semikolon am Schluss, warum? Normalerweise wenn sie keine {} hat zählt nur die nächste Zeile, aber was hat es hiermit auf sich?
|
Die Schleife hat bereits alles im Kopf, was sie machen soll. Daher braucht sie keinen Körper. Man könnte sie auch so schreiben:
| C++: | 1 2 3 4 5 6 7 8 | while (1)
{
if !(p != namen + sizeof(namen) / sizeof(*namen))
break;
if !(fgets(*p, sizeof(*p), stdin) != NULL)
break!
++p;
} | | Jetzt sollte auch klarer sein, was das überhaupt macht. Zeile 3 prüft, ob man am Ende des vorreservierten Arrays ist und bricht gegebenenfalls ab. Zeile 5 liest eine Zeile ein und überprüft den Rückgabewert der Lesefunktion (das ist immer eine gute Idee!). Tritt ein Fehler auf, wird abgebrochen. Fehler bedeutet bei dieser Aktion normalerweise Dateiende, das heißt effektiv wird bis zum Dateiende gelesen oder bis 256(257)-Strings gelesen wurden, was eher eintritt.
Zeile 7 setzt dann den Zeiger p auf das nächste 256-char-Array aus dem großen Array strings. Ich habe oben in meiner Antwort noch das Stichwort Pointerarithmetik reineditiert, als du schon geantwortet hast.
| Zitat: |
qsort hab ich auch vorher schon nachgeschlagen, eh genau dort wo du hinverweist, ich wollte auch nur wissen ob die ersten 3 Parameter so richtig interpretiert sind von mir, und der vierte, naja, der vergleicht praktisch 2 Pointer, aber was für welche?
| Irgendwie muss die Funktion qsort zwei Elemente vergleichen. Da C nicht die Abstraktionstechniken von C++ kann, muss ein allgemeiner Vergleich für eine allgemeine Sortierfunktion über void-Zeiger mit entsprechenden Casts erfolgen. Das Thema ist vermutlich ein bisschen zu hoch für einen Anfänger. Um das zu verstehen könntest du ja mal eine einfache Sortierfunktion für ein Integerfeld schreiben (es muss ja nicht gleich quicksort sein, ein einfacher Algorthmus reicht zum Üben auch). Wenn du weißt, das alle Elemente Integer sind, kannst du zwei Elemente mittels '<' vergleichen. Wenn du dann versuchst, diese Funktion zu verallgemeinern, dass sie Arrays von irgendwelchen Typen sortieren kann (die du vorher nicht kennst!), dann kann das nicht mehr funktionieren (Zeichenketten zum Beispiel kann man nicht mit < verlgeichen). Dann musst du dir eine allgemeine Vergleichsfunktion vom Nutzer übergeben lassen, die zu den Elementen passt. Und eine allgemeine Funktion, die zwei Parameter von irgendeinem Typ nehmen kann und dann einen Vergleichswert zurückgibt, die kann in C nur über void-Zeiger funktionieren, da man void-Zeiger in und aus allen anderen Zeigertypen umwandeln kann. |
_________________ Du brauchst Hilfe?, Buchempfehlungen für C++,
Wie man in Fragen den richtigen Code postet,
The Definitive C++ Book Guide and List
Zuletzt bearbeitet von SeppJ am 14:55:57 19.03.2012, insgesamt 2-mal bearbeitet |
|
 |
|
Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
|
|
|
|
|