Nefunkční cyklus s funkcí strtok – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Nefunkční cyklus s funkcí strtok – C / C++ – Fórum – Programujte.comNefunkční cyklus s funkcí strtok – C / C++ – Fórum – Programujte.com

 

MucoVerde
~ Anonymní uživatel
13 příspěvků
7. 1. 2013   #1
-
0
-

Ahoj, používám funkci strtok ve while cyklu pro oddělování jednotlivýcj tokenů. Vím, že funkce strtok "vycucává" z původního řetězce její obsah - proto všechny pole překopíruju do jiných (viz kód). Problém mám ale s tím, že "Token" se vypíše pouze jednou... pokud ale zakomentuju určitý řádek v kódu (viz kód), vše proběhne jak má... netušíte, kde je chyba?

char poleA [F_LENGTH];
char vstupniPole [strlen(input)+1];
strcpy(vstupniPole, puvodniPole);
	
char *token;
token = strtok(vstupniPole, "|");
char detekce [strlen(token)+1];
while (token != NULL){

	printf("Token: %s\n", token);
	strcpy(detekce, token);
	if (isupper(detekce[2]) != 0){
		char dalsiPole [strlen(poleA)+1]; 
		strcpy(dalsiPole, poleA);
		char *token2;
		token2 = strtok(dalsiPole, "|"); // pokud toto zakomentuji, vse funguje jak ma
	}
	token = strtok(NULL, "|");
}
Nahlásit jako SPAM
IP: 147.228.209.–
7. 1. 2013   #2
-
0
-

puvodniPole má alokovanou paměť? Kde se naplní poleA? Smyčka je zřejmě nekonečná, hodnota proměnné token se v jejím těle nemění.

hu

Nahlásit jako SPAM
IP: 188.95.60.–
MucoVerde
~ Anonymní uživatel
13 příspěvků
7. 1. 2013   #3
-
0
-

puvodniPole je vstupni parametr a pamět už má alokovanou (funkce je delší, vytáhl jsem jen ten usek, který nefunguje). Předpokládejme, že poleA je už naplněné.. takhle jak to mám napsané, by se mi druhý token samozřejmě nevypsal, protože poleA nic neobsahuje...

Nahlásit jako SPAM
IP: 147.228.209.–
MucoVerde
~ Anonymní uživatel
13 příspěvků
7. 1. 2013   #4
-
0
-

Při výpisu je vidět, že while cyklus proběhne tak jak má JEN když neskočí do podmínky.. ta podmínka ho jakoby breakne...

Nahlásit jako SPAM
IP: 147.228.209.–
vitamin+8
Grafoman
7. 1. 2013   #5
-
0
-
Nerozhodně

#1 MucoVerde


strtok je funkcia ktora modifikuje povodne pole (doplna znak '\0') a ktomu si uchovava adresu posledneho nacitaneho tokenu v globalnej premennej. Ty si vytvoris lokalnu premennu na stacku vo vnutri cyklu a potom inicializujes touto lokalnou premennou strtok(). strtok() si uchova adresu tejto lokalnej premennej, lenze hned za tymto volanim opustas scope a uvolni sa lokalna premenna. Pouzivaj malloc()/calloc() a free().

edit: alebo radsej nepouzivaj strtok().

edit2: tak som si ten kod prezrel lepsie a tytam mas viac problemov. Funkcia strtok nie je stavana na pouzivanie s viacerimi poliami sucasne, na to su funkcie ako strtok_s(win) a strtok_r(linux)

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
KIIV
~ Moderátor
+43
God of flame
7. 1. 2013   #6
-
0
-

a taky pokud bude prvni token nejak vyrazne kratsi nez dalsi tak je tam hned buffer overflow...

Nahlásit jako SPAM
IP: 94.112.35.–
Program vždy dělá to co naprogramujete, ne to co chcete...
7. 1. 2013   #7
-
0
-

Asi už jsem nejen hluchej, ale i slepej. To s tím cyklem odvolávám.

hu

Nahlásit jako SPAM
IP: 188.95.60.–
MucoVerde
~ Anonymní uživatel
13 příspěvků
7. 1. 2013   #8
-
0
-

Upravil jsem zdrojový kód tak, aby bylo přehlednější, jaký mám problém. Po spuštění programu by mi měl vypsat

Token abC

Proslo abC

Token vCd

Token dfF

Proslo dfF

Ovšem vypíše mi pouze

Token abC

Proslo abC

Co se týče strtok_s, tak to by stačilo pouze nahradit za současný strtok, či jak?

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


int main(void){
	char puvodniPole[50];
	puvodniPole[0] = 'a';
	puvodniPole[1] = 'b';
	puvodniPole[2] = 'C';
	puvodniPole[3] = '|';
	puvodniPole[4] = 'v';
	puvodniPole[5] = 'C';
	puvodniPole[6] = 'd';
	puvodniPole[7] = '|';
	puvodniPole[8] = 'd';
	puvodniPole[9] = 'f';
	puvodniPole[10] = 'F';
	puvodniPole[11] = '\0';
	
	char poleA[10];
	poleA[0] = 'd';
	poleA[1] = 'd';
	poleA[2] = '|';
	poleA[3] = 'a';
	poleA[4] = 'a';
	poleA[5] = '|';
	poleA[6] = 'd';
	poleA[7] = '\0';
	char vstupniPole [strlen(puvodniPole)+1];
	strcpy(vstupniPole, puvodniPole);
	
	char *token;
	token = strtok(vstupniPole, "|");
	char detekce [strlen(token)+1];
	while (token != NULL){

		printf("Token: %s\n", token);
		strcpy(detekce, token);
		if (isupper(detekce[2]) != 0){
			
			char dalsiPole [strlen(poleA)+1]; 
			strcpy(dalsiPole, poleA);
			printf("Proslo: %s\n", token);
			char *token2;
			token2 = strtok(dalsiPole, "|"); // pokud toto zakomentuji, vse funguje jak ma
		}
		token = strtok(NULL, "|");
	}
  return 0;
}
Nahlásit jako SPAM
IP: 147.228.209.–
vitamin+8
Grafoman
7. 1. 2013   #9
-
0
-
Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
MucoVerde
~ Anonymní uživatel
13 příspěvků
7. 1. 2013   #10
-
0
-

#9 vitamin
OK. A takhle zapsaný to teda nemůže být? Nemůžu prostě použít víckrát strtok, i když se jedná o dvě jiná pole?

Nahlásit jako SPAM
IP: 147.228.209.–
vitamin+8
Grafoman
7. 1. 2013   #11
-
0
-

#10 MucoVerde
Mozes, ale nebude to robit to co chces :)

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
MucoVerde
~ Anonymní uživatel
13 příspěvků
7. 1. 2013   #12
-
0
-

#11 vitamin
OK, koukám na ten strtok_s, ale moc ho nechápu ... má tři parametry, první je řetězec, ze kterého chci dostat ty tokeny, druhý parametr je oddělovací znak a třetí by mělo být k uložení pozice.. ten třetí moc nechápu.. jak by to vypadalo, kdybych tuhle funkci použil na muj kod?

Nahlásit jako SPAM
IP: 147.228.209.–
vitamin+8
Grafoman
7. 1. 2013   #13
-
0
-

#12 MucoVerde
Ved v tom linku mas aj priklad.

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
MucoVerde
~ Anonymní uživatel
13 příspěvků
10. 1. 2013   #14
-
0
-

#13 vitamin
Pokud použiju to co je v příkladu, tak mi to nejde ani přeložit (collect2.exe: error: ld returned 1 exit status undefined reference strtok_s)

int main(void){
	char puvodniPole[50];
	puvodniPole[0] = 'a';
	puvodniPole[1] = 'b';
	puvodniPole[2] = 'C';
	puvodniPole[3] = '|';
	puvodniPole[4] = 'v';
	puvodniPole[5] = 'C';
	puvodniPole[6] = 'd';
	puvodniPole[7] = '|';
	puvodniPole[8] = 'd';
	puvodniPole[9] = 'f';
	puvodniPole[10] = 'F';
	puvodniPole[11] = '\0';
	
	char poleA[10];
	poleA[0] = 'd';
	poleA[1] = 'd';
	poleA[2] = '|';
	poleA[3] = 'a';
	poleA[4] = 'a';
	poleA[5] = '|';
	poleA[6] = 'd';
	poleA[7] = '\0';
	char vstupniPole [strlen(puvodniPole)+1];
	strcpy(vstupniPole, puvodniPole);
	
	char *token;
	char *dalsiToken;
	token = strtok_s(vstupniPole, "|", &dalsiToken);
	char detekce [strlen(token)+1];
	while (token != NULL){

		printf("Token: %s\n", token);
		strcpy(detekce, token);
		if (isupper(detekce[2]) != 0){
			
			char dalsiPole [strlen(poleA)+1]; 
			strcpy(dalsiPole, poleA);
			printf("Proslo: %s\n", token);
			char *token2;
			//token2 = strtok(dalsiPole, "|"); // pokud toto zakomentuji, vse funguje jak ma
		}
		token = strtok_s(NULL, "|", &dalsiToken);
	}
  return 0;
}
Nahlásit jako SPAM
IP: 147.228.209.–
crazy
~ Moderátor
+10
Grafoman
10. 1. 2013   #15
-
0
-

#14 MucoVerde
použij strtok_r

Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
MucoVerde
~ Anonymní uživatel
13 příspěvků
10. 1. 2013   #16
-
0
-

Změnil jsem to na strtok_r a furt to vyhazuje error...

undefined_reference to strtok_r ... pak něco s bad reloc address 0x20 in section ".eh_frame"

final link failed: Invalid operation

collect2.exe: error: ld returned 1 exit status

Error 1

Nahlásit jako SPAM
IP: 147.228.209.–
10. 1. 2013   #17
-
0
-

U kódu který jsi sem vložil nejsou žádné include hlavičkových souborů. Nechybí ti tam #include "string.h" ?

hu

Nahlásit jako SPAM
IP: 188.95.60.–
MucoVerde
~ Anonymní uživatel
13 příspěvků
10. 1. 2013   #18
-
0
-

To mě napadlo jako první, ale string.h tam právě že mám.

Takhle vypadá celý kód:

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


int main(void){
	char puvodniPole[50];
	puvodniPole[0] = 'a';
	puvodniPole[1] = 'b';
	puvodniPole[2] = 'C';
	puvodniPole[3] = '|';
	puvodniPole[4] = 'v';
	puvodniPole[5] = 'C';
	puvodniPole[6] = 'd';
	puvodniPole[7] = '|';
	puvodniPole[8] = 'd';
	puvodniPole[9] = 'f';
	puvodniPole[10] = 'F';
	puvodniPole[11] = '\0';
	
	char poleA[10];
	poleA[0] = 'd';
	poleA[1] = 'd';
	poleA[2] = '|';
	poleA[3] = 'a';
	poleA[4] = 'a';
	poleA[5] = '|';
	poleA[6] = 'd';
	poleA[7] = '\0';
	char vstupniPole [strlen(puvodniPole)+1];
	strcpy(vstupniPole, puvodniPole);
	
	char *token;
	char *dalsiToken;
	token = strtok_r(vstupniPole, "|", &dalsiToken);
	char detekce [strlen(token)+1];
	while (token != NULL){

		printf("Token: %s\n", token);
		strcpy(detekce, token);
		if (isupper(detekce[2]) != 0){
			
			char dalsiPole [strlen(poleA)+1]; 
			strcpy(dalsiPole, poleA);
			printf("Proslo: %s\n", token);
			char *token2;
			//token2 = strtok(dalsiPole, "|"); // pokud toto zakomentuji, vse funguje jak ma
		}
		token = strtok_r(NULL, "|", &dalsiToken);
	}
  return 0;
}
Nahlásit jako SPAM
IP: 147.228.209.–
crazy
~ Moderátor
+10
Grafoman
10. 1. 2013   #19
-
0
-

#18 MucoVerde
čim to kompiluješ? gcc mi to přeloží v pohodě

Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
MucoVerde
~ Anonymní uživatel
13 příspěvků
10. 1. 2013   #20
-
0
-

Mám to udělaná make, ve kterým mam klasicky gcc abc.c -o abc

ale v cmd, mi to zobrazí jen cc ab.c -o abc ?není to chyba?

Jinak to gcc jsem stáhnul v rámci MinGW

Nahlásit jako SPAM
IP: 147.228.209.–
10. 1. 2013   #21
-
0
-

C++ Builder 2010 nepřeloží, nezkousne char vstupniPole [strlen(puvodniPole)+1];. Nemohu vyzkoušet.
<string.h> vkládáš. Zkus jednoduchý projekt ve kterém bude jen řetězec a na něj použitý strtok_r.:

hu

Nahlásit jako SPAM
IP: 188.95.60.–
MucoVerde
~ Anonymní uživatel
13 příspěvků
10. 1. 2013   #22
-
0
-

Tak jsem to zkusil jen čistě s strtok_r a opět Error

c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: final link
failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
make: *** [matice] Error 1

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


int main(void){
	char puvodniPole[50];
	puvodniPole[0] = 'a';
	puvodniPole[1] = 'b';
	puvodniPole[2] = 'C';
	puvodniPole[3] = '|';
	puvodniPole[4] = 'v';
	puvodniPole[5] = 'C';
	puvodniPole[6] = 'd';
	puvodniPole[7] = '|';
	puvodniPole[8] = 'd';
	puvodniPole[9] = 'f';
	puvodniPole[10] = 'F';
	puvodniPole[11] = '\0';
	
	char poleA[10];
	poleA[0] = 'd';
	poleA[1] = 'd';
	poleA[2] = '|';
	poleA[3] = 'a';
	poleA[4] = 'a';
	poleA[5] = '|';
	poleA[6] = 'd';
	poleA[7] = '\0';
	
	char *token;
	char *dalsiToken;
	token = strtok_r(puvodniPole, "|", &dalsiToken);
	char detekce [strlen(token)+1];
	while (token != NULL){

		printf("Token: %s\n", token);
		token = strtok_r(NULL, "|", &dalsiToken);
	}
	return 0;
}
Nahlásit jako SPAM
IP: 147.228.209.–
vitamin+8
Grafoman
10. 1. 2013   #23
-
0
-

#22 MucoVerde
strtok_r a strtok_s su nestandartne funkcie ktore kompilator nemusi podporovat. MinGW nepodporuje ani jednu z nich.

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
crazy
~ Moderátor
+10
Grafoman
10. 1. 2013   #24
-
0
-
Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
MucoVerde
~ Anonymní uživatel
13 příspěvků
10. 1. 2013   #25
-
0
-

Tak SUPER, použil jsem odkaz od Crazyho a už se to "točí" 

Vysvětlil by mi tu ještě někdo, proč to tak vlastně funguje? V podstatě jsem jen přidal prázdnej char a už to funguje, nechápu moc to kouzlo, díky kterému strtok_r funguje a strtok ne?

Nahlásit jako SPAM
IP: 147.228.209.–
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, 25 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ý