Zum Inhalt springen

Jonglieren mit wchar, mbchar, char und verschiedenen charsets


Shamharoth

Empfohlene Beiträge

hallo zusammen.

ich mal wieder und mein Problem bezüglich verschiedenen charsets.

vorinformation:

ich arbeite C++ unter linux

mein problem:

ich möchte einen eingehenden string von z.b. iso-8859-1 in utf-8 konvertieren (geht über iconv). den multibyte-string, den ich bekomme, soll nun in einen widechar gespeichert werden (sollte mit mbstowcs gehen).

leider geht dies nicht (ich wollt einfach den satz mit einfügen X) ).

wenn der string ein umlaut enthält bekomme ich bei mbstowcs() ein -1 (Fehler) zurück.

Mein testlauf:

Eingangsstring: abö (hab ich über strlin in char-array gespeichert)

Konvertierter String (ISO-8859-2 -> UTF-8): abö (hier sieht man ja wurde in ein mb-string konvertiert)

wenn ich jetzt z.b. die länge der kette ermitteln will

int mbslen(char *strptr)

{

   int i = 0;

   int charlen;

   mblen(NULL, 0);


   while (charlen = mblen(strptr, MB_LEN_MAX)) {

      if (charlen < 0) {

         return -1;

      }

      strptr += charlen;

      i++;

   }

   return i;

}

bekomme ich n -1 an der 3. stelle.

die minifunktion wird ja sozusagen benötigt, da ich ja in mbstowcs(dest,src,len) ja zum schluss die länge des zielstrings angeben muss (sollte ja eigentlich genau lang wie mein übergabestring sein).

irgend etwas mach ich falsch, aber was ???

wäre super wenn ihr mir helfen könntet (bin schon seit 3 tagen am rätseln)

Link zu diesem Kommentar
Auf anderen Seiten teilen

weil der string unabhängig von der eingangskonvertierung bearbeitet werden soll.

jedoch wenn die verschiedenen Charsetts sofort richtig bei der konv. in wide char geändert werden brauch ich wirklich keins mehr .... muss ich mal überprüfen. ... frag is dann nur noch wie es z.b. mit ländern wie tschechen mit ihren 20 zusatzzeichen is ..... bzw. mit den deutschen umlauten .....

wie gesagt .... muss probieren ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

hmmm missd .....

also ich hab jetz das über UTF32 versuchd ...


*Input = toWCHAR(*Input, (const char*)Charset);

wcscpy(tmpwchr,(wchar_t*)(*Input));

wsInput = tmpwchr;

std::wcout << L"X" << wsInput << L"X";

leider bekomm ich bei Sonderzeichen noch ne fehlerhafte ausgaben ....

wäre mein Input "abc" stände "XabcX" auf dem Bildschirm.

steht jedoch "abcä" im Input, steht "Xabc??" am Monitor.

bei "abcü" steht sogar "Xabc? 1/4 X".

zur info bezüglich meines codes: toWCHAR() bekmmt input übergeben un aktuellen charset. die funktion ruft wiederum eine firmeninterne funktion auf, welche die daten verarbeitet und iconv ausführt. darum hat die firmeninterne funktion (wird iconvert genant) statt size_t a char * als rückgabewert (darum auch vorhin das mit rückgabewert ^^).

rest müsste verständlich sein ... wsInput is vom typ wstring (habs damit auch probierd darum steht es mit drinnen) und tmpwchr is vom typ wchar_t.

edit:

ach un nebenbei danke für deine mühe :) scho klasse dass du hier im forum zeit verbringsd um andren zu helfen ^^ (hab vorhin beim thema suchen ein thread entdeckt, bei dem ein andrer sehr schroff wurde, obwohl du sehr sachlich geblieben bisd ;) )

Bearbeitet von Shamharoth
Link zu diesem Kommentar
Auf anderen Seiten teilen

ich hab mal das wcout probiert und bei mir kommt

"abc?" raus.

jedoch wenn ich das "abcö" in ein char * über "cin >> " mach, wird das char richtig ausgegeben gleich nach dem einlesen (also steht "abcö" am bildschirm). das gleiche wenn ich es hardcoded ausgebe ... (speicherung wird ja in n char* gemachd). vielleichd is ja der string dadurch schon UTF-8? ..... kann ich mir jedoch nichd vorstellen. bezüglich iconv bin ich zufüllig auf das beispiel gekommen:

iconv Examples - The GNU C Library <- hier wird aus ner datei mit x-beliebiges charset sofort in wchar_t umgewandelt ....

Link zu diesem Kommentar
Auf anderen Seiten teilen

ich hab mal das wcout probiert und bei mir kommt

"abc?" raus.

Deine Konsole kann also auch nicht so einfach Wide-Character-Strings ausgeben. Die Konsole ist damit nicht geeignet für die Erfolgsprüfung. Wie gesagt, wenn ich den von iconv umgewandelten Text in eine Datei schreibe, ist der in Ordnung.

