Čtení z binárního souboru a následný výpis dat – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Čtení z binárního souboru a následný výpis dat – C / C++ – Fórum – Programujte.comČtení z binárního souboru a následný výpis dat – C / C++ – Fórum – Programujte.com

 

avalagne0
Newbie
14. 1. 2013   #1
-
0
-

Ahoj,
nedaří se mi rozumně vypsat data načtená z binárního souboru. Mám binární soubor, který obsahuje informace o dané osobě - jméno, příjmení, titul před jménem, titul za jménem, telefon a mail. První řádek výpisu mi funguje bez problému (osoba má všechny informace vyplněné), další už se nezobrazí korektně a myslím si, že to bude tím, že některé informace vyplněné nemá (nemá titul před jménem).

Zdrojové kódy:
osoba.c:

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

tOsoba *alokujOsobu()
{
	tOsoba *novaOs = NULL;

	novaOs = (tOsoba*) malloc(sizeof(tOsoba));

	return novaOs;
}

void vypisOsobu(tOsoba* os)
{
	printf("Vypis osoby:\n");
	printf("%s %s %s %s\n", os->titulPred, os->jmeno, os->prijmeni, os->titulZa);
	printf("Telefon: %s\n", os->telefon);
	printf("Mail: %s\n\n", os->mail);
}

seznam.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "seznam.h"
#include "osoba.h"

tOsoba **poleUkOsob = NULL;
int velikostPole = 0;

void nacti(char *nazevSouboru)
{
	FILE *soubor = NULL;
	int i;
	tOsoba *novaOs = NULL;

	soubor = fopen(nazevSouboru, "rb");
	fseek(soubor, 0, SEEK_END);
	velikostPole = ftell(soubor) / sizeof(tOsoba);
	fseek(soubor, 0, SEEK_SET);
	poleUkOsob = (tOsoba**) calloc(velikostPole, sizeof(tOsoba*));

	for(i = 0; i < velikostPole; i++)
	{
		novaOs = alokujOsobu();
		fread(novaOs, sizeof(tOsoba), 1, soubor);		
		
		poleUkOsob[i] = novaOs;
	}
	fclose(soubor);
}

void vypis(char *retezec)
{
	int i;

	if(retezec == NULL)
	{
		for(i = 0; i < velikostPole; i++)
		{
			printf("Osoba %d:\n", i + 1);
			vypisOsobu(poleUkOsob[i]);
		}
	}
	else
	{
		for(i = 0; i < velikostPole; i++)
		{
			if(strstr(poleUkOsob[i]->prijmeni, retezec) != NULL)
			{
				vypisOsobu(poleUkOsob[i]);
				break;
			}
		}
		printf("Shoda se zadanym retezcem nenalezena!\n");
	}
}

main.c:

#include <stdlib.h>
#include <stdio.h>
#include "osoba.h"
#include "seznam.h"

int main()
{
	char *nazevSouboru = NULL, prijmeni[20];

	nazevSouboru = "osoby.bin";
	if(nazevSouboru == NULL)
	{
		printf("Soubor nenalezen!\n");
		return 0;
	}
	nacti(nazevSouboru);
	printf("Vypis vsech osob:\n\n");
	vypis(NULL);
	printf("Zadejte prijmeni, ktere chcete hledat: ");
	scanf("%s", prijmeni);
	vypis(prijmeni);

	system("pause");
	return 0;
}

Díky moc za rady, já už nevím, čím by to mohlo být. Podle mě se nesprávně posouvám v tom binární kódu (po jiných blocích paměti než potřebuju)...

EDIT: Přidávám screen problému pro představu...

Nahlásit jako SPAM
IP: 85.13.126.–
vitamin+8
Grafoman
14. 1. 2013   #2
-
0
-

Nebolo by lepsie do suboru ukladat stringy ako velkost + data? Pri nacitani si najprv nacitas velkost, ak bude rovna 0 tak danu cast neobsahuje ak >= 1 tak mozes presne alokovat velkost pre string a potom tam nacitat data.

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. "
avalagne0
Newbie
14. 1. 2013   #3
-
0
-

#2 vitamin
Takže myslíš tak, že bych se pohyboval v tom binárním souboru pomocí fseek, vždycky si uložil ten řetězec a takhle pro vše? Místo fread, kde to neovlivním... Nebo ještě jinak?

Nahlásit jako SPAM
IP: 85.13.126.–
vitamin+8
Grafoman
14. 1. 2013   #4
-
+1
-
Zajímavé

Myslel som nieco taketo:

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

