Výpočet pravděpodobnosti písmen v textu – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Výpočet pravděpodobnosti písmen v textu – C / C++ – Fórum – Programujte.comVýpočet pravděpodobnosti písmen v textu – C / C++ – Fórum – Programujte.com

 

Filip
~ Anonymní uživatel
121 příspěvků
21. 5. 2015   #1
-
0
-

Potřebuji udělat program v C, který rozpozná jazyk textu na základě četnosti výskytu písmen v jednotlivých textech. Budu mít několik souborů v různých jazycích a s těmito texty budu porovnávat "výchozí" text uložený v souboru. Bohužel moc nevím, jak na to. Nejdřív, co mi bylo doporučeno:

1) Vytvořit si několik textových souborů, kde bude vždy text v určitém jazyku

2) Vytvořit si textový soubor, ve kterém bude porovnávaný text 

3) Měl bych přečíst jednotlivé soubory po jednotlivých znacích, to realizuji takto:

FILE *Soubor = fopen("porovnavany.txt", "r");
	if (Soubor != NULL)
	{
		while ((znak = fgetc(Soubor)) != EOF)
		{
			if (znak == '\n')
				pp = true;
			else
			{
				if (pp)
				{
					printf("%3d: ", poc++);
					pp = false;
				}
			}
			printf("%c", znak);
		}
		fclose(Soubor);
	}

Takto to udělám se všemi soubory (přečtu po písmenech). Akorát nevím, kam nebo jak pak zaznamenám počet těch jednotlivých písmen? Počet písmen v souboru bych pak měl vydělit celkovým početem znaků v souboru.

Na zaznamenání toho výsledku bych si měl vytvořit pole typu float o 256 znacích, kde bych měl každému znaku přiřadit pravděpodobnost výskytu a následně to porovnat.

Momentálně ale netuším, jak spočítám ty jednotlivé znaky a jak je dostanu do toho pole typu float.

Nahlásit jako SPAM
IP: 89.102.3.–
Quimby
~ Anonymní uživatel
10 příspěvků
21. 5. 2015   #2
-
0
-

Co třeba udělat pole, kdy index je daný znak a hodnota udává počet výskytů v daném textu?

něco jako :

int array[256];
int temp << jeden znak;
array[temp]+=1;

Samozřejmě tohle není funkční kod, ale jen pro vysvětlení principu. Je potřeba ošetřit vstup, aby se všechny znaky vešli do pole.

Nahlásit jako SPAM
IP: 81.200.55.–
PiranhaGreg0
Stálý člen
21. 5. 2015   #3
-
0
-

Takovej nástřel 

#include <stdio.h>
#include <stdlib.h>

#define range 128

int * getFrequency(const char * filename) {
	int * frequency, c;
	
	FILE * file = fopen(filename, "r");
	if (!file) return NULL;

	frequency = calloc(sizeof(int), range);

	while((c = fgetc(file)) != EOF)
		frequency[c]++;

	fclose(file);
	return frequency;
}

int main(int argc, char const * argv[]) {
	int i, * sample, ** languages;

	if (argc < 4) {
		fprintf(stderr, "usage: %s <sample> <languages...>\n", argv[0]);
		return 1;
	}

	sample = getFrequency(argv[1]);
	languages = malloc((argc - 2) * sizeof(int *));

	for (i = 2; i < argc; i++)
		languages[i - 2] = getFrequency(argv[i]);


	/* tohle je na tobě ;-) */


	for (i = 0; i < argc - 2; i++)
		free(languages[i - 2]);

	free(languages);
	free(sample);
	return 0;
}

To porovnání už si hezky dopiš  . Taky upozorňuji, že to zvládne pouze text bez diakritiky (pouze ASCII tabulku). Pro všechny znaky by to bylo mnohem komplikovanější a Cčko bych na to nedoporučoval.

Jinak jsem to nezkoušel pustit, tak za správnost neručím  .

Nahlásit jako SPAM
IP: 2a00:1028:9942:b69e:de2:9...–
Filip
~ Anonymní uživatel
121 příspěvků
22. 5. 2015   #4
-
0
-

#3 PiranhaGreg
Tak tohle mi vůbec nepomohlo, protože prostě netuším, co ten kód má dělat.

Ale i tak díky.

Nahlásit jako SPAM
IP: 77.48.59.–
PiranhaGreg0
Stálý člen
22. 5. 2015   #5
-
0
-

Celý jsem to okomentoval. Už je ti to jasnější? 

#include <stdio.h>
#include <stdlib.h>

/* předpokládáme pouze základní ASCII znaky. Proto 128 */
#define range 128

