Čtení lineárního pole (dynamická struktura) ze souboru – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Čtení lineárního pole (dynamická struktura)  ze souboru – C / C++ – Fórum – Programujte.comČtení lineárního pole (dynamická struktura) ze souboru – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
25. 4. 2015   #1
-
0
-

Ahoj, mám menší problém s tímto kódem:

void ReadFromFile(TDatabase *database)
{
	FILE *Database;
	Database = fopen(FILENAME, "a+"); //čtení Database.
	TDatabase *Actually = (TDatabase*)malloc(sizeof(TDatabase));
	char *p, *token;
	int inc = 0;

	char *Line = (char*)malloc(sizeof(char));

	while(NULL != fgets(Line, sizeof(Line), Database))
	{
		 if ((p = strrchr(Line, '\n')) != NULL) *p = '�';
                token = strtok(Line, ';');
                while (token != NULL) {
					
					switch(inc)
					{
						case 0: Actually->ID = atoi(token); break;
						case 1: Actually->SPZ = token; break;
						case 2: Actually->Name = token; break;
						case 3: Actually->Surname = token; break;
						case 4: Actually->INplace = token; break;
						case 5: Actually->INdate = token; break;
						case 6: Actually->INtime = token; break;
						case 7: Actually->OUTplace = token; break;
						case 8: Actually->OUTdate = token; break;
						case 9: Actually->OUTtime = token; break;
						case 10: Actually->distance = atoi(token); break;
						case 11: Actually->fuelconsumption = atoi(token); break;
						default : printf("Error: Chyba v databazi!"); break;
					}
					inc++;
					
                    token = strtok(NULL, ';');
					AddEnd(&database, Actually->ID, Actually->SPZ, Actually->Name, Actually->Surname, Actually->INplace, Actually->INdate, Actually->INtime,
						Actually->OUTplace, Actually->OUTdate, Actually->OUTtime, Actually->distance, Actually->fuelconsumption);

                }
				inc = 0;
				Line = NULL;
				Line = (char*)malloc(sizeof(char));
	}
}

	/*//rewind(Database);
	bool Vysledek;
	do
	{
		TDatabase *Actually = (TDatabase*)malloc(sizeof(TDatabase));
		Vysledek = fscanf(Database, "%d;%s;%s;%s;%s;%s;%s;%s;%s;%s;%d;%.2f\n", &Actually->ID, Actually->SPZ, Actually->Name, Actually->Surname, Actually->INplace, 
			Actually->INdate, Actually->INtime, Actually->OUTplace, Actually->OUTdate, Actually->OUTtime, &Actually->distance, &Actually->fuelconsumption) == 1;
		AddEnd(&database,Actually->ID, Actually->SPZ, Actually->Name, Actually->Surname, Actually->INplace, 
			Actually->INdate, Actually->INtime, Actually->OUTplace, Actually->OUTdate, Actually->OUTtime, Actually->distance, Actually->fuelconsumption);
		Actually = NULL;
	} while(Vysledek);
	fclose(Database);
	}
	*/

hlásí mi to tyto chyby u všech položek ve switch a token = strtok(xxxx);


Error    22    error C2440: '=' : cannot convert from 'char *' to 'char [10]'    
'strtok' : cannot convert parameter 2 from 'char' to 'const char *'   

Lineární pole:

struct TDatabase {
	int ID;
	char SPZ[10];
	char Name[20];
	char Surname[20];
	char INplace[20];
	char INdate[10];
	char INtime[5];
	char OUTplace[20];
	char OUTdate[10];
	char OUTtime[5];
	int distance;
	float fuelconsumption;
	TDatabase *Next;
};

Děkuji předem za pomoc s vyřešením tohoto problému.

edit.: nebo mám předělat položky lineárního pole na dynamické?

Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
25. 4. 2015   #2
-
0
-

Musis retezec zkopirovat, ne se snazit prepsat pointer (coz nastesti u pole nejde)

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
25. 4. 2015   #3
-
0
-

Děkuji za odpověď. Počet errorů se snížil na 2.

strcpy(token, strtok(Line, ';'));
strcpy(token, strtok(NULL, ';'));

error C2664: 'strtok' : cannot convert parameter 2 from 'char' to 'const char *'   

Neví někdo co s tím? Děkuji

Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
25. 4. 2015   #4
-
0
-

Pomoci apostrofu se definuje jeden znak - napriklad 'A'. Uvozovky uz jsou retezec "retezec" typu const char * a obsahuje i ukoncovaci znak '\0', podle ktereho se poznava konec retezce.

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
25. 4. 2015   #5
-
0
-

Aktuálně mi to chyby při buildu nehází, ale při spuštění mi VS hází tuto chybu:

Připojen obrázek.

void ReadFromFile(TDatabase *database)
{
	FILE *Database;
	Database = fopen(FILENAME, "a+"); //čtení Database.
	TDatabase *Actually = (TDatabase*)malloc(sizeof(TDatabase));
	char *p, *token;
	int inc = 0;

	char *Line = (char*)malloc(sizeof(char));

	while(NULL != fgets(Line, sizeof(Line), Database))
	{
		 if ((p = strrchr(Line, '\n')) != NULL) 
			{
				*p = '\0';
				token = (char*)malloc(sizeof(char));
				strcpy(token, strtok(Line, ";"));
                while (token != NULL) 
				{	
					switch(inc)
					{
						case 0: Actually->ID = atoi(token); break;
						case 1: strcpy(Actually->SPZ, token); break;
						case 2: strcpy(Actually->Name, token); break;
						case 3: strcpy(Actually->Surname, token); break;
						case 4: strcpy(Actually->INplace, token); break;
						case 5: strcpy(Actually->INdate, token); break;
						case 6: strcpy(Actually->INtime, token); break;
						case 7: strcpy(Actually->OUTplace, token); break;
						case 8: strcpy(Actually->OUTdate, token); break;
						case 9: strcpy(Actually->OUTtime, token); break;
						case 10: Actually->distance = atoi(token); break;
						case 11: Actually->fuelconsumption = atoi(token); break;
						default : printf("Error: Chyba v databazi!"); break;
					}
					inc++;
					
                    strcpy(token, strtok(NULL, ";"));
					AddEnd(&database, Actually->ID, Actually->SPZ, Actually->Name, Actually->Surname, Actually->INplace, Actually->INdate, Actually->INtime,
						Actually->OUTplace, Actually->OUTdate, Actually->OUTtime, Actually->distance, Actually->fuelconsumption);
				}
                }
				inc = 0;
				Line = NULL;
				Line = (char*)malloc(sizeof(char));
	}
}
Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
25. 4. 2015   #6
-
0
-

Nekde nacitas z NULL pointru

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
25. 4. 2015   #7
-
0
-

Už vím kde je problém 

while(NULL != fgets(Line, sizeof(Line), Database))

problém je s délkou řádku (sizeof(Line) - nejspíš se to takto nedá ani zapsat). Jak zjistit předem délku řádku v souboru?

Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
25. 4. 2015   #8
-
0
-

Relativne tezko.. musis bud projet soubor a spocitat si to, nacist buffer a pokud je to delsi, tak ho zvetsit a nacist zbytek (samozrejme drzet velikost bufferu, sizeof(pointer) da jen velikost pointeru, ne celeho dynamicky alokovaneho pole), nebo stavova masina, nacitat po znacich a ukladat na spravne misto bez nacitani celych radku... Jeste peknych par moznosti bude.

Jinak Line = NULL - tak nejak prijdes o tu alokovanou pamet. A jelikoz retezce kopirujes, tak je uplne zbytecne Line furt alokovat a pak ztracet. Proste si odhadni maximalni delku radku dejme tomu 1024, a pokud by byl delsi, tak muzes i vyhlasit chybu.

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
25. 4. 2015   #9
-
0
-

maximální délka by neměla přesáhnout 400 znaků ale preventivně jsem nastavil 1024.

 po proběhnutí 11 cyklu (inc = 11) se token != NULL a inc se zvýší na 12, poté to vypíše ten můj error (printf), a pote vyhodí VS chybu (Unhandled exception at 0x6b27f693 in xsmola07_173743_projekt.exe: 0xC0000005: Access violation reading location 0x00000000.) na řádku -> což znamená že ukazatel ukazuje na NULL.

strcpy(token, strtok(NULL, ";"));

ale nevím proč nefunguje tato podmínka 

 while (token != NULL) 

ZK:

void ReadFromFile(TDatabase *database)
{
	FILE *Database;
	Database = fopen(FILENAME, "a+"); //čtení Database.
	TDatabase *Actually = (TDatabase*)malloc(sizeof(TDatabase));
	
	char *token = (char*)malloc(sizeof(char));
	char *Line = (char*)malloc(sizeof(char));
	int inc = 0;
	

	while(NULL != fgets(Line, 1024, Database))
	{
		 if (strrchr(Line, '\n') != NULL) 
			{
				strcpy(token, strtok(Line, ";"));
                while (token != NULL) 
				{	
					switch(inc)
					{
						case 0: Actually->ID = atoi(token); break;
						case 1: strcpy(Actually->SPZ, token); break;
						case 2: strcpy(Actually->Name, token); break;
						case 3: strcpy(Actually->Surname, token); break;
						case 4: strcpy(Actually->INplace, token); break;
						case 5: strcpy(Actually->INdate, token); break;
						case 6: strcpy(Actually->INtime, token); break;
						case 7: strcpy(Actually->OUTplace, token); break;
						case 8: strcpy(Actually->OUTdate, token); break;
						case 9: strcpy(Actually->OUTtime, token); break;
						case 10: Actually->distance = atoi(token); break;
						case 11: Actually->fuelconsumption = atoi(token); break;
						default : printf("Error: Chyba v databazi!"); break;
					}
					inc++;
					strcpy(token, strtok(NULL, ";"));
                    
				}
                }
				AddEnd(&database, Actually->ID, Actually->SPZ, Actually->Name, Actually->Surname, Actually->INplace, Actually->INdate, Actually->INtime,
					Actually->OUTplace, Actually->OUTdate, Actually->OUTtime, Actually->distance, Actually->fuelconsumption);
				inc = 0;
	}
}
Nahlásit jako SPAM
IP: 88.146.158.–
q
~ Anonymní uživatel
219 příspěvků
26. 4. 2015   #10
-
0
-

Alokuješ místo jen pro jeden znak

char *token = (char*)malloc(sizeof(char) * nejakypocet);
char *Line = (char*)malloc(sizeof(char) * nejakypocet);
Nahlásit jako SPAM
IP: 213.211.51.–
26. 4. 2015   #11
-
0
-

Děkuji, 

zkusil jsem to, ale samotná alokace nestačila.

char *token = (char*)malloc(sizeof(char)*11);
char *Line = (char*)malloc(sizeof(char)*1024);

Musel jsem ještě do programu dopsat tuto podmínku:

if(inc <= 11)
   strcpy(token, strtok(NULL, ";"));
else						
   break;  

z důvodu toho, že tato podmínka je pořád splněná a program se zacyklí a VS vyhodí chybu. 

while (token != NULL) 

sice mi to čte ze souboru, ale je tam problém. Do indexu 1 mi to vrátí ten samý jako je v posledním indexu. Ale když krokuji program, tak se do každého indexu nahraje každý řádek, tzn že do indexu 1 se nahraje 1 řádek, ale když se ukončí cyklus, tak se zkopíruje poslední řádek seznamu do prvního. Nevíte někdo co s tím? Děkuji

edit.: vlákno není vyřešené, jen jsem klikl vedle, a nevím jak to vrátit zpět.

Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
26. 4. 2015   #12
-
0
-

A proc to vubec kopirujes do tokenu? Abys to pak jeste jednou zkopiroval do struktury?

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
26. 4. 2015   #13
-
0
-

Mě to jinak nefungovalo, hazelo mi to samé chyby. Jak to udělat, abych to nekopíroval do tokenu?

Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
26. 4. 2015   #14
-
0
-

   

//v cyklu:
char * token = strtok(Line, ";");
while (token != NULL) {
  ....

  token = strtok(NULL, ";");
}


Kazdopadne a+ neni jen otevreni pro cteni, ale i pro zapis za konec.

V kodu neuvolnujes alokovanou pamet. A ze ji alokujes az zbytecne moc.

Nezaviras soubor.

Vypada, ze to ani nekompilujes C kompilatorem, proc tedy nepouzivas vymozenosti C++?

Pokud je databaze prazdna, tak se pointer urcite nedostane ven. Ale tezko rict, jak je to okolo.

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
26. 4. 2015   #15
-
0
-

#14 KIIV

Tak jsem to upravil, a dělá to samé -> pořád se přepisuje první položka jako poslední. C++ nepoužívám, jelikož jsem se ho neučil, a toto potřebuji stejně udělat v C. Zavírání souboru jsem tam měl, ale bylo v poznámce pod kódem - opraveno.Kompiluji to normálně ve VS 2008. Samozřejmě je kód ukládán v souboru *.cpp . V databázi zatím mám 8 řádků -> 8 = 1. Zkoušel jsem smazat první řádek  (v programu), ale nejde to - ostatní řádky lze smazat (když smažu 8 řádek, tak 1 = 7 řádku). 

Nahlásit jako SPAM
IP: 88.146.158.–
KIIV
~ Moderátor
+43
God of flame
27. 4. 2015   #16
-
0
-

Mozna hod komplet soubor nekam na pastebin.dqd.cz nebo pastebin.com... bude rychlejsi, kdyz si to zkompiluju, nez jen odhadovat co vse je spatne

Mimochodem v C to kvuli tem strukturam nezkompilujes. Maji trosku striktnejsi zpusob zapisu v cistym C.

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
27. 4. 2015   #17
-
0
-
Nahlásit jako SPAM
IP: 88.146.158.–
Řešení
KIIV
~ Moderátor
+43
God of flame
27. 4. 2015   #18
-
0
-
Vyřešeno Nejlepší odpověď

Na prvni pohled tam nesedi:

Actually = *database;

Mozna by bylo lepsi mit Actually jako statickou promennou, ne jako pointer, protoze to stejne nikam nedavas. Vsude se kopiruje a tak, takze se nic nestane.

Nahlásit jako SPAM
IP: 94.113.93.–
Program vždy dělá to co naprogramujete, ne to co chcete...
8. 5. 2015   #19
-
0
-

#18 KIIV
Po zapoznámkování Actually = *database začal program správně fungovat. Díky

Nahlásit jako SPAM
IP: 147.229.220.–
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, 116 hostů

Podobná vlákna

Python:cteni souboru do pole — založil kaja09

Dynamická Struktura — založil Petr

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ý