Was soll denn hinterher in deinem Programm mit den Wide-Character-Strings passieren?

jedoch wenn ich das "abcö" in ein char * über "cin >> " mach, wird das char richtig ausgegeben gleich nach dem einlesen (also steht "abcö" am bildschirm).
Logisch, du liest in UTF-8 ein und gibst in UTF-8 wieder aus.

das gleiche wenn ich es hardcoded ausgebe ... (speicherung wird ja in n char* gemachd). vielleichd is ja der string dadurch schon UTF-8? .....
Na sicher. Dein Quellcodeeditor benutzt mit sehr hoher Wahrscheinlichkeit auch UTF-8. Du kannst dir ja mal sizeof("ä") ausgeben lassen, sollte 3 sein (eine UTF-8-Sequenz aus zwei Bytes und ein Nullterminator).
Link zu diesem Kommentar
Auf anderen Seiten teilen

mein programm soll verschiedene typen prüfen (z.b. isd input numerisch oder alphanumerisch, das einfachste mal als beispiel). damit dann charset unabhängig ist und auch z.b. osteuropäische zeichensätze benutzt werden kann, sollte intern in UTF8 (bzw. eigentlich is es ja UTF32) laufen.

k also bedeutet es, dass intern wennman "abcö" schreibt für "ö" n multibyte automatisch bekommt.

ich hab jetzt n kleines prüfprogramm gemachd zum testen

int main(void){

	char cstr[40] = "abcö";

	char *pcstr = cstr;

	wchar_t *pwcstr = NULL;

	FILE *ffile;


	std::cin >> cstr;

	std::cout << sizeof(cstr) << " / " << strlen(cstr) << " / " << mblen(cstr,500) << std::endl;

	pcstr = toWCHAR(pcstr,"ISO-8859-1");

	std::cout << pcstr << std::endl;

	pwcstr = (wchar_t *)pcstr;

	std::wcout << pwcstr << wcslen(pwcstr) << std::endl;


	ffile = fopen("/.../test.txt","w");

	fwrite(pwcstr,4,wcslen(pwcstr),ffile);

	fclose(ffile);


	return 0;

}


char * toWCHAR(char * sString, const char * from)

{

	const char * to = "WCHAR_T";

	return iconvert(sString, from, to);

}


char * fromWCHAR(char * sString, const char * to)

{	const char * from = "WCHAR_T";

	return iconvert(sString, from, to);

}

hierbei bekomme ich bei "abcö" aufn bildschirm:

40 / 5 / 1

a

abcö5

und in die datei:

a b c d � �

sollte nicht dann wcslen 4 zurückgeben? weil bei "ööö" bekomme ich "6" zurück

edit:

ok wenn ich mein from - charset auf UTF8 ändere kommt schon mal richtige länge raus ...

abc�4
Bearbeitet von Shamharoth
Link zu diesem Kommentar
Auf anderen Seiten teilen

misd ich kanns nicht mehr editieren :/ darum n doppelpost von mir:

ich hab etwas in ner manpage gefunden:

f the format string contains non-ASCII wide characters, the program will only work correctly if the LC_CTYPE category of the current locale at run time is the same as the LC_CTYPE category of the current locale at compile time. This is because the wchar_t representation is platform and locale dependent. (The GNU libc represents wide characters using their Unicode (ISO-10646) code point, but other platforms don't do this. Also, the use of C99 universal character names of the form \unnnn does not solve this problem.) Therefore, in internationalized programs, the format string should consist of ASCII wide characters only, or should be constructed at run time in an internationalized way (e.g. using gettext() or iconv(), followed by mbstowcs()).

so könnte evtl ein problem geben bei der rückkonvertierung geben (hab auch n fehler, da wennich dann fromWCHAR() mach, hüpfd er in ne endlosschleife. wenn ich dann den widechar von wchar_t in a multibyte char änder, fliegt er auch beim sonderzeichen raus.

hier is aber das problem: es ist ja ne bibliothek und soll ja von verschiedenen programmen (egal des locals) genutzt werden. jetz die große frage: ist es möglich den local zu belassen? weil ansonsten müsste ja in derbibliothek das geändert werden, wodurch der rest des programmes beeinträchtigt werden könnte. die ganze problemstellung bereitet mir kopfzerbrechen ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

problem hierbei wäre dann aber, dass ich so a gschmarri rausbekomm:

�abc� / 5

(bezüglich der zeile mit "std:.wcout << pwcstr....")

der haut dann irgend ein 4Byte-Zeichen einfach vorne an.

bezüglich speicherung hab ichjetzt statt fwrite fputws benutzt jetz bekomm ich auch a anständige utf8-codierte datei (laut geany). jedoch wurde das "ö" mit einem "?" (NICHT zeichen ->� ! nur ein normales "?") ausgetauscht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

der haut dann irgend ein 4Byte-Zeichen einfach vorne an.
Das ist ein BOM, das ist da durchaus angebracht. Wenn du es nicht willst, lass es weg.

bezüglich speicherung hab ichjetzt statt fwrite fputws benutzt jetz bekomm ich auch a anständige utf8-codierte datei (laut geany).
Moment, was ist jetzt dein Ziel? Wide Character oder UTF-8? Beides gleichzeitig ist Quatsch.
Link zu diesem Kommentar
Auf anderen Seiten teilen

das was gespeichert wird is ja UTF-8 (kenne keine datei, welche in WCHAR_T gespeichert ist (da es ja datentyp ist)

das mit speichern ist ja eh nur zur prüfung gedacht. eigentlich wollt ich ja mit dem convertierten string ja weiterarbeiten. jedoch könnt ich einfach nach konvertierung wirklich das BOM-zeichen abschneiden :)

Bezüglich des speicherleaks ist es dann angebrachd pcstr = pcstr+1 zu machen? ansonsten konvertier ich es sofort in wstring un entfern es dann darüber ...

Link zu diesem Kommentar
Auf anderen Seiten teilen

das was gespeichert wird is ja UTF-8 (kenne keine datei, welche in WCHAR_T gespeichert ist (da es ja datentyp ist)
Den Satz verstehe ich überhaupt nicht. UTF-8 ist keine Wide-Character-Codierung. Wenn du Wide Character hast, hast du nicht UTF-8. Das schließt sich gegenseitig aus.

Bezüglich des speicherleaks ist es dann angebrachd pcstr = pcstr+1 zu machen?
Ich vermute, dass irgendwo in deiner iconvert-Funktion irgendwie Speicher reserviert wird. Den musst du natürlich wieder freigeben.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Den Satz verstehe ich überhaupt nicht. UTF-8 ist keine Wide-Character-Codierung. Wenn du Wide Character hast, hast du nicht UTF-8. Das schließt sich gegenseitig aus.

naja es is ja so: ich habe jetzt wchar_t string. den hab ich ja mit dem iconv befüllt, indem ich die source-zeichenkette in UTF-32 umcodiert habe.

nun hab ich über fputwc in eine datei gespeichert. DIESE datei ist laut geany UTF-8 codiert (meint zumindest der statusbar). das war meine aussage ^^ (zudem hab ja gesagt, es gibt ja keine konvertierung von Textdateien in "WCHAR")

Keine Ahnung. Ich vermute, dass irgendwo in deiner iconvert-Funktion irgendwie Speicher reserviert wird. Den musst du natürlich wieder freigeben.

K bezüglich des muss ich wohl a lösung finden.

Das problem (wenn man das BOM-zeichen aussen vor lässt) was ich noch hab is dann noch die rückconvertierung in z.B. UTF-8 ... die funktion zur konvertierung bleibt bei mir in ner loop schleife hängen, welche erst rausgeht, wenn die länge des Inputs (3 parameter von der iconv_funktion. laut manpage "size_t *inbytesleft").

kann es sein, dass hier wegen der UTF-32 Codierung die richtige länge nicht erkennt wird bzw. durch die codierung auf 32bit für ein zeichen dies zu problemen führt?

hab irgendwo (webseite) gesehen, dass durch die erweiterung hinter jedem zeichen dann ein "\0" stehen würd. ...

Bearbeitet von Shamharoth
Link zu diesem Kommentar
Auf anderen Seiten teilen

nun hab ich über fputwc in eine datei gespeichert.
Warum tust du das?

fputwc nimmt in Abhängigkeit der aktuellen Locale wieder eine Umcodierung in Multibyte vor.

(zudem hab ja gesagt, es gibt ja keine konvertierung von Textdateien in "WCHAR")
WCHAR ist auch keine Codierung. Aber du kannst Textdateien natürlich in eine Wide-Character-Codierung wie UTF-32 konvertieren.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Warum tust du das?

fputwc nimmt in Abhängigkeit der aktuellen Locale wieder eine Umcodierung in Multibyte vor..

ok ... mist :/ ... welche methode würdest du empfehlen? (wfwrite (oder ähnlich) gibts ja nur bei windows) un bei wfprint(ffile,L"%s", pwcstr); hat er bei mir nur den ersten byte geschrieben.)

blöd is nur momentan ich kann ja auch wcstombs() nicht benutzen, da er bei den umlauten raushaut und -1 zurückgibt (ich glaub das hat ich schon am anfang des threads mit erwähnt).

Link zu diesem Kommentar
Auf anderen Seiten teilen

so ich hab mal 123abc in utf32 convertiert und als char ausgeben lassen.

Dabei hab ich alle '\0' als [] angezeigt.

ergebnis:

��[][]2[][][]2[][][]3[][][]a[][][]b[][][]c[][][][][][][]

(BOM ist noch dabei)

bei abcü kommt

��[][]a[][][]b[][][]c[][][]�[][][][][][][]

jetz ist die frage: wenn ich alle 0 in viererblöcken lösch bis auf den aller letzten, ist dann noch gegeben, dass es richtig convertiert (dann is es ja genaugenommen a MB char array.

Aber ob dies eine konforme "beschneidung" ist bezweifle ich irgendwie.

Irgendwie MUSS ja UTF-32 nach "unten" konvertierbar sein.

edit:

ich hab mir mal schnell folgende funktion zusammengedacht:

void * UTF32toUTF8(char *sString)

{

	DWORD pos = 0;

	DWORD newpos = 0;

	while(1)

	{

		DWORD temppos = 0;

		if(sString[pos+temppos] == 0 && sString[pos+temppos+1] == 0 && sString[pos+temppos+2] == 0 && sString[pos+temppos+3] == 0)

		{

			sString[pos+temppos] = 0;

			break;

		}

		for(;temppos < 4; temppos++)

		{

			if(sString[pos+temppos] == 0)

				break;

			sString[newpos] = sString[pos+temppos];

			newpos++;

		}

		pos+=4;

	}

}

Bearbeitet von Shamharoth
Link zu diesem Kommentar
Auf anderen Seiten teilen

ergebnis:

Sieht doch gut aus.

jetz ist die frage: wenn ich alle 0 in viererblöcken lösch bis auf den aller letzten, ist dann noch gegeben, dass es richtig convertiert (dann is es ja genaugenommen a MB char array.
Nein. Wie willst du denn "ab" von "慢" (Unicode-Zeichen 0x6162) unterscheiden?

UTF-32 ist keine Multibyte-Codierung mit "Zusatznullen". Die Tatsache, dass jedes Zeichen durch genau 32 Bits codiert wird, ist eine für die Decodierung wichtige Zusatzinformation. Wenn du die Nullbytes entfernst, kann man nicht mehr rekonstruieren, wo im Datenstrom ein neues Zeichen anfängt. Multibyte-Codierungen benutzen zusätzliche Bits für genau diese Information.

Irgendwie MUSS ja UTF-32 nach "unten" konvertierbar sein.
Ist es ja auch. Aber so einfach ist es dann doch nicht.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Sieht doch gut aus.

Nein. Wie willst du denn "ab" von "慢" (Unicode-Zeichen 0x6162) unterscheiden?

haha:) ich hab dein post gelesen und wollte mit deinem post als zitat antworten, aber in zwischenzeit hast etwas editiert. beim öffnen des editors hab ich mir gedacht "huch wo kommt plötzlich der satz her?" .. ach ja es lebe die zeit ^^ ... zum quote:

hm verständlich ....

UTF-32 ist keine Multibyte-Codierung mit "Zusatznullen". Die Tatsache, dass jedes Zeichen durch genau 32 Bits codiert wird, ist eine für die Decodierung wichtige Zusatzinformation. Wenn du die Nullbytes entfernst, kann man nicht mehr rekonstruieren, wo im Datenstrom ein neues Zeichen anfängt. Multibyte-Codierungen benutzen zusätzliche Bits für genau diese Information.

...

Ist es ja auch. Aber so einfach ist es dann doch nicht.

k das bedeutet ich müssd mir a funktion suchen die das machd. ... für alphanumerische zeichen is es nich schlimm einfach die "0"-Bytes zu cutten ... jedoch will ich ja doch noch die anderen zeichen beibehalten ;)

warum gibt es keine standartfunktion die das machen kann? warum kann es iconv nicht? blödes iconv! *schachtel mit "iconv"-aufschrift tret*

falls ich diesbezüglich a funktion gefunden hab, meld ich mich (es seidenn es kennt jemand die funktion schon.

Link zu diesem Kommentar
Auf anderen Seiten teilen

hab momentan ne gaaaaaaaaanz blöde idee (weshalb ich jetzt ma fragen müssd)

... alle MB-chars sind ja so codiert, dass diese (wenn man char in unsigned int umwandelt) >128 sind ... je nach anzahl der dazugehörigen Zeichen kann man auch sagen wieviele elemente zum MB-zeichen gehören.

dann kann ich mit glück so machen, dass ich für den bereich, der den inhalt ändert, gar nicht in UTF32 umwandle und nur zur prüfung ohne änderung des eingabetextes das mach. .... somit hab ich kein problem mit der rückformatierung. ....

etwas problematischer wird dann hald, dass ich z.b. MB-zeichen weglöschen muss .... sollte jedoch eifnacher sein als UTF32 in UTF8 zu konvertieren ;D

.... muss nochmal überlegen ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...