Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   

Die mobilen Seiten von c++.de:
http://m.c-plusplus.de
Infos hier [BETA]

  
c++.de :: C (C89, C99 und C11) ::  String Array mit qsort sortieren  
Gehen Sie zu Seite 1, 2, 3  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
Zoltamor
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
Beitrag 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:

Code:
das
ist
ein
test


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 -->

Code:
das
ein
ist
test


MFG Zoltamor
cooky451
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6924
Beitrag 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. :D 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
Beitrag 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: 6924
Beitrag 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
Beitrag 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: 18398
Beitrag SeppJ Moderator 12:32:45 19.03.2012   Titel:              Zitieren

Zoltamor schrieb:

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.

http://cdecl.org/

Das ist ein Pointer auf ein char[256].

_________________
Du brauchst Hilfe?, Buchempfehlungen für C++,
Wie man in Fragen den richtigen Code postet,
The Definitive C++ Book Guide and List
Zoltamor
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
Beitrag 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: 18398
Beitrag 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
Beitrag 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 :confused:

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: 18398
Beitrag 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
c++.de :: C (C89, C99 und C11) ::  String Array mit qsort sortieren  
Gehen Sie zu Seite 1, 2, 3  Weiter
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




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.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.