| Autor |
Nachricht |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 6924
|
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: 18395
|
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: 6924
|
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
|
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: 6924
|
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
|
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
|
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
|
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: 18395
|
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
|
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 |
|
 |
|
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.
|
|
|
|
|