GideonRavenor
Anmeldungsdatum: 1. März 2015
Beiträge: 171
|
Ich habe hier ein wunderschönes Programm geschrieben, das eine kleine Caesar-Verschlüsselung mit Zeichen und Ziffern durchführen soll.
Klappt an sich, nur ist die erstellte Text-Datei immer in irgendeinem ISO-format. Wenn Ich sie mit Mousepad öffnen möchte, meldet das Programm "Dieses Dokument ist kein gültiges UTF-8". Ich muss dann einen der ISO-Standards auswählen, um die Datei anzeigen / öffnen zu können. Außerdem wird in der ver- / entschlüsselten Datei immer ein komisches Zeichen "ÿ" angehängt - Ich vermute, dass da versehentlich das EOF noch mitgezogen wird, obwohl das feof-Funktion in der while eigentlich abfangen müsste. Weiß da jemand Rat? 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 | #include <stdio.h>
int encodeAlpha(int ch)
{ int rueck;
if(ch < 'a')
rueck = (ch-'A'+13)%26+'A';
else
rueck = (ch-'a'+13)%26+'a';
return rueck;
}
int encodeDigit(int ch)
{ return( ((ch - '0' +5) % 10 ) + '0' );
}
int main(int argc, char *argv[])
{ if(argc == 3)
{ FILE *fpQ, *fpZ;
char alpha, omega;
int digitIn, digitOut;
if( (fpQ = fopen(argv[1], "r")) != 0 && ((fpZ = fopen(argv[2], "w")) != 0) )
{
while ( feof(fpQ) == 0)
{ alpha = fgetc(fpQ);
digitIn = (int)alpha;
//printf("%c ", digitIn);
if( (digitIn >= 'A' && digitIn <= 'Z') || (digitIn >= 'a' && digitIn <= 'z') )
digitOut = encodeAlpha(digitIn);
else if( digitIn >= '0' && digitIn <= '9')
digitOut = encodeDigit(digitIn);
else
digitOut = digitIn;
omega = (char)digitOut;
fputc(omega, fpZ);
//printf("%c ", omega);
}
fclose(fpQ);
fclose(fpZ);
}
else
fprintf(stderr, "Fehler, Datei konnte nicht geoffnet werden!\n");
}
else
printf("Falscher Aufruf!\n<programmname> <quelldateiname> <zieldateiname>\n");
return 0;
}
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11260
Wohnort: München
|
Schau mal hier: http://www.cprogramming.com/tutorial/unicode.html. Das Problem dürfte sein, dass du durch den ROT-13 Werte für Zeichen bekommst, die sich nicht mehr mit 7 Bit (0-127) darstellen lassen. Und dann musst du berücksichtigen, dass UTF-8 Zeichen mit mehr als 7 Bit Informationen mit mehr als einem Byte darstellt (vgl. UTF-8).
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6500
Wohnort: Hamburg
|
Ich habe hier ein wunderschönes Programm geschrieben, ...
Jo, eigene Programme sind immer wunderschön, jedenfalls solange sie nicht abstürzen 😉 Für die Umwandlung von Zeichencodes > 127 in UTF-8 sollte man vorzugsweise die entsprechenden Wide-Character Funktionen. Aber ich habe mich einmal darin versucht das selber zu lösen. Hier mal ein Auszug aus meiner Rezepte Sammlung:
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 | /*
UTF-8 Codierung eines Unicode Zeichens. Diese Version ist nicht
thread-save wegen des statischen Puffers. Das kann aber bei Bedarf geändert
werden, indem der Anwender den Puffer (8 Bytes) bereit stellt.
Dabei ist zu beachten, das der zurückgelieferte Zeiger nicht auf den
Pufferanfang zeigt. Er darf also nicht für free() verwendet werden.
*/
/* ---------------------------------------------------------------------------
** Encode an unicode character to an UTF-8 string
*/
char *
code2utf8( unsigned long code )
{
static char string[8]; /* storage for UTF-8 chars */
int i = 7; /* index to last output char */
unsigned long val = code;
unsigned long startmax = 0x3F; /* max possible value in startbyte */
unsigned int startbits = 0x80; /* one bit for every byte */
string[ i ] = '\0'; /* mark end of string */
if ( val > 127 ) { /* do we need UTF-8 encoding? */
while ( i > 0 ) {
if ( val <= startmax ) {
/* the remaining bits will fit into startbyte */
string[ --i ] = val | startbits;
break;
}
/* we will need another byte */
string[ --i ] = (val & 0x3F) | 0x80;
val >>= 6;
startmax >>= 1;
startbits = (startbits >> 1) | 0x80;
}
} else { /* ASCII direct, no UTF-8 needed */
string[ --i ] = val;
}
return string + i;
}
|
Vielleicht hilft das ja.
|
GideonRavenor
(Themenstarter)
Anmeldungsdatum: 1. März 2015
Beiträge: 171
|
Hm, aber wir verlassen in meinem Beispiel doch den zulässigen Bereich gar nicht?
Alle Zeichen von a-z und A-Z werden wieder geschoben zu ganz normalen ASCII-Zeichen.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6500
Wohnort: Hamburg
|
Hm, aber wir verlassen in meinem Beispiel doch den zulässigen Bereich gar nicht?
Offenbar doch, denn "Dieses Dokument ist kein gültiges UTF-8"
UTF-8 Strings haben immer das Minus-Bit gesetzt, wobei dabei immer bestimmte Muster eingehalten werden. Die Fehlermeldung lässt darauf schließen, das diese Muster nicht vorliegen. Ohne gesetztes Bit-7 würde dein Mousepad gar nicht auf die Idee kommen auf UTF-8 zu testen.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11260
Wohnort: München
|
GideonRavenor schrieb: Hm, aber wir verlassen in meinem Beispiel doch den zulässigen Bereich gar nicht?
Alle Zeichen von a-z und A-Z werden wieder geschoben zu ganz normalen ASCII-Zeichen.
Stimmt, da kommt tatsächlich das EOF durch. Anscheinend bekommst du das als letztes Zeichen der Datei bevor feof() einen anderen Wert als 0 liefert.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6500
Wohnort: Hamburg
|
Stimmt, da kommt tatsächlich das EOF durch.
Ups, über den Fehler bin ich auch schon mal gestolpert. feof() liefert erst dann TRUE, wenn man über das Dateiende hinaus gelesen hat. Daher muss man eigentlich auch die Ausgabe von fgetc() auf den Wert EOF testen.
|
GideonRavenor
(Themenstarter)
Anmeldungsdatum: 1. März 2015
Beiträge: 171
|
Tatsache, das ist es.
Warum mir das das Format zerschießt bzw. warum es dann als komisches Zeichen interpretiert wird erschließt sich mir zwar nicht ganz, aber sei's drum, hauptsache Fehler weg.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11260
Wohnort: München
|
GideonRavenor schrieb: Warum mir das das Format zerschießt bzw. warum es dann als komisches Zeichen interpretiert wird erschließt sich mir zwar nicht ganz, aber sei's drum, hauptsache Fehler weg.
| #include <stdio.h>
void main() {
printf("%c", EOF);
}
|
EOF wird bei mir zu ff und das ist mehr als sich mit 7 Bit darstellen lässt, und damit ein ungültiges mit nur einem Byte darstellbares Zeichen bei UTF-8:
./a.out | hexdump
0000000 00ff
0000002
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6500
Wohnort: Hamburg
|
Warum mir das das Format zerschießt bzw. warum es dann als komisches Zeichen interpretiert wird erschließt sich mir zwar nicht ganz ...
EOF wird normalerweise als -1 (int) codiert, d.h. alle Bits an. Wenn das dann als Character interpretiert wird ergibt das den Wert 255 (0xFF), was keine gültige UTF-8 Codierung ist und außerhalb des Wertebereichs für ASCII Zeichen liegt. Das Unicode Zeichen ÿ hat denn auch den Wert U+00FF.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11260
Wohnort: München
|
Dakuan schrieb: Das Unicode Zeichen ÿ hat denn auch den Wert U+00FF.
Was dann in UTF-8 durch 2 Bytes dargestellt wird:
11000011 10111111
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6500
Wohnort: Hamburg
|
Das ist mir bekannt, aber wegen: Ich muss dann einen der ISO-Standards auswählen, um die Datei anzeigen / öffnen zu können.
bin ich davon ausgegangen, das dadurch eine irgendwie passende Codepage geladen wird.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11260
Wohnort: München
|
Ja, dann hat er einen Zeichensatz gewählt, der 8-Bit Zeichen nutzt, da passt das mit dem ÿ = 0xFF: ISO_8859-1
|
GideonRavenor
(Themenstarter)
Anmeldungsdatum: 1. März 2015
Beiträge: 171
|
Interessant. Lässt UTF-8 denn nur 7-Bit-ASCII-Zeichen bzw. Zusammensetzungen daraus zu? Ich dachte es wäre der Witz am Unicode, alle Zeichen der Menschheit darstellen zu können.
Was muss man denn tun, um mit C Zeichen jenseits der ASCII-Tabelle auszugeben?
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17620
Wohnort: Berlin
|
Nun, ich würde sagen, dass C lange vor allen UTF-Codes entworfen und standardisiert wurde. Ich bin da nicht auf dem Laufenden, aber würde mich wundern, wenn ein char nicht nach wie vor ein Byte wäre. Und mit einem Byte kann man sicher nicht alle Zeichen der Menschheit darstellen.
|