Databaze v cecku, problem se souborem Vyřešeno

Místo pro dotazy a rady ohledně programovacích jazyků (C++, C#, PHP, ASP, Javascript, VBS..) a tvorby webových stránek

Moderátor: Mods_senior

Mr_piruletka
nováček
Příspěvky: 5
Registrován: únor 12
Pohlaví: Muž
Stav:
Offline

Databaze v cecku, problem se souborem  Vyřešeno

Příspěvekod Mr_piruletka » 07 úno 2012 15:57

kdyz dam vypsat soubor, tak vypise jen prvni udaj, na danem radku jsem problem popsal konkretneji, dekuji za pomoc

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

typedef struct {
char jmeno[20];
char prijmeni[20];
int plat;
}ZAMESTNANEC;


void pridat(void);
void vypsat(void);

int main()
{
int v,konec,a;

for(a=0;a!=5;){
printf("VYBER MOZNOST\n");
printf("Pridat zamestnance......1\nVypsat zamestnance......3\nKONEC...................4\n");
scanf("%d",&v);
switch(v){
case 1: pridat();
break;
case 2:
break;
case 3: vypsat();
break;
case 4: a=5;
break;

default: printf("neplatny prikaz\n");
}
}

printf("konec\n");
system("pause");
return 0;
}//konec main




void pridat(void)
{
ZAMESTNANEC lide[20];
int i,N;

printf("Kolik chces vytvorit zamestnancu?");
scanf("%d",&N);
for (i=0;i<N;i++){
printf("\n%d. zamestnanec\n",(i+1));
printf("Zadej jmeno: ");
scanf("%s",&lide[i].jmeno);
printf("Zadej prijmeni: ");
scanf("%s",&lide[i].prijmeni);
printf("Zadej plat: ");
scanf("%d",&lide[i].plat);

//ULOŽENÍ
int j;
FILE *soubor;

if((soubor = fopen("pokus", "wb")) == NULL)
{
printf("Soubor nelze otevrit.\n");
exit(1);
}

for(j=0; j<N; j++)
if(fwrite(&lide[j], sizeof(ZAMESTNANEC), 1, soubor) != 1)
{
printf("Chyba pri zapisu.\n");
exit(1);
}
fclose(soubor);
}
}


void vypsat(void)
{
ZAMESTNANEC lide[20];
int i,N,j, pocet;
FILE *soubor;

if((soubor = fopen("pokus", "rb")) == NULL)
{
printf("Soubor nelze otevrit.\n");
exit(1);
}
i=0; // TADY JE PROBLEM, AT ZADAM JAKEKOLI I, VZDY VYPISE JENOM PRVNI ZAZNAM, POTREBOVAL BYCH, ABY kdyz i=0, vypise prvni osobu, kdyz i=1; vypise druhou pridanou osobu, atd...
// vim ze jdu na to urcite spatne, ale nevim jak jinak to udelat, jestli je problem treba uz v zapisu nebo pri vypisu
fread(&lide[i],sizeof(ZAMESTNANEC),1,soubor); //nacitani ze souboru do databaze
{
printf("%s %s %d Kc\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
}
fclose(soubor);



}

Reklama
Uživatelský avatar
CZechBoY
Master Level 9.5
Master Level 9.5
Příspěvky: 8813
Registrován: srpen 08
Bydliště: Brno
Pohlaví: Muž
Stav:
Offline
Kontakt:

Re: Databaze v cecku, problem se souborem

Příspěvekod CZechBoY » 07 úno 2012 20:12

načti celej soubor někam a pak zjisti co z něj vůvec vytahuješ..
PHP, Nette, MySQL, C#, TypeScript, Python
IntelliJ Idea, Docker, Opera browser, Linux Mint
iPhone XS
Raspberry PI 3 (KODI, Raspbian)
XBox One S, PS 4, nVidia GeForce NOW

Uživatelský avatar
domitea
Tvůrce článků
Level 4.5
Level 4.5
Příspěvky: 1971
Registrován: červen 09
Bydliště: Královehradecký kraj
Pohlaví: Muž
Stav:
Offline
Kontakt:

Re: Databaze v cecku, problem se souborem

Příspěvekod domitea » 07 úno 2012 20:34

Asi jses ještě neučil cyklus for :smile:, ale tady bych použil while :wink:

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7397
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod faraon » 07 úno 2012 20:37

Měl bych k tomu tvému programu pár poznámek, nevím v jakém prostředí ho tvoříš, ale podívej se jestli nejde zapnout zobrazování všech warningů při kompilaci. A dobře je pročítej ;-)
Já jsem dostal tuhle hromadu výstrah, která je dost nepřehledná:

Mr_piruletka.c: In function ‘main’:
Mr_piruletka.c:19: warning: unused variable ‘konec’
Mr_piruletka.c:42:2: warning: C++ style comments are not allowed in ISO C90
Mr_piruletka.c:42:2: warning: (this will be reported only once per input file)
Mr_piruletka.c: In function ‘pridat’:
Mr_piruletka.c:57: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[19u]’
Mr_piruletka.c:59: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[19u]’
Mr_piruletka.c:64: warning: ISO C90 forbids mixed declarations and code
Mr_piruletka.c: In function ‘vypsat’:
Mr_piruletka.c:87: warning: unused variable ‘pocet’
Mr_piruletka.c:87: warning: unused variable ‘j’
Mr_piruletka.c:87: warning: unused variable ‘N’


Takže začneme tím nejjednodušším a jinak neškodným, a to jsou komentáře. Ve standardním Céčku se uvozují znaky /* a */, teprve norma C99 dovoluje použití celořádkových // komentářů z C++, ale ze slušnosti a úcty k patriarchům je vhodné přemoci lenost a používat ty tradiční. A navíc ty klávesy jsou na numerické klávesnici hned vedle sebe, takže je možné ten dvojznak napsat ještě rychleji než dvě lomítka za sebou.

Vzhledem k tomu že v Céčku je možné udělat prakticky cokoliv (jen nemůžeš tušit co se vlastně stane), tak dvě velké chyby jsou označeny jen jako varování, protože sice nedělají nic nepovoleného, ale podle překladače pravděpodobně chceš udělat něco jiného než jsi napsal:

Mr_piruletka.c:57: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[19u]’
Mr_piruletka.c:59: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[19u]’


Vztahuje se to k těmhle řádkům ve funkci pridat():

scanf("%s",&lide[i].jmeno);
...
scanf("%s",&lide[i].prijmeni);


Pozor na řetězce, protože to je ve skutečnosti pole znaků, a název pole je sám o sobě ukazatel, takže nemůžeš funkci scanf() předávat ukazatel na něj. Tedy ve skutečnosti v Céčku můžeš, ale v tomhle případě to určitě neudělá to co jsi očekával. Takže to má vypadat jen takhle:

scanf("%s",lide[i].jmeno);
...
scanf("%s",lide[i].prijmeni);


Tím si uložíš načtená jména skutečně na adresy v paměti kam patří.
Pak se nám tam vyloupne další varování:

Mr_piruletka.c:64: warning: ISO C90 forbids mixed declarations and code

Tohle je zlořád z "moderních" jazyků jako je Java a C#, plácnout si deklaraci proměnné tam kde jí zrovna hodlám použít. V Céčku patří na začátek funkce, do společného bloku se všemi ostatními deklaracemi, a věř mi že tam se bude mnohem lépe hledat, až budeš za pár měsíců nebo let v tom programu dělat změny. Takže si je sesypeme pěkně dohromady:

ZAMESTNANEC lide[20];
int i,N;
int j;
FILE *soubor;


Teď se nám sbírka warningů pěkně zkrátila:

Mr_piruletka.c: In function ‘main’:
Mr_piruletka.c:19: warning: unused variable ‘konec’
Mr_piruletka.c: In function ‘vypsat’:
Mr_piruletka.c:87: warning: unused variable ‘pocet’
Mr_piruletka.c:87: warning: unused variable ‘j’
Mr_piruletka.c:87: warning: unused variable ‘N’


Nepoužité proměnné budeme ignorovat, předpokládám že je chceš použít při dalším vývoji programu, takže žádné další chyby ani nepřístojnosti z pohledu překladače už v programu nejsou.

A teď tedy může proběhnout první spuštění a pokus o vytvoření dat, což sice proběhlo bez záseku, ale s chybovým hlášením:

sh: pause: command not found

Tohle je pěkná prasárna, volat cizí program jen kvůli tomu, aby se ti hned neuzavřelo okno! Víš co se při tom stane? Funkcí system() spustíš příkazový interpret, ve tvém případě CMD, a jako parametr mu předáš příkaz pause. Trvá to strašně dlouho a zabere asi tak stotisíckrát víc paměti než ten tvůj prográmek :evil:
A navíc, když se o něco takového pokusíš u mě, na Linuxu, samozřejmě žádný program ani příkaz pause nenajdeš, takže místo pozastavení programu jen vyskočí chybové hlášení a ukončí se okamžitě. Tohle je dobré na jedinou věc, k vytvoření totálně nepřenositelného programu, který bude fungovat jen na jedné verzi jednoho operačního systému... Navíc jazyk C byl vytvořený právě proto aby byly programy snadno přenositelné na jakýkoliv počítač s jakýmkoliv systémem. Takže nejjednodušší způsob bude nechat si tam načíst z konzole ukončený řádek, tedy čekat na stisk klávesy Enter:

getchar();
getchar();


Tím prvním načteš \n které ti zůstalo v bufferu po odeslání volby 4, ten druhý čeká na další Enter.

A teď se konečně dostáváme k té tvé chybě. Nevím odkud jsi to opsal, ale podle složených závorek kolem printf() za tím fread() bych řekl, že měl být součástí nějaké podmínky nebo cyklu. A protože ty potřebuješ opakovat čtení a výpis do té doby, dokud je co načítat, mělo se (zřejmě) jednat o cyklus while(). Letmé nakouknutí do nápovědy řekne, že funkce fread() vrací počet úspěšně načtených položek, takže na konci souboru, kde nemá co načíst, vrátí nulu. Takže uděláme tohle:

Kód: Vybrat vše

     while (fread(&lide[i],sizeof(ZAMESTNANEC),1,soubor))          /*//nacitani ze souboru do databaze */
           {
           printf("%s %s %d Kc\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
           }   


A v tuhle chvíli program začal dělat přesně to co má! Bylo by ještě dobré ten počet načtených položek uložit do proměnné a testovat jestli odpovídá požadovanému, tím se ošetří možnost poškozeného souboru.

Ještě poznámku na závěr. Pokud program řeší chybu při otevírání souboru tím že spadne, nezaslouží si nic jiného než přepsání užitečnějšími daty. Slušná funkce místo sebevraždy vypíše chybové hlášení a vrátí řízení tam, odkud ho dostala, v tomhle případě do funkce main(), aby program mohl pokračovat v jiné činnosti! Takže to otevírání souboru pro čtení bych provedl spíš takhle:

Kód: Vybrat vše

     if ((soubor = fopen("pokus", "rb")))
        {
        i=0;
        while (fread(&lide[i],sizeof(ZAMESTNANEC),1,soubor))
              {
              printf("%s %s %d Kc\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
              }   
        fclose(soubor);           
        }
     else
        {
        printf("Soubor s daty nelze nacist!\n");
        }


A jeden detail, jediný přenositelný formát dat je čistý text, pokud si tu svojí databázi uložíš na x86 procesoru do binárního souboru a zkusíš jí poté načíst třeba na ARMu, tak se budeš moc divit. Ne všechny procesory mají stejné pořadí bytů ve slově, takže tebou uložená čísla budou mít po načtení na jiné platformě úplně jinou hodnotu! Pokud je mezitím neproženeš nějakým konverzním programem, který bys musel také napsat.
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

Mr_piruletka
nováček
Příspěvky: 5
Registrován: únor 12
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod Mr_piruletka » 07 úno 2012 21:12

faraon:
v prvni rade ti moc dekuju za vsechny Tve rady a cas
delam to v dev-c++ , warningy mi nezobrazuje ; (jeste mam v komu keil uvision 3 ktery jsem pouzival kdyz jsem psal v asembleru)
system("pause"); mi prislo takove vznesene, ale od ted uz tu knihovnu stdlib kvuli tomuto nebudu pridavat a pouziju vzdy getchar();
u scanf mi to funguje bez problemu i s &
ty slozene zavorky mam z foru kterym jsem to chtel nejdriv vypsat, ale nefungovalo to a zapomnel jsem je odstranit
mohl bys mi prosimte napsat kod, ktery by vypsal konkretne treba JEN druheho zamestnance? myslim ze by mi to celkove pomohlo pochopit tuto problematiku
Naposledy upravil(a) Mr_piruletka dne 07 úno 2012 21:33, celkem upraveno 1 x.

Uživatelský avatar
CZechBoY
Master Level 9.5
Master Level 9.5
Příspěvky: 8813
Registrován: srpen 08
Bydliště: Brno
Pohlaví: Muž
Stav:
Offline
Kontakt:

Re: Databaze v cecku, problem se souborem

Příspěvekod CZechBoY » 07 úno 2012 21:33

eh?
za svým příspěvkem si stojím a žádnej spam nepíšu
ze souboru čteš prvních 20B (nebo co se uvádí za ten parametr)
tak nevim proč narážíš..
PHP, Nette, MySQL, C#, TypeScript, Python
IntelliJ Idea, Docker, Opera browser, Linux Mint
iPhone XS
Raspberry PI 3 (KODI, Raspbian)
XBox One S, PS 4, nVidia GeForce NOW

Mr_piruletka
nováček
Příspěvky: 5
Registrován: únor 12
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod Mr_piruletka » 07 úno 2012 21:36

jsem si ted uvedomil ze si to asi myslis dobre tak jsem to smazal, nicmene pozde az po tom co sis to precetl

--- Doplnění předchozího příspěvku (07 Úno 2012 22:19) ---

jo a a faraone, kdybych to ukladal klasicky jako text, tak slo by potom s temi daty pracovat krome vypisu?

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7397
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod faraon » 08 úno 2012 20:01

Pomocí for() by to samozřejmě šlo vypsat také, ale musel buďto bys vědět kolik těch zaměstnanců máš, nebo hlídat konec souboru. A nebo obojí, jak jsem to provedl já (viz níže), takže si můžeš nechat vypsat jen určitý počet karet, a smyčka zároveň testuje jestli ještě nějaká další existuje.

Jen druhého zaměstnance si můžeš buďto takhle najít pomocí smyčky, nebo pomocí fseek() skočit přímo na jeho záznam (a samozřejmě ohlídat jestli vůbec existuje a něco se načetlo). To je výhoda binárních souborů, v textových by se to tak snadno provést nedalo, tam bys musel vždy provést rewind() na začátek souboru a načítat všechna data znovu, až by ses dostal k tomu správnému.

Takže jsem si ten tvůj program trochu přeformátoval aby se mi lépe četl a přidal jsem dvě nové funkce pro ukázku toho co jsem právě popsal:

Kód: Vybrat vše

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



typedef struct {
               char jmeno[20];
               char prijmeni[20];
               int plat;
               } ZAMESTNANEC;



void pridat(void);
void vypsat(void);
void smycka(void);
void poradi(void);



int main()
    {
    int v,konec=0,a;

    do {
       printf("VYBER MOZNOST\n"
              "Pridat zamestnance ...... 1\n"
              "Vypsat zamestnance ...... 3\n"
              "Vypsat smyckou .......... 5\n"
              "Vypsat konkretniho ...... 6\n"
              "KONEC ................... 0\n");
       scanf("%d",&v);
       switch (v)
              {
              case 1:
                   pridat();
                   break;
              case 2:
                   break;
              case 3:
                   vypsat();
                   break;
              case 5:
                   smycka();
                   break;
              case 6:
                   poradi();
                   break;
              case 0:
                   ++konec;
                   break;
              default:
                   printf("neplatny prikaz\n");
                  }
       } while (!konec);

    printf("konec\n");
    /*system("pause");   */
    getchar();
    getchar();
    return 0;
    }/*//konec main*/



void pridat(void)
     {
     ZAMESTNANEC lide[20];
     int i,N;
     int j;
     FILE *soubor;

     printf("Kolik chces vytvorit zamestnancu?");
     scanf("%d",&N);
     for (i=0;i<N;i++)
         {
         printf("\n%d. zamestnanec\n",(i+1));
         printf("Zadej jmeno: ");
         scanf("%s",lide[i].jmeno);
         printf("Zadej prijmeni: ");
         scanf("%s",lide[i].prijmeni);
         printf("Zadej plat: ");
         scanf("%d",&lide[i].plat);

        /*//ULOŽENÍ*/
        if ((soubor = fopen("pokus", "wb")) == NULL)
           {
           printf("Soubor nelze otevrit.\n");
           exit(1);
           }

        for (j=0; j<N; j++)
            if (fwrite(&lide[j], sizeof(ZAMESTNANEC), 1, soubor) != 1)
               {
               printf("Chyba pri zapisu.\n");
               exit(1);
               }
        fclose(soubor);
        }
     }



void vypsat(void)
     {
     ZAMESTNANEC lide[20];
     int i,N,j, pocet;
     FILE *soubor;

     if ((soubor = fopen("pokus", "rb")))
        {
        i=0;
        while (fread(&lide[i],sizeof(ZAMESTNANEC),1,soubor))
              {
              printf("%s %s %d Kc\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
              }
        fclose(soubor);
        }
     else
        {
        printf("Soubor s daty nelze nacist!\n");
        }
     }



void smycka(void)
     {
     ZAMESTNANEC lide;
     int i,pocet;
     FILE *soubor;
     
     if ((soubor = fopen("pokus", "rb")))
        {
        printf("Kolik karet mam zobrazit? ");
        scanf("%d",&pocet);
        for (i=0;i<pocet;++i)
            {
            if (!fread(&lide,sizeof(ZAMESTNANEC),1,soubor))
               break;
            printf("%d: %s %s %d Kc\n",i,lide.jmeno,lide.prijmeni,lide.plat);
            }
        fclose(soubor);
        }
     else
        {
        printf("Soubor s daty nelze nacist!\n");
        }
     }



void poradi(void)
     {
     ZAMESTNANEC lide;
     int i;
     FILE *soubor;

     if ((soubor = fopen("pokus", "rb")))
        {
        printf("Zadej poradove cislo: (0, 1, 2...) ");
        scanf("%d",&i);
        fseek(soubor,(long)i*sizeof(lide),SEEK_SET);
        if (!fread(&lide,sizeof(ZAMESTNANEC),1,soubor))
           return;
        printf("%s %s %d Kc\n",lide.jmeno,lide.prijmeni,lide.plat);
        fclose(soubor);
        }
     else
        {
        printf("Soubor s daty nelze nacist!\n");
        }
     }


Data uložená v binárním souboru můžeš zpracovávat právě takhle pomocí seekování, požadovanou kartu načíst ze souboru, upravit, a zase uložit zpátky. Má to výhodu že nepotřebuješ prakticky žádnou paměť, vždy jen pro jednoho zaměstnance. Nevýhoda je pomalejší činnost, hlavně při čtení, ukládání urychluje cache.
Textový soubor takhle zpracovávat nemůžeš, z něj bys musel všechna data načíst do paměti (nebo pomocného souboru), a po zpracování je zase uložit do textového souboru. Samotná práce programu je mnohem rychlejší, ale zase zdržuje načítání dat na začátku a jejich ukládání na konci programu.
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

Mr_piruletka
nováček
Příspěvky: 5
Registrován: únor 12
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod Mr_piruletka » 09 úno 2012 15:33

co v fseek dela ten SEEK_SET? podle toho tveho vzoru jsem to chtel takhle pouzit i pro editaci, ale dela mi to furt nejake blbosti. a je jedno jestli dam fseek(soubor,(long)i*sizeof(lide),SEEK_SET); nebo fseek(soubor,(long)i*sizeof(ZAMESTNANEC),SEEK_SET);?

kdybych to ukladal v tom .txt tak bych se o toto vlastne vubec nestaral a na zacatku bych celou databazi nekam nacetl, pak s ni pracoval a ulozil? slo by ale cely ten soubor nacist do pole tak, abych s tim polem mohl pracovat jako jeste pred ulozenim? ze bych to nacetl do nejakeho pole a to pole by bylo naprosto stejne jako kdybych to pole prave vytvoril?

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7397
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod faraon » 09 úno 2012 18:47

Linuxáci jsou (nejen) v tomhle ve výhodě, těm stačí napsat do příkazového řádku man fseek a hned se dozvědí vše potřebné, ostatní holt musí zalistovat v příručkách a/nebo hledat na netu...
Hlavička funkce fseek() vypadá takhle:
int fseek(FILE *stream, long offset, int whence);

Návratová hodnota je int, pokud se operace podařila vrací 0, pokud ne vrací -1.
S čím se má hýbat určuje *stream.
O kolik se má posunout říká offset.
Odkud se má posouvat je whence.

Ta poslední položka může mít tři různé hodnoty:
SEEK_SET je od počátku souboru, tady má v offset smysl jen kladné číslo,
SEEK_CUR je od aktuální pozice, hodnota offset může být kladná nebo záporná,
SEEK_END je od konce souboru, offset samozřejmě jen záporným číslem.
Jsou to ve skutečnosti makra, která se při kompilaci rozbalí do čísel 0, 1 a 2, ale lepší je psát jejich názvy než konkrétní hodnoty, je tak na první pohled vidět co se má provést a mnohem snáz se v programu hledají slova, než nějaké čísílko. Hlavně při opravování chyb, což je ta nejběžnější a nejčastější činnost programátora :twisted:

Tu databázi můžeš samozřejmě celou načíst do paměti i když jí máš uloženou binárně, a stejně tak jí zase vcelku binárně uložit. A mezitím s ní můžeš provádět libovolné psí kusy.

Takže jsem v programu provedl pár úprav.
Pole lide[20] jsem udělal jako globální, aby s ním mohly pracovat všechny funkce bez předávání, k němu patří také globální proměnná pocet_karet, asi uhodneš k čemu tam je ;-)
Přejmenoval jsem funkci pridat() na nova(), protože ve skutečnosti nic nepřidává, ale vytváří kompletně novou databázi. V Menu je ještě volné číslo 2, takže k němu si můžeš zkusit vytvořit novou funkci pridat(), která bude pouze přidávat novou kartu na konec již existující databáze, nezapomeň zvýšit pocet_karet. A před přidáním otestuj jestli je menší než 20, aby v poli vůbec ještě bylo kam přidávat. Céčko ti to klidně a ochotně provede (v něm se nic automaticky nehlídá, to si musí programátor obstarat sám, tam kde to je potřeba), takže si přepíšeš data která leží za polem, a budou se dít velmi nepříjemné věci! :lol:
Do funkce vypsat() jsem přidal zvýšení počítadla, takže ta teď současně s vypisováním souboru na obrazovku také načítá binární data do pole, na správnou pozici odpovídající indexu i. A samozřejmě je nutné nakonec to počítadlo uložit do pocet_karet, aby ostatní funkce věděly kolik položek v poli je. Tady je její změněná část:

Kód: Vybrat vše

...
     if ((soubor = fopen("pokus", "rb")))
        {
        i=0;
        while (fread(&lide[i],sizeof(ZAMESTNANEC),1,soubor))
              {
              printf("%s %s %d Kc\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
              ++i;
              }
        fclose(soubor);
        }
     else
        {
        printf("Soubor s daty nelze nacist!\n");
        }
     pocet_karet=i;
...

Ten maximální počet položek je lepší zadat jako konstantu: #define MAXPOCET 20 a v programu vždy použít jí, protože při úpravách pak stačí změnit jen jedno číslo na začátku zdrojového kódu a při kompilaci se automaticky změní veškeré její výskyty, než hledat kde všude je v programu napsaná. Zaručeně tak na něco zapomeneš, nebo změníš i jiné číslo, které bude mít náhodou stejnou hodnotu... Říká se že přímo ve zdrojovém kódu se smí z čísel vyskytovat jen nula a jednička, a ta ještě jen v nejnutnějším případě :bomb:

Rozšířil jsem Menu, takže takhle vypadá aktuální funkce main() i s prototypy funkcí a těmi globálními proměnnými, umístěnými hned před ní:

Kód: Vybrat vše

void nova(void);
void vypsat(void);
void smycka(void);
void poradi(void);
void save(void);
void load(void);
void view(void);



int pocet_karet=0;
ZAMESTNANEC lide[20];



int main()
    {
    int v,konec=0/*,a*/;

    do {
       printf("VYBER MOZNOST\n"
              "Vytvorit databazi ....... 1\n"
              "Vypsat zamestnance ...... 3\n"
              "Vypsat smyckou .......... 5\n"
              "Vypsat konkretniho ...... 6\n"
              "Ulozit textove .......... 7\n"
              "Nacist textove .......... 8\n"
              "Zobrazit pole ........... 9\n"
              "KONEC ................... 0\n");
       scanf("%d",&v);
       switch (v)
              {
              case 1:
                   nova();
                   break;
              case 2:
                   break;
              case 3:
                   vypsat();
                   break;
              case 5:
                   smycka();
                   break;
              case 6:
                   poradi();
                   break;
              case 7:
                   save();
                   break;
              case 8:
                   load();
                   break;
              case 9:
                   view();
                   break;
              case 0:
                   ++konec;
                   break;
              default:
                   printf("neplatny prikaz\n");
                  }
       } while (!konec);

    printf("konec\n");
    /*system("pause");   */
    getchar();
    getchar();
    return 0;
    }/*//konec main*/


Funkce save() ukládá databázi v paměti do textového souboru, nejdřív uloží na první řádek její velikost a pak na další samostatné řádky každý jednotlivý údaj. To kvůli jednoduchosti načítání. Zapisuje se funkcí fprintf(), úplně stejně jako obyčejným printf(), jen se zadá do jakého streamu.
Mimochodem, fprintf() se dá použít i pro výpis na obrazovku, když se zadá standardní výstup: fprintf(stdout,"Hello!\n");, nebo na chybový výstup, který se nedá přesměrovat, tudíž se vypíše na obrazovku i když standardní výstup přesměruješ do souboru nebo do roury: fprintf(stderr,"Nastala chyba!\n"); Takže kód save():

Kód: Vybrat vše

void save(void)
     {
     int i;
     FILE *vystup;

     if ((vystup=fopen("pokus.txt","w")))
        {
        fprintf(vystup,"%d\n",pocet_karet);
        for (i=0;i<pocet_karet;++i)
            fprintf(vystup,"%s\n%s\n%d\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
        fclose(vystup);
        }
     else
        printf("Nelze ulozit data do pokus.txt!\n\a");
     }


Funkce load() načítá databázi z textového souboru, nejdřív si samozřejmě načte její uloženou velikost, aby věděla kolik karet má vlastně načíst. Přitom samozřejmě hlídá i to, jestli se data vejdou do pole, a případnou chybu včas ošetří. Načítání probíhá funkcí fscanf(), která funguje stejně jako normální scanf(), jen navíc se zadáním streamu:

Kód: Vybrat vše

void load(void)
     {
     int i;
     FILE *vstup;

     if ((vstup=fopen("pokus.txt","r")))
        {
        fscanf(vstup,"%d\n",&pocet_karet);
        if (pocet_karet>20)
           {
           printf("Pocet karet %d je vetsi nez 20, databaze nebude nactena cela!\n\a",pocet_karet);
           pocet_karet=20;
           }
        for (i=0;i<pocet_karet;++i)
            fscanf(vstup,"%s %s %d",lide[i].jmeno,lide[i].prijmeni,&lide[i].plat);
        fclose(vstup);
        }
     else
        printf("Nelze nacist data z pokus.txt!\n\a");
     }


A když máme v paměti nějaká data, nebylo by také špatné mít možnost si je zobrazit, takže funkce view(), která vypíše celé pole karet na obrazovku:

Kód: Vybrat vše

void view(void)
     {
     int i;

     for (i=0;i<pocet_karet;++i)
         printf("%s %s %d Kc\n",lide[i].jmeno,lide[i].prijmeni,lide[i].plat);
     }


Pokud máš už nějakou databázi vytvořenou a uloženou v binární podobě, můžeš jí s těmihle úpravami načíst z Menu pomocí (3), pak buď vypsat (9) nebo uložit jako text (7). A buď hned nebo až při dalším spuštění programu už jí načteš textově (8).
Ten textový soubor můžeš libovolně upravovat jiným programem, třeba pomocí textového editoru, ale dej pozor ať nepoškodíš jeho strukturu, nebo u textových řádků nepřekročíš maximální délku. Akorát není možné ho po načtení uložit zpět do binárního tvaru, pro to v programu není funkce.
Mohl bys to zkusit aspoň nouzově propašovat do nové funkce pridat(), která chybí v Menu pod číslem (2), ta by po přidání nové karty zaměstnance vždy automaticky uložila celou databázi binárně.

No a pak bude ta správná chvíle celý ten program zahodit a napsat úplně znovu, podle kompletního uspořádaného návrhu, pěkně čistě a přehledně, ne takovýhle záplatovaný slepenec 8)
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

Mr_piruletka
nováček
Příspěvky: 5
Registrován: únor 12
Pohlaví: Muž
Stav:
Offline

Re: Databaze v cecku, problem se souborem

Příspěvekod Mr_piruletka » 09 úno 2012 20:56

i kdyz je to vsechno urcite jednoduche tak v tom uz ted mam bordel a v hlave nemam uplne vsechno vyjasnene, takze uz to zacinam psat znovu a pochybuju ze nebudu mit nejake problemy takze Te asi budu zase obtezovat :?

--- Doplnění předchozího příspěvku (09 Úno 2012 22:52) ---

sice jsem "nic" jeste nenapsal ale program dela to co chcu a ne jak predtim "to co pisu" :D !! DIKY MOC!!! mozna nekde nastanou nejake problemy, ale myslim ze to zmaknu, takze davam fajfku, ale to neznamena ze uz se nezeptam :)


  • Mohlo by vás zajímat
    Odpovědi
    Zobrazení
    Poslední příspěvek
  • Problém s RAM
    od lukas222 » 04 lis 2024 13:52 » v Problémy s hardwarem
    4
    3386
    od lukas222 Zobrazit poslední příspěvek
    05 lis 2024 13:36
  • Problém s FPS
    od mcrakvar » 26 lis 2024 16:22 » v Vše ostatní (sw)
    4
    4020
    od petr22 Zobrazit poslední příspěvek
    28 lis 2024 10:06
  • Problém s internetem Příloha(y)
    od valama » 06 dub 2025 16:13 » v Internet a internetové prohlížeče
    11
    4780
    od RIKI22 Zobrazit poslední příspěvek
    06 dub 2025 20:42
  • Problém s mikrofonem Příloha(y)
    od Shokata88 » 19 úno 2025 16:44 » v Problémy s hardwarem
    4
    2557
    od Shokata88 Zobrazit poslední příspěvek
    19 úno 2025 19:18
  • Problém s internetem
    od yakubb23 » 31 led 2025 19:01 » v Sítě - hardware
    1
    4631
    od meda2016 Zobrazit poslední příspěvek
    31 led 2025 21:50

Zpět na “Programování a tvorba webu”

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 5 hostů