Themen-Überblick
(Aktualisieren)
| Autor |
Nachricht |
DirkB
|
| 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
|
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
|
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
|
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
|
| 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
|
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
|
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
|
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
|
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
|
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 |
|
|
 |
|
|
|
|
|