int zapis(FILE* fp, const char* str){
	size_t len = strlen(str);
	if(fwrite(&len, sizeof(size_t), 1, fp) != 1)return 0;
	return (fwrite(str, sizeof(char), len, fp) == len);
}
char* nacitaj(FILE* fp){
	size_t len;
	if(fread(&len, sizeof(len), 1, fp) != 1)return NULL;
	char *str = (char*)malloc(sizeof(char)*(len+1));

	if(len && fread(str, sizeof(char), len, fp) != len){
		free(str);
		return NULL;
	}
	
	str[len] = '\0';
	return str;
}
	
int main(){
	FILE* w = fopen("test.txt", "wb");
	if(!w)return EXIT_FAILURE;
	
        //vynechal som testovanie navratovych hodnot
	zapis(w, "text1");
	zapis(w, "");	//prazdny text
	zapis(w, "text3");
	
	fclose(w);
	
	//-------------------------------
	
	FILE* r = fopen("test.txt", "rb");
	if(!r)return EXIT_FAILURE;
	
	char* a = nacitaj(r);
	char* b = nacitaj(r);
	char* c = nacitaj(r);
	
	fclose(r);
	
	printf("%s, %s, %s", a, b, c);
	
	free(a);
	free(b);
	free(c);


}
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. "
avalagne0
Newbie
14. 1. 2013   #5
-
0
-

#4 vitamin
Souhlasím, takhle to vypadá dobře. Kdysi jsem ale ten prográmek psal a vím, že to nebylo nutný dělat takhle "složitě"... Stačilo znát velikost struktury (ta je konstantní). Nevím, proč mi to nefunguje. Problém je s NULL hodnotama. Zkusím to ještě nějak pořešit (ten můj způsob). Ale díky moc za užitečnou ukázku  

Nahlásit jako SPAM
IP: 85.13.126.–
vitamin+8
Grafoman
14. 1. 2013   #6
-
0
-

Ak obsahuje tOsoba len pointre na retazce, tak ti tvoj sposob fungovat nebude :)

Do suboru vtedy nezapises samotny retazec, ale hodnotu pointra ktora ti je po nacitani uplne nanic.

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. "
avalagne0
Newbie
14. 1. 2013   #7
-
0
-

#6 vitamin

tOsoba obsahuje to co píšeš:

typedef struct osoba
{
	char jmeno[20];
	char prijmeni[20];
	char titulPred[7];
	char titulZa[7];
	char telefon[20];
	char mail[30];
} tOsoba;

Já ale nepotřebuju zapisovat do souboru. Mě stačí z binárního souboru dostat data a ty vypsat na obrazovku. To nic ale nemění na tom, co píšeš... Jedině nahradit ty NULL hodnoty natvrdo prázdným znakem (po přečtení řádku), ale taky nevim, jestli to zafunguje...

Nahlásit jako SPAM
IP: 85.13.126.–
vitamin+8
Grafoman
14. 1. 2013   #8
-
0
-

#7 avalagne
staci na zaciatku inicializovat premenne:

tOsoba o = {"", "", "", "", "", ""};
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. "
avalagne0
Newbie
14. 1. 2013   #9
-
0
-

#8 vitamin
To mě teda nepustí... Píše to: expected an expression (chybí výraz)

Nahlásit jako SPAM
IP: 85.13.126.–
Mr. Bro
~ Anonymní uživatel
7 příspěvků
14. 1. 2013   #10
-
0
-

#9 avalagne
Taky jsem mel ten problem, pomohlo mi zarovnani #pragma pack(push, 1) a za strukturu #pragma pack(pop)

Nahlásit jako SPAM
IP: 83.147.138.–
avalagne0
Newbie
15. 1. 2013   #11
-
0
-

#10 Mr. Bro
Abych řekl pravdu, tak vůbec nevim co to znamená... A asi ani nechápu, kam to mám vložit. Můžeš to prosím nějak blíž popsat? Díky

Nahlásit jako SPAM
IP: 85.13.126.–
Mr. Bro
~ Anonymní uživatel
7 příspěvků
15. 1. 2013   #12
-
0
-

   



#pragma pack(push, 1)

typedef struct osoba
{
char jmeno[20];
char prijmeni[20];
char titulPred[7];
char titulZa[7];
char telefon[20];
char mail[30];
} tOsoba;

#pragma pack(pop)
Nahlásit jako SPAM
IP: 83.147.138.–
avalagne0
Newbie
15. 1. 2013   #13
-
0
-

#12 Mr. Bro
A co by to mělo dělat?    Mě to vypisuje pořád nesmysly...

Nahlásit jako SPAM
IP: 85.13.126.–
Mr. Bro
~ Anonymní uživatel
7 příspěvků
15. 1. 2013   #14
-
0
-

#13 avalagne
No to je zarovnani v pameti.

Zkousel jsem to v editoru a vse O.K., takze mas chybu asi v ukladani

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

Podobná vlákna

Cteni binarniho souboru — založil Azimut

Cteni dat ze souboru — založil honza

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ý