/* 
	funkce vrátí pole intů, kde má každé písmeno uvedeno,
	kolikrát se objevilo v načteném textu.

	př. pro text "arabela"

	frequency['a'] vrátí 3
	frequency['b'] vrátí 1
	frequency['c'] vrátí 0
	...
*/
int * getFrequency(const char * filename) {
	int * frequency, c;
	
	/* otevřeme soubor s textem */
	FILE * file = fopen(filename, "r");
	if (!file) return NULL;

	/* alokujeme pole se samými nulami */
	frequency = calloc(sizeof(int), range);

	/* postupně procházíme text a inkrementujeme výskyt nalezených znaků */
	while((c = fgetc(file)) != EOF)
		frequency[c]++;

	/* zavření souboru a vrácení pole výskytů */
	fclose(file);
	return frequency;
}

int main(int argc, char const * argv[]) {
	/* sample - text k analýze
	   languages - pole s analýzou ostatních jazyků */
	int i, * sample, ** languages;

	/* kontrola vstupu */
	if (argc < 4) {
		fprintf(stderr, "usage: %s <sample> <languages...>\n", argv[0]);
		return 1;
	}

	/* načteme tabulku s četností znaků */
	sample = getFrequency(argv[1]);

	/* načteme tabulky s četností znaků pro všechny jazyky */
	languages = malloc((argc - 2) * sizeof(int *));

	for (i = 2; i < argc; i++)
		languages[i - 2] = getFrequency(argv[i]);

	/* 
		tohle je na tobě...
		
		malý příklad: mějme soubory

		sample.txt   s textem "tohle se musi uhodnout"
		czech.txt    s textem "ceska veta"
		enhlish.txt  s textem "some english sentence"

		po spuštění programu s parametry

		./program sample.txt english.txt czech.txt

		budou obsahy polí následující

		sample['o'] == 3
		sample['s'] == 2
		languages[0]['e'] == 4
		languages[0]['a'] == 0
		languages[1]['k'] == 2
		languages[1]['s'] == 1
	*/

	/* uvolnění alokovaných prostředků */
	for (i = 0; i < argc - 2; i++)
		free(languages[i - 2]);

	free(languages);
	free(sample);
	return 0;
}
Nahlásit jako SPAM
IP: 2a00:1028:9942:b69e:e821:...–
Filip
~ Anonymní uživatel
121 příspěvků
23. 5. 2015   #6
-
0
-

#5 PiranhaGreg
Tak ještě několik dotazů.

1)  

/* alokujeme pole se samými nulami */
	frequency = calloc(sizeof(int), range);

	/* načteme tabulky s četností znaků pro všechny jazyky */
	languages = malloc((argc - 2) * sizeof(int *));

Mi píše, že nejde zkonvertovat z void do int.

2) Pokud to budu chtít udělat pro všechny znaky ASCII tabulky, tak bude stačit pedělat ten range na 256? Protože pak to moc nebude fungovat. Jak pak rozpoznám angličtinu od češtiny, když tam budu text bez diakritiky?

3) Všechyn ostatní, známé jazyky budu mít v tom languages? Jak to z těch jednotlivých souborů dostanu do toho pole?

Já se omlouvám, ale programování prostě nerozumím, ale musím to splnit :-/

Nahlásit jako SPAM
IP: 77.48.59.–
PiranhaGreg0
Stálý člen
23. 5. 2015   #7
-
0
-

#6 Filip
1)  Používáš kompilátor pro C++

frequency = (int *)calloc(sizeof(int), range);
languages = (int **)malloc((argc - 2) * sizeof(int *));

2) Na 256 znaků to rozšířit můžeš, ale už si pak zahráváš s kódováním. Pokud pak načteš např. text v češtině, který používá kódování Windows-1250 a ruštině, která používá Windows-1251, tak se ti bude např. č shodovat s иůщ, atd.

Výhoda prvních 128 znaků je, že jsou ve všech možných kódováních stejný. Takže bych ti doporučil vystačit si pouze s tímhle. Pro frekvenční analýzu, kterou chceš dělat nemá diakritika nějaký zásadní vliv.

Pokud chceš řešit i cizí znaky, tak buď přesedlej na vyšší jazyk, který si plně rozumí s Unicode (C#, Java, JS, ...) a nebo budeš muset využít knihovny jako ICU nebo Boost.Locale. I tak to ale nebude příjemný řešit...

3) Já nevím kolik ti říkají argumenty programu... Jestli používáš VS, koukni třeba sem. Nechce se mi ti to vysvětlovat. K jednotlivým jazykům pak přistupuješ přes languages[i], kde i je index jazyku respektující pořadí tak jak přišel v parametrech... můžeš si ten vstup klidně pořešit nějak jinak  .

Nahlásit jako SPAM
IP: 2a00:1028:9942:b69e:ad79:...–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 26 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý