Radek Chalupao programování a počítačích, vývoj software, školení ...
Domů | Články | Ukázky kódu | Tipy a triky | Aktuality | Školení a konzultace | Vývoj software | Freeware | Kontakt

Odstranění diakritiky z textu v C++ na Linuxu  3.1.2019

V minulém příspěvku jsem ukázal jak v C++ s využitím knihovny GLib snadno odstranit z textu diakritiku. Pokud z nějakého důvodu nechceme nebo nemůžeme v aplikaci použít knihovnu GLib (nebo nějaký jiný framework), použijeme v Linuxu přímo funkci iconv (a související). Jejich deklarace jsou v hlavičkovém souboru iconv.h.

Uvedu nejprve komplení kód ukázkové aplikace a pak pár vysvětlujících poznámek

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <iconv.h>
#include <string>

std::string iconv_impl(const char* text, bool zobraz = true)
{
	if (zobraz)
		printf("%s\n", (char*)text);
	iconv_t ictd = iconv_open("ASCII//TRANSLIT", "UTF-8");
	if ((iconv_t)-1 == ictd)
	{
		perror("chyba iconv_open");
		return std::string("");
	}
	size_t delka = strlen(text) * 2;
	char* vstup = (char*)malloc(delka);
	char* vystup = (char*)malloc(delka);
	char* vystup_orig = vystup;
	char* vstup_orig = vstup;
	size_t size_vstup = delka;
	size_t size_vystup = delka;
	strcpy(vstup, text);
	if (iconv(ictd, (char**) &vstup, &size_vstup,
		(char**)&vystup, &size_vystup) == (size_t)-1)
	{
		perror("chyba iconv");
		iconv_close(ictd);
		free(vstup_orig);
		free(vystup_orig);
		return std::string("");
	}
	if (zobraz)
		printf("%s\n", vystup_orig);
	std::string str_vystup = vystup_orig;
	iconv_close(ictd);
	free(vstup_orig);
	free(vystup_orig);
	return str_vystup;
}

int main(int argc, char** argv)
{
	setlocale(LC_ALL, "");
	std::string str =
		iconv_impl("Nějaký český text.€.$.@.ěščřžýáíé.#.ĚŠČŘŽÝÁÍÉ");
	printf("pro kontrolu: %s\n", str.c_str());
	return 0;
}

Proč alokuji dvojnásobek délky vstupního textu?

Jak bude zřejmě při spuštění programu, (jeden) znak pro "euro" je ve výstupu (bez diakritiky) převeden na trojznakový text EUR. Podobně to může být i s jinými znaky (v jiných jazycích), proto tato "bezpečná velikost".

Proč ukládám ukazatele na alokovaná pole do proměnných vstup_orig a vystup_orig, které pak předávám jako parametry funkce free při uvolnění paměti?

Funkci iconv totiž předáváme jako parametry adresy ukazatelů (char**) a tato funkce ty ukazatele použije při procházení textovým polem a mění jejich hodnoty, takže po provedení funkce iconv máme v předaných proměnných jiné adresy než na vstupu. Funkce free samozřejmě vyžaduje adresu počátku bloku který má uvolnit, takže jí musíme předat právě ty předem uložené hodnoty.


Máte připomínku, dotaz nebo komentář k článku a souvisejícími tématy?

Napište a odešlete ji emailem

Copyright © 2019  Radek Chalupa