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
Antwort schreiben
Benutzername:
Titel:
Nachrichtentext:
  :)  :D  ;)  :(  :p  :mad:  :rolleyes:  :eek:  :confused:  :cool:  :o)  :leak:  :live:  :die:  :idea:  :arrow:  :warning: 
                             
                         
         
           
                             
                             
                             
             


BBCode in diesem Beitrag deaktivieren [BBCode]
Smilies in diesem Beitrag deaktivieren
String Array mit qsort sortieren and 301073
     


Themen-Überblick 
(Aktualisieren)
Autor Nachricht
DirkB
13:28:23 20.03.2012   Titel:   Zitieren

Zoltamor schrieb:
Ja aber es ist halt die maximale Länge, also sehe ich da kein Problem oder?

Sehr schlechte Einstellung.

Strings enden beim Stringendezeichen '\0' und nicht nach 254 Zeichen wie bei dir.

Einmal richtig programmiert und du kannst es immer wieder ohne Änderung verwenden.

Zudem vergleichst du ja jedes Zeichen einzeln mit einer Stringfunktion.

Das macht man eigentlich direkt mit den Zeichen:
C++:
result = (int)*(string1+i)-(int)*(string2+i); // Der * ist kein mal sondern das Dereferenzierungszeichen
Zoltamor
12:56:15 20.03.2012   Titel:   Zitieren

Ja aber es ist halt die maximale Länge, also sehe ich da kein Problem oder?

Grundsätzlich funktioniert das sortieren ja, nur dass er mir nur den ersten char nach Groß- und Kleinschreibung sortiert (also klein vor groß), aber warum ist die Frage? Ich vergleiche ja eh die kompletten Strings...

MFG
DirkB
11:49:36 20.03.2012   Titel:   Zitieren

Das for(int i = 0;i<255;i++) ist für Strings schon mal großer Mist, da ein String ja auch mal weniger Zeichen enthalten kann.

Du musst doch nur wenn strcasecmp 0 zurückliefert und strcmp != 0 vom Ergebnis von strcmp das Vorzeichen ändern.
C++:
if ( !(result = strcasecmp(string1,string2)))  /* Es sind die gleichen Woerter) */
  result = -strcmp(string1,stringg2);   /* Bei 0 sind sie gleich, sonst willst du das umgekehrte Verhalten */
Zoltamor
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
SeppJ
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?
Zoltamor
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
DirkB
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
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
cooky451
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.
Zoltamor
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

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.