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 Zurück  1, 2, 3  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
cooky451
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6870
Beitrag cooky451 Mitglied 14:53:24 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?

Falsch gemerkt. Nullterminierung ist immer '\0', sonst nichts. Was unterschiedlich ist, ist das Zeilenende. Das ist unter Unix nur "\n", während unter Windows "\r\n" üblich ist. Wenn du also wirklich bis zu 255 Buchstaben + Zeilenende lesen möchtest, bräuchtest du theoretisch 258 Zeichen. Window wandelt im Textmodus aber \r\n zu \n. Sind wir bei 257 Zeichen. Interessant, wenn man wirklich sicher gehen will, dass Name und Zeilenende passen braucht man tatsächlich 257 Zeichen, es sei denn man führt noch extra Tests durch. ;)


Zoltamor schrieb:
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?

Ein ";" entspricht einer leeren Answeisung. Ist also gleichbedeutend mit {}:
C++:
for (; a; b;);
for (; a; b;) {}
while (a) b;
while (a) { b; }

Alles gleich.

Zoltamor schrieb:
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?

Der letzte Parameter ist: "ein Zeiger auf eine Funktion die int zurückgibt und als Parameter zwei Pointer auf void nimmt.".
Das sind const void*, weil qsort ja den Datentypen der verglichen wird nicht kennen kann. Je ein const void* zeigt auf ein Element, und die Funktion soll diese Elemente vergleichen.

Da wir strings vergleichen wollen und es bereits eine Funktion gibt die genau das macht was wir wollen, nehmen wir die einfach. Nur passt die Signatur nicht, allerdings sind const void* und const char* ganz gut kompatibel, sodass wir einfach casten können.
(Das const bedeutet übrigens, dass das worauf der Pointer zeigt nicht verändert werden soll.)

_________________
Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
Keksverteilungsbeauftragter


Zuletzt bearbeitet von cooky451 am 14:55:45 19.03.2012, insgesamt 1-mal bearbeitet
SeppJ
Moderator

Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17952
Beitrag SeppJ Moderator 14:58:49 19.03.2012   Titel:              Zitieren

cooky451 schrieb:

Falsch gemerkt. Nullterminierung ist immer '\0', sonst nichts. Was unterschiedlich ist, ist das Zeilenende. Das ist unter Unix nur "\n", während unter Windows "\r\n" üblich ist. Wenn du also wirklich bis zu 255 Buchstaben + Zeilenende lesen möchtest, bräuchtest du theoretisch 258 Zeichen. Window wandelt im Textmodus aber \r\n zu \n. Sind wir bei 257 Zeichen. Interessant, wenn man wirklich sicher gehen will, dass Name und Zeilenende passen braucht man tatsächlich 257 Zeichen, es sei denn man führt noch extra Tests durch. ;)
Nein. Die Umwandlung erfolgt irgendwo tief in den Eingeweiden des Dateistreams. Sämtliche Lesefunktionen die darauf arbeiten und erst recht dein Hauptprogramm bekommen davon gar nichts mehr mit. Das fgets sieht nur ein \n, wo in der Datei \r\n stand.

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

Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6870
Beitrag cooky451 Mitglied 16:53:53 19.03.2012   Titel:              Zitieren

SeppJ schrieb:
Das fgets sieht nur ein \n, wo in der Datei \r\n stand.
Du hast meinen Punkt nicht verstanden. 255 Zeichen für den Namen + \n + \0 macht de facto 257. ;)

_________________
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 19:09:53 19.03.2012   Titel:              Zitieren

Wirklich klarer wird mir der erste Teil der Schleife leider auch nicht, der 2te is jetzt logisch, aber der Anfang:

Was macht das Rufzeichen vor der Anweisung? Normalerweise würde ich sagen, wenn der Ausdruck falsch ist, aber wenn ich versuche das so zu kompilieren, kommt ein Error. Hätte es nicht den gleichen Effekt, wenn ich das Rufzeichen weglasse, und nicht != sondern == abfrage? Dann funktioniert es nämlich.

Dann: Kannst du mir noch erklären, was genau du in der Schleife (Zeile 3) berechnest? Oder eher, warum du das so berechnest?

Und bezüglich qsort: was meinst du mit casten? Und was mir noch aufgefallen ist, warum sortiert es die Namen verkehrt?

MFG
cooky451
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6870
Beitrag cooky451 Mitglied 20:08:49 19.03.2012   Titel:              Zitieren

Ach komm, was solls. Hier:
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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    char strings[256][257]; // 256 Arrays mit je 257 chars
    char (*p)[257] = strings; // Ein Pointer auf ein Array mit 257 chars. Zeigt jetzt auf das erste Array von strings.
        // Hier wird eingelesen
    for (; p != strings + sizeof(strings) / sizeof(*strings) && fgets(*p, sizeof(*p), stdin) != NULL; ++p);
        // sizeof(strings) / sizeof(*strings) berechnet wie viele Elemente strings hat, das sind hier 256
        // p darf also nicht strings + arraygröße(strings) sein.
        // Diese Bedingung wird zu erst getestet, wenn sie wahr ist, wird fgets() aufgerufen.
        // *p ist ein Array, das zerfällt bei der Übergabe in einen Zeiger auf das erste Element.
        // (Wie du es auch schon kennst von eindimensionalen Puffern.)
        // sizeof(*p) gibt hier 257 zurück.
        // ++p lässt p sizeof(*p) byte weiter nach vorne zeigen.
        // (Dort liegt dann das jeweils nächste Array[257] aus strings)
 
        // Hier wird sortiert. Nach "casten c++" kannst du selbst googlen.
    qsort(strings, p - strings, sizeof(*p), (int (*) (const void*, const void*))strcmp);
 
        // Das hier ist die Ausgabe, wie du siehst wird rückwärts ausgegeben.
        // Das letzte Element wird als erstes ausgegeben und so weiter.
    while (p-- != strings)
        printf("%s", *p);
 
    return 0;
}


Edit: Zu SeppJs !: Da hat er Klammern vergessen.

_________________
Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
Keksverteilungsbeauftragter


Zuletzt bearbeitet von cooky451 am 20:11:28 19.03.2012, insgesamt 3-mal bearbeitet
Zoltamor
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
Beitrag Zoltamor Mitglied 09:40:47 20.03.2012   Titel:              Zitieren

Danke schonmal vielmals, langsam wird mir alles klar!

Ich hab das mit qsort jetzt noch ein bisschen anders gelöst, und zwar so:

meine Aufruffunktion ist

C++:
qsort (namen, zahler, sizeof(char*), compare);


die Funktion compare schaut so aus:

C++:
int compare (const void * a, const void * b)
{
    return strcmp(a,b);
}

is ja eig. nur die längere Version von dir.

Soweit funktioniert das auch, allerdings hab ich ein kleines Problem: ich will die Strings ein wenig anders sortieren, und zwar so, dass aA vor Aa is, was hier leider nicht der Fall is.

Könnt ihr mir nochmal helfen? Wäre wirklich sehr dankbar!

MFG Zoltamor


Zuletzt bearbeitet von Zoltamor am 09:41:32 20.03.2012, insgesamt 3-mal bearbeitet
DirkB
Unregistrierter




Beitrag DirkB Unregistrierter 09:59:32 20.03.2012   Titel:              Zitieren

Dann musst du dir deine eigene strcmp() bauen.

Wenn du den Quellcode von strcmp() hast, wirst du sehen, dass das eine ziemlich einfache Funktion ist.

Die strcmp-Versionen, die zumindest Groß/kleinschreibung ignorieren heissen meist
strcasecmp oder strcmpi.
Auch dazu solltest du Quellen finden, damit du das anpassen kannst.

Bedenke noch das qsort nur darauf achtet, ob die Werte <0 , ==0 oder >0 sind.
Es muss nicht -1 oder +1 sein
Zoltamor
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.09.2011
Beiträge: 21
Beitrag Zoltamor Mitglied 10:12:50 20.03.2012   Titel:              Zitieren

Ok, hab das ganze jetzt ein wenig anders gelöst, und zwar so:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int compare (const void * a, const void * b)
{
 
int result = 0;
    char* string1 = (char*) a;
    char* string2 = (char*) b;
    //run through all chars in the string
 
 for(int i = 0;i<255;i++)
    {
        // compare each char case insensitive
            result = strncasecmp(string1+i,string2+i,1);
            result*=2;
           // if a char is the uppercase variant of the other strings char and the words have the same length add 1 to the result do differentiate between upper and lower
            if(isupper((int)string1[i])!= 0 && result == 0 && strlen(string1)==strlen(string2)) result+=1;
            else if( isupper((int)string2[i])!= 0 && result == 0 && strlen(string1)==strlen(string2)) result=-1;
            if(result != 0) break;
    }
  return result;
}


Allerdings hab ich einen Error, und keine Ahnung was dieser bedeutet:

error: 'for' loop initial declaration used outside C99 mode

der Aufruf mit qsort ist dieser:
C++:
qsort (namen, zahler, sizeof(char*), compare);


Was is da falsch gelaufen?

MFG Zoltar


Zuletzt bearbeitet von Zoltamor am 11:02:41 20.03.2012, insgesamt 1-mal bearbeitet
SeppJ
Moderator

Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17952
Beitrag SeppJ Moderator 11:23:12 20.03.2012   Titel:              Zitieren

Zoltamor schrieb:

Allerdings hab ich einen Error, und keine Ahnung was dieser bedeutet:

error: 'for' loop initial declaration used outside C99 mode

der Aufruf mit qsort ist dieser:
C++:
qsort (namen, zahler, sizeof(char*), compare);

Guck doch mal genau auf den Fehler. Der ist ganz woanders.

Schleifen der Form for(Deklaration;...) darfst du erst ab C99-Standard. Das musst du bei deinem Compiler anscheinend aktivieren (-std=c99 bei GCC), sofern er es überhaupt kann (ja, der MS Compiler kann C99 (das 99 steht für 1999) überhaupt nicht und wird es wohl auch nie können).

Deine Vergleichsfunktion ist übrigens ziemlich sicher total falsch, außer du möchtest ganz was anderes als ich vermute. Was soll die machen? Groß-/Kleinschreibung beim Vergleich ignorieren?

_________________
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 11:48:20 20.03.2012   Titel:              Zitieren

Mein Programm sortiert jetzt zwar Klein- vor Großbuchstaben, aber nur den ersten char! Obwohl ich natürlich jeden String nach klein- und großschreibung sortieren will.. Könnt ihr mir sagen, wo der Fehler ist?

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
 
 
 
int compare (const void * a, const void * b)
{
 
int result = 0;
    char* string1 = (char*) a;
    char* string2 = (char*) b;
    int i=0;
 
 for(i = 0;i<255;i++)
    {
        // compare each char case insensitive
            result = strncasecmp(string1+i,string2+i,1);
            result*=2;
           // if a char is the uppercase variant of the other strings char and the words have the same length add 1 to the result do differentiate between upper and lower
            if(isupper((int)string1[i])!= 0 && result == 0 && strlen(string1)==strlen(string2)) result+=1;
            else if( isupper((int)string2[i])!= 0 && result == 0 && strlen(string1)==strlen(string2)) result=-1;
            if(result != 0) break;
    }
  return result;
}
 
 
 int main(int argc, char *argv[])
 {
 
 FILE *datei;
 char arr[257]; //da Namen maximal 255 Zeichen lang
 
 int zahler=0;
 int i;
 int vergleich_r;
 int c=0;
 
    if(argc==4)
            datei = fopen(argv[2], "r");
    else
            datei = fopen(argv[1], "r");
 
while ((c = fgetc(datei)) != EOF)       //geht dur Datei bis zum Ende
  {
 
   if( (c >='a' && c <='z')   ||  (c >='A' && c <='Z') || c=='-' || c==' ' || c=='\n' ) //wenn es nur aus diesen Zeichen besteht
       {
        }
        else
       {
            fprintf(stderr,"sortnames: wrong input format\n");
            return 1;
            break;
       }
 
  }
 
 
 fclose(datei);
 
 
 if(argc==4)
            datei = fopen(argv[2], "r");
    else
            datei = fopen(argv[1], "r");
 
    if(datei == NULL)
         {
 
                if(argc==4)     //wenn 4 Parameter übergeben sind und Input Datei nicht vorhanden ist
             {
                fprintf(stderr,"sortnames: cannot open input file: %s\n",argv[2]);
                return 1;
             }
 
             else       //wenn x Parameter übergeben sind und Input Datei nicht vorhanden ist
             {
                fprintf(stderr,"sortnames: cannot open input file: %s\n",argv[1]);
                return 1;
             }
 
         }
 
    while(fgets(arr, 257,datei) != NULL)    //bei jeder eingelesenen Zeile
         {
         zahler++;
         }
 
 fclose(datei);
 
 
 
 
 
 
if(argc==4)
            datei = fopen(argv[2], "r");
    else
            datei = fopen(argv[1], "r");
 
  char namen[zahler][255];
 
 for(i=0;i<zahler;i++)
         {
 
                 fgets(namen[i], 255, datei);
 
         //  printf("Namen Stelle %d: %s",i,namen[i]);
 
         }
 fclose(datei);
 
 
    if(argc<3)  //zu wenig Parameter
    {
       fprintf(stderr,"sortnames: wrong number of input or output files\n");
       return 1;
 
    }
 
 
    if (argc==4)
        {
             vergleich_r = strcmp(argv[1],"-r");    //wenn 4 Parameter, muss der an Stelle 1 die Option sein, also -r
        if (vergleich_r == 0)           //wenn 4 Parameter sind und -r
                {
 
                qsort (namen, zahler, sizeof(char*), compare);
 
 
 
                    if(argc==4)
                        datei = fopen(argv[3], "w");
                    else
                        datei = fopen(argv[2], "w");
 
                     if(datei == NULL)
         {
 
                if(argc==4)     //wenn 4 Parameter übergeben sind und Output Datei nicht gelesen werden ann
             {
                fprintf(stderr,"sortnames: cannot open output file: %s\n",argv[3]);
                return 1;
             }
 
             else       //wenn x Parameter übergeben sind und Output Date nicht gelesen werden kann
             {
                fprintf(stderr,"sortnames: cannot open output file: %s\n",argv[2]);
                return 1;
             }
 
         }
 
 
 
                for(i=zahler;i>=0;i--)
                     {
                     fputs (namen[i],datei);
                     }
                fclose(datei);
                }
 
 
        else                    //4 Parameter, aber kein -r
            {
                fprintf(stderr,"sortnames: wrong option %c\n",argv[1][1]);
                return 1;
            }
 
        }
 
            else        //3 Parameter
                {
 
 
                qsort (namen, zahler, sizeof(char*), compare);
 
                if(argc==4)
                        datei = fopen(argv[3], "w");
                    else
                        datei = fopen(argv[2], "w");
 
 
                if(datei == NULL)
                             {
 
                                    if(argc==4)     //wenn 4 Parameter übergeben sind und Output Datei nicht gelesen werden ann
                                 {
                                    fprintf(stderr,"sortnames: cannot open output file: %s\n",argv[3]);
                                    return 1;
                                 }
 
                                 else       //wenn x Parameter übergeben sind und Output Date nicht gelesen werden kann
                                 {
                                    fprintf(stderr,"sortnames: cannot open output file: %s\n",argv[2]);
                                    return 1;
                                 }
 
                             }
 
                for(i=0;i<zahler;i++)
                     {
                     fputs (namen[i],datei);
                     }
                fclose(datei);
                }
 
 return 0;
 }





MFG Zoltamor


Zuletzt bearbeitet von Zoltamor am 12:46:40 20.03.2012, insgesamt 1-mal bearbeitet
c++.de :: C (C89, C99 und C11) ::  String Array mit qsort sortieren  
Gehen Sie zu Seite Zurück  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.