ubuntuusers.de

Umlaute in C

Status: Gelöst | Ubuntu-Version: Ubuntu 9.04 (Jaunty Jackalope)
Antworten |

supeo

Anmeldungsdatum:
25. Februar 2009

Beiträge: 23

Hallo.

Ich bin noch Programmieranfänger, wollte jedoch ein Programm schreiben, mit welchem man Umlaute in einer Datei mit den HTML-Kodierungen ersetzen kann. Die Umlaute werden jedoch nicht richtig erkannt. Wenn ich in einen String, in welchem Umlaute enthalten sind, ausgeben lasse, werden diese problemlos dargestellt. Lasse ich sie jedoch als Char ausgeben, funktioniert dies nicht. Dezimal, Hexadezimal und auch Oktalzahlen funktionieren ebenfalls nicht. Ich habe schon Header-Datei <locale.h> eingebunden, was nicht auch nicht funktioniert hat bzw. könnte es sein, dass ich es falsch gemacht habe. Ich benutze die Entwicklungsumgebung Code::Blocks.

Dies sind zwei verschiedene Umsetzungen der Funktion (unterscheiden sich nicht groß), in welcher die Umlaute ersetzt werden sollen:

 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
void html_konverter( char *text, char *neuer_text)   {
    short i, k;
    short zahl;

    for( i=0, k=0; text[i] != '\0'; i++, k++) {
        zahl = (short)text[i];
        printf("\n%d\n", zahl);

        if (zahl == '\x84')    {
            strncat( neuer_text, "&auml;", 6 );
            k += 5;
        }
        else if (zahl == '\x94')   {
            strncat( neuer_text, "&ouml;", 6 );
            k += 5;
        }
        else if (zahl == '\x81')   {
            strncat( neuer_text, "&uuml;", 6 );
            printf("Ja");
            k += 5;
        }
        else if (zahl == '\x8E')   {
            strncat( neuer_text, "&Auml;", 6 );
            k += 5;
        }
        else if (zahl == '\x99')   {
            strncat( neuer_text, "&Ouml;", 6 );
            k += 5;
        }
        else if (zahl == '\x9A')   {
            strncat( neuer_text, "&Uuml;", 6 );
            k += 5;
        }
        else
            neuer_text[k] = text[i];

    }

}
 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
void html_konverter( char *text, char *neuer_text)   {
    short i, k;
    short zahl;

    for( i=0, k=0; text[i] != '\0'; i++, k++) {
        zahl = (short)text[i];

        switch( zahl )  {
            case '\224':
                strncat( neuer_text, "&ouml;\0", 7 );
                k += 5;
                break;
            case '\x99':
                strncat( neuer_text, "&Ouml;\0", 7 );
                k += 5;
                break;
            case '\204':
                strncat( neuer_text, "&auml;\0", 7 );
                k += 5;
                break;
            case '\x8E':
                strncat( neuer_text, "&Auml;\0", 7 );
                k += 5;
                break;
            case '\201':
                strncat( neuer_text, "&uuml;\0", 7 );
                k += 5;
                break;
            case '\232':
                strncat( neuer_text, "&Uuml;\0", 7 );
                k += 5;
                break;
            default:
                neuer_text[k] = text[i];
                neuer_text[k+1] = '\0';
        }
    }
}

Danke schon mal im voraus ☺

Gruß, supeo

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4638

Wohnort: Berlin

@supeo: Das beginnt mit der Frage: Was sind Umlaute? In welcher Kodierung kommen die rein? Ich würde dringend dazu raten die Eingabe irgendwie geartet nach "Unicode" zu konvertieren und damit zu arbeiten. Das geht bei C am "besten" mit Bibliotheken, die das können, aber eigentlich würde ich von C für diese Aufgabe einfach mal abraten.

supeo

(Themenstarter)

Anmeldungsdatum:
25. Februar 2009

Beiträge: 23

Danke für deine schnelle Antwort. Mit Umlauten mein ich 'ä', 'Ä','ö',..., 'ß'. Die HTML-Kodierung soll einfach nur "&auml;" sein. Ich würde das schon ganz gerne in C schreiben. Welche Bibliotheken könnte ich denn verwenden? Gruß

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6436

Wohnort: Hamburg

Lasse ich sie jedoch als Char ausgeben, funktioniert dies nicht.

Das ist ein Problem, welches in C Tutorials meistens vernachlässigt wird und an dem ich auch noch etwas arbeiten muss. Jedenfalls werden unter Linux die Umlaute meist UTF-8 codiert und als Multibyte Strings dargestellt. D.h. das z.B. ein "Ä" durch mehr als ein Byte repräsentiert wird.

Wenn dich englisch nicht stört, kannst du hier etwas mehr Information darüber bekommen (bessere Links finde ich in meiner Zettelsammlung gerade nicht). Wenn du allerdings nur die HTML Kodierungen generieren willst, könnte es einfacher sein, die Dekodierung der UTF-8 Strings selber zu machen, was ich einem Anfänger allerdings nicht empfehlen würde (zu viel Neues auf einmal).

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4638

Wohnort: Berlin

@supeo: Okay, Da habe ich vielleicht etwas ungenau gefragt. Was Umlaute sind weiss ich schon, aber weisst Du was Umlaute für den Rechner sind? Der kennt nämlich keine Umlaute sondern nur Zahlen. Und welche Zahl zum Beispiel für ein 'ä' steht, ist alles andere als eindeuting. Also musst Du wissen welcher Bytewert, oder welche Bytewerte (Mehrzahl!) bei Deiner Eingabe für ein 'ä' stehen, und die dann ersetzen. Das funktioniert dann aber grundsätzlich erst einmal nur für Eingaben, die das 'ä' auch so kodieren, wie Du das erwartest. Falls es ander kodiert ist, dann funktioniert die Ersetzung auch nicht.

Eine ordentliche Lösung nimmt als Argument die Eingabekodierung entgegen und wandelt intern dann erst einmal in eine Kodierung um, die den kompletten Unicode-Bereich abdeckt. Da weiss man dann welche Bytewerte 'ä' & Co haben und kann entsprechend ersetzen. Dann kodiert man wieder zu der angegebenen Kodierung und gibt das Ganze aus. Zum Umkodieren gibt's zum Beispiel die POSIX-Funktion iconv().

supeo

(Themenstarter)

Anmeldungsdatum:
25. Februar 2009

Beiträge: 23

Danke noch einmal für die schnell Antworten ☺

@Dakuan Ich werde mich mal mit dem Link beschäftigen. Mir ist auch schon aufgefallen, dass wenn bspw. ein 'ä' als Zahl ausgeben lasse, '-61' und '-92' ausgegeben wird.

@Marc 'BlackJack' Rintsch Ich habe keine Ahnung wie ich das bewerkstelligen kann. Ich werde morgen mal nach dieser POSIX-Funktion googlen.

Gruß

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4638

Wohnort: Berlin

@supeo: Sich die Werte als vorzeichenbehaftete Bytes ausgeben zu lassen ist vielleicht nicht so günstig. Das dürfte die unüblichste Art sein, so etwas darzustellen. ☺

supeo

(Themenstarter)

Anmeldungsdatum:
25. Februar 2009

Beiträge: 23

Als nicht vorzeichenbehaftete Zahl sieht das ganze dann so aus: '4294967235d' & '4294967228d'. Ich weiß nicht, was ich davon habe. Gibt es die Möglichkeit, mithilfe beider Zahlen das Zeichenausgeben zu lassen, bzw. diese beiden Zahlen mit dem bereits gespeicherten Zeichen zu vergleichen? Die erste Zahl lässt sich damit vergleichen, aber die ist bei allen gleich.

Gruß

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4638

Wohnort: Berlin

Die Bytewerte -62 und -92 (dezimal) sehen nicht vorzeichenbehaftet ganz bestimmt nicht so aus, wie Du das da gezeigt hast. Das sind dezimal 195 und 164.

Natürlich kannst Du diese beiden Werte mit anderen Werten vergleichen und die auch in einem Array suchen.

Wenn das erste Byte so eines Multibyte-Zeichens für Deine Zwecke immer den gleichen Wert hat, dann kannst Du doch danach suchen und nach dem drauffolgenden Wert entscheiden was zu tun ist. Dein Programm wird dann aber nur mit UTF-8 kodierten Texten funktionieren.

Zeigt *neuer_text eigentlich auf einen Speicherbereich, der gross genug ist im Ernstfall ca. sechs mal so viele Bytes aufzunehmen wie strlen(text) ergibt?

strncat() ist für diese Aufgabe ungünstig. Erst einmal würde strcat() ausreichen, weil Du ja weisst wie lang das zweite Argument ist. Und diese beiden Funktionen müssen immer das erste Argument komplett nach dem Nullbyte am Ende durchsuchen, d.h. je länger das wird, umso langsamer die Funktion.

supeo

(Themenstarter)

Anmeldungsdatum:
25. Februar 2009

Beiträge: 23

Ja, stimmt, mein Fehler ich habe die Zahl einfach unsigned ausgeben lassen und die Zahl ist eben größer als ein Byte. Ich habe nämlich, einer Lösung aus dem Internet zufolge, das Zeichen in einer anderen Variable gespeichert.

Also könnte ich auch einfach ( nicht schöne Lösung ), aber daran habe ich gar nicht gedacht, den Quelltext als ISO-8859-1 kodieren.

Der Speicherbereich wird in einer anderen Funktion berechnet und dementsprechend erstellt.

Stimmt, das könnte ich ändern.

Gruß

supeo

(Themenstarter)

Anmeldungsdatum:
25. Februar 2009

Beiträge: 23

Jetzt habe ich aber noch eine Frage. Wie kann man auf die einzelnen Bytes der UTF-8-Kodierung zugreifen in C?

Gruß

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4638

Wohnort: Berlin

@supeo: Ich verstehe die Frage nicht so ganz!? Welchen Datentyp hast Du denn? Für Bytes würde man normalerweise ein char-Array oder einen Zeiger auf char verwenden.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6436

Wohnort: Hamburg

Wie kann man auf die einzelnen Bytes der UTF-8-Kodierung zugreifen in C?

Wie die UTF-8 Codierung aufgebaut ist kannst du hier nachlesen.

Ich denke der richtige Weg wäre die UTF-8 / Multibyte Strings in echte Unicode Zeichen umzuwandeln (z.B. mit mbstowcs()). Es gibt da eine ganze Reihe von Funktionen, die alle mit mb (multibyte) oder wc (wide character) anfangen. Ich bin da leider auch erst am Anfang und tue mich da auch noch schwer eine gute Einführung dazu zu finden.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4638

Wohnort: Berlin

@Dakuan: Das sind Funktionen von C99. Ist mir persönlich zu neumodisch und noch nicht gut genug unterstützt, so dass ich mir da Sorgen um die Portierbarkeit machen würde. Ich denke ich würde mich da eher nach einer portierbaren Bibliothek für das "alte" C umschauen. Ist aber vielleicht eine exotische Einzelmeinung von mir. ☺

Zumindest das was supeo machen möchte, sollte auch auf UTF-8 kodierten Daten gehen.

Lunar

Anmeldungsdatum:
17. März 2006

Beiträge: 5792

Marc 'BlackJack' Rintsch schrieb:

@Dakuan: Das sind Funktionen von C99. Ist mir persönlich zu neumodisch und noch nicht gut genug unterstützt, so dass ich mir da Sorgen um die Portierbarkeit machen würde. Ich denke ich würde mich da eher nach einer portierbaren Bibliothek für das "alte" C umschauen. Ist aber vielleicht eine exotische Einzelmeinung von mir. ☺

Soweit ich weiß, unterstützen der icc, der gcc und der Sun-Compiler C99 relativ vollständig. Nach zehn Jahren sollte man da langsam etwas Verbreitung erwarten dürfen, schließlich ist C++ auch schon angekommen 😉

Antworten |