Spojový seznam v C - zápis do souboru

Thomas

Spojový seznam v C - zápis do souboru
« kdy: 21. 10. 2016, 00:48:22 »
Potřebuji poradit:

Mám triviální jednosměrný lineární spojový seznam,
mám 4 prvky na zadání(název, hmotnost, jasnost, radiální rychlost) a potřebuji to nacpat do souboru.
Vše je psané v C. Koukám do toho už dobrý 4 hodiny a nemůžu se k tomu dobrat :-/
Tady je kód, stačí když mi to někdo vysvětlí, nemusí to psát za mne, jde mi spíš o princip jak dostat prvek z lin. spoj. seznamu i do souboru a jak ho ze souboru zase přečíst což bude analogie k zápisu.
kód hlavičky:

Kód: [Vybrat]
#ifndef PARAMETRY_H
#define PARAMETRY_H

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

typedef struct katalog {


    char nazev;       
    int radial_rychlost;
    int hmotnost;
    int jasnost;
       
   
    struct katalog *nasledujici;

} KATALOG;



void pridat_nazev(KATALOG **pps, char nazev) {
   
    KATALOG *ps;
   
    ps = (KATALOG *) malloc(sizeof(KATALOG));
   
    if (ps != NULL) {
       
        printf("Chyba alokace paměti!\n");
       
        return;
       
    }
   
    ps->nazev;
    ps->nasledujici = *pps;
   
    *pps = ps;   
   
   
};

void pridat_radialni_rychlost(KATALOG **pps, int radial_rychlost) {
   
   
    KATALOG *ps;
   
    ps = (KATALOG *) malloc(sizeof(KATALOG));
   
    if (ps != NULL) {
       
        printf("Chyba alokace paměti!\n");
       
        return;
       
    }
   
    ps->radial_rychlost;
    ps->nasledujici = *pps;
   
    *pps = ps;
   
};


void pridat_hmotnost(KATALOG **pps, int hmotnost) {
   
   
    KATALOG *ps;
   
    ps = (KATALOG *) malloc(sizeof(KATALOG));
   
    if (ps != NULL) {
       
        printf("Chyba alokace paměti!\n");
       
        return;
       
    }
   
    ps->hmotnost;
    ps->nasledujici = *pps;
   
    *pps = ps;
   
};


void pridat_jasnost(KATALOG **pps, int jasnost) {
   
   
    KATALOG *ps;
   
    ps = (KATALOG *) malloc(sizeof(KATALOG));
   
    if (ps != NULL) {
       
        printf("Chyba alokace paměti!\n");
       
        return;
       
    }
   
    ps->jasnost;
    ps->nasledujici = *pps;
   
    *pps = ps;
   
};


#endif

kód void main():

Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "parametry.h"
#include "mazani.h"
#include "hledani.h"


 

int main() {
   
    char c;
   
    FILE *fa;
   
    fa = fopen("/home/teodor/Plocha/katalog_exoplanet.txt", "a+");
   
    if(fa == NULL) {
       
        fputs("Nelze otevrit soubor!\n", stderr);
       
        return 1;
       
    } else if(fa != NULL) {
       
        printf("Soubor uspesne otevren!\n");
       
    }
             
   // int choice = 0;
   
   /* do {
       
        choice = getchoice("Vyberte operaci: \n", menu);    // Volani fce, ktera obsahuje menu
        printf("Zvolili jste: %c\n", choice);       
       
    } while(choice != 'q');
    */   
   
   
        KATALOG *ps;
       
        ps = NULL;     
       
        pridat_nazev(&ps, 0);
        pridat_radialni_rychlost(&ps, 1);
        pridat_hmotnost(&ps, 2);
        pridat_jasnost(&ps, 3);
       
       
       
   
   
   
    fclose(fa);
     
   
    return 0;
       
}

Předem díky!
« Poslední změna: 21. 10. 2016, 08:11:18 od Petr Krčmář »


mr. big

Re:Spojový seznam -zápis do souboru
« Odpověď #1 kdy: 21. 10. 2016, 01:01:40 »
Co presne maji delat radky jako:

    ps->nazev;

:-D

Jinak ukladat do souboru ukazatele na dalsi polozku asi nema smysl takze bych tam proste hazel jeden zaznam za druhym. Pseudokod:

    for each item:
        zapis nazev
        zapis hmotnost
        zapis jasnost
 
Potom cteni by vypadalo:

    while not EOF:
        precti nazev
        precti hmotnost
        precti jasnost
        pridej do seznamu polozku s prave prectenymi daty

Thomas

Re:Spojový seznam -zápis do souboru
« Odpověď #2 kdy: 21. 10. 2016, 01:10:31 »
Co presne maji delat radky jako:

    ps->nazev;

:-D

Jinak ukladat do souboru ukazatele na dalsi polozku asi nema smysl takze bych tam proste hazel jeden zaznam za druhym. Pseudokod:

    for each item:
        zapis nazev
        zapis hmotnost
        zapis jasnost
 
Potom cteni by vypadalo:

    while not EOF:
        precti nazev
        precti hmotnost
        precti jasnost
        pridej do seznamu polozku s prave prectenymi daty

Já to vzal z linuxsoft.cz a tam je to jen přeloženo z wikipedie :)
Ukazatel na další prvek, ne?
No, právě že zadání je úplně k hovnu - operace přidání, mazání, hledání nad zásobníkem(spojový lin, seznam) a pak při přidání to nacpat i do souboru a při hledání ze souboru číst.

Martin Dráb

Re:Spojový seznam -zápis do souboru
« Odpověď #3 kdy: 21. 10. 2016, 01:13:11 »
Navíc úspěšnou alokaci vyhodnocujete jako chybu. Myslím si, že by nejprve bylo dobré pokusit se správně ten spojový seznam vytvořit a jeho ukládání řešit až poté.

Název položky katalogu nemáte definovaný jako řetězec, ale jako znak. Nevím, zda je to účel či ne (zda jsou názvy pouze jednoznakové).

Co se týče ukládání, řiďte se příspěvkem nade mnou. V případě řetězcových názvů tam je lehká komplikace v tom, že řetězce nemají pevnou délku, ale to lze řešit například tím, že řetězec uložíte jako jeho délku následovanou obsahem.

Kit

Re:Spojový seznam -zápis do souboru
« Odpověď #4 kdy: 21. 10. 2016, 01:16:36 »
Je tam i chyba v tom, že pro každý atribut se alokuje celý nový záznam. Přitom by zřejmě v jednom záznamu měly být všechny čtyři atributy.


Thomas

Re:Spojový seznam -zápis do souboru
« Odpověď #5 kdy: 21. 10. 2016, 01:20:30 »
Navíc úspěšnou alokaci vyhodnocujete jako chybu. Myslím si, že by nejprve bylo dobré pokusit se správně ten spojový seznam vytvořit a jeho ukládání řešit až poté.

Název položky katalogu nemáte definovaný jako řetězec, ale jako znak. Nevím, zda je to účel či ne (zda jsou názvy pouze jednoznakové).

Co se týče ukládání, řiďte se příspěvkem nade mnou. V případě řetězcových názvů tam je lehká komplikace v tom, že řetězce nemají pevnou délku, ale to lze řešit například tím, že řetězec uložíte jako jeho délku následovanou obsahem.

Díky, to jsem ani nepostřehl. Já už nad tím dneska spím.

Thomas

Re:Spojový seznam -zápis do souboru
« Odpověď #6 kdy: 21. 10. 2016, 01:22:03 »
Je tam i chyba v tom, že pro každý atribut se alokuje celý nový záznam. Přitom by zřejmě v jednom záznamu měly být všechny čtyři atributy.

Fce pro každý záznam jsem napsal poté co mi gcc hlásilo, že tam mam moc argumentů.
Měl jsem na všechny 4 záznamy jednu fci.
No, jdu spát a zítra to předělám. Když tak se ozvu,pokud bych se nikam nehnul...

Kit

Re:Spojový seznam -zápis do souboru
« Odpověď #7 kdy: 21. 10. 2016, 01:22:27 »
Atribut "nazev" má jen jeden znak?

Kit

Re:Spojový seznam -zápis do souboru
« Odpověď #8 kdy: 21. 10. 2016, 01:25:31 »
Fce pro každý záznam jsem napsal poté co mi gcc hlásilo, že tam mam moc argumentů.
Měl jsem na všechny 4 záznamy jednu fci.

Možná jen neseděl počet formálních parametrů s počtem skutečných parametrů.

Parametrů můžeš mít kolik chceš, v daném případě by ty 4 parametry byly tak akorát.

Thomas

Re:Spojový seznam -zápis do souboru
« Odpověď #9 kdy: 21. 10. 2016, 09:33:56 »
Fce pro každý záznam jsem napsal poté co mi gcc hlásilo, že tam mam moc argumentů.
Měl jsem na všechny 4 záznamy jednu fci.

Možná jen neseděl počet formálních parametrů s počtem skutečných parametrů.

Parametrů můžeš mít kolik chceš, v daném případě by ty 4 parametry byly tak akorát.

Super,
za chvilku se do toho pustím a postnu kód, abych se nějak hejbnul.

anonym

Re:Spojový seznam v C - zápis do souboru
« Odpověď #10 kdy: 21. 10. 2016, 09:49:18 »
jak moc te boli cross-platform prenositelnost?

zkus si rozdelit ten seznam a ty data do 2 structu, pak muzes zapisovat/cist celej struct s datama, a nemusis se zajimat o to kolik je v nem prvku.

Karel

Re:Spojový seznam v C - zápis do souboru
« Odpověď #11 kdy: 21. 10. 2016, 10:04:36 »
Jen pseudo-C, nemám zde překladač

ps2 = ps; // ps2 je pomocna promenna, zacina jako ukazatel na prvni prvek seznamu a pak se posouva

while ( ps2 != NULL )
{
   fprintf(fa, "%c %i %i %i\n", ps2->nazev, ps2->radial_rychlost, ps2->hmotnost, ps2->jasnost);
   ps2 = ps2->nasledujici;
}

-----------------------------------------------------------
Nacitani je slozitejsi, je potreba se rozhodnout, zda nacitani je soucasti funkci pro praci s tim seznamem, nebo stoji mimo. V zasade to bude neco takoveho:

char _nazev;
int _radial_rychlost;
int _hmotnost;
int _jasnost;

while( fscanf( fa, "%c %i %i %i\n", &_nazev, &_radial_rychlost, &_hmotnost, &_jasnost) == 4)
   {
   ... pridej do seznamu
   }

-----
To pridej do seznamu pak muze byt ten kus kodu s mallocem apod. Ale jen pokud ta funkce pro nacteni je soucasti toho seznamu. Pokud to ma byt samostatna funkce, tak je potreba naopak volat tu funkci "pridat".

Thomas

Re:Spojový seznam v C - zápis do souboru
« Odpověď #12 kdy: 21. 10. 2016, 13:58:29 »
kód header:

Kód: [Vybrat]
#ifndef PARAMETRY_H
#define PARAMETRY_H

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


typedef struct katalog {


    char nazev [50];       
    int radial_rychlost;
    int hmotnost;
    int jasnost;
       
   
    struct katalog *nasledujici;

} KATALOG;



void pridat_parametry(KATALOG **pps, char nazev, int radial_rychlost, int hmotnost, int jasnost) {
   
    KATALOG *ps;
   
    ps = (KATALOG *) malloc(sizeof(KATALOG));
   
    if (ps == NULL) {
       
        printf("Chyba alokace paměti!\n");
       
        return;
       
    }
   
    ps->nazev;
    ps->radial_rychlost;
    ps->hmotnost;
    ps->jasnost;
    ps->nasledujici = *pps;
   
    *pps = ps;   
   
   
};


#endif

Mám tam jednu funkci pro záznam parametru,
a tady je void main() kód:

Kód: [Vybrat]
void vypis_katalog(const KATALOG *ps) {
 
    while(ps != NULL) {
       
        printf("%s\n", ps->nazev);
        ps = ps->nasledujici;
        printf("%i\n", ps->radial_rychlost);
        ps = ps->nasledujici;
        printf("%i\n", ps->hmotnost);
        ps = ps->nasledujici;
        printf("%i\n", ps->jasnost);       
       
       
    }
   
   
};
 

int main() {
   
    char c;
   
    FILE *fa;
   
    fa = fopen("/home/teodor/Plocha/katalog_exoplanet.txt", "a+");
   
    if(fa == NULL) {
       
        fputs("Nelze otevrit soubor!\n", stderr);
       
        return 1;
       
    } else if(fa != NULL) {
       
        printf("Soubor uspesne otevren!\n");
       
    }
             
   
   
   
        KATALOG *ps;
       
        ps = NULL;   
       
        pridat_parametry(&ps, 0);  /* Tady to hodí během překladu tuhle hlášku: too few arguments to function
        pridat_parametry(&ps, 1);
        pridat_parametry(&ps, 2);
        pridat_parametry(&ps, 3); */       
       
       
        vypis_katalog(ps);
       
       
       
   
   
   
    fclose(fa);
     
   
    return 0;
       
}

Dvě struct mne taky napadli, jenže tohle je semestrálka a má striktní zadání, dělám VŠ dálkově.
To Karel: Tak tohle zkusim, jinak ten spojový seznam bude muset ukládat informace do souboru a pak z nich zase načítat popřípadě mazat.

gamer

Re:Spojový seznam v C - zápis do souboru
« Odpověď #13 kdy: 21. 10. 2016, 14:26:59 »
Než se do takového projektu pustíš, nebylo by lepší naučit se základy C? Ty totiž neznáš, takže s tvými znalostmi nemůžeš ten projekt dát dohromady. Neber si to nějak špatně, každý nějak začínal, jde o to, že C znáš příliš špatně na to, abys v něm mohl úspěšně udělat projekt podle zadání. Pár rad:
Kód: [Vybrat]
char nazev [50];
....
void pridat_parametry(KATALOG **pps, char nazev, int radial_rychlost, int hmotnost, int jasnost) {
Do pole nazev, které má 50 znaků, chceš dát ve funkci prida_parametry parametr nazev, který má jeden znak?

Kód: [Vybrat]
ps->radial_rychlost; // tohle nic nedělá
ps->radial_rychlost = radial_rychlost; // tohle jsi chtěl

Kód: [Vybrat]
void pridat_parametry(KATALOG **pps, char nazev, int radial_rychlost, int hmotnost, int jasnost) {
pridat_parametry(&ps, 0);  /* Tady to hodí během překladu tuhle hlášku: too few arguments to function
Co by to asi mělo udělat, máš funkci, která má 5 parametrů a dáváš jí jen 2 parametry?

Thomas

Re:Spojový seznam v C - zápis do souboru
« Odpověď #14 kdy: 21. 10. 2016, 15:57:14 »
Než se do takového projektu pustíš, nebylo by lepší naučit se základy C? Ty totiž neznáš, takže s tvými znalostmi nemůžeš ten projekt dát dohromady. Neber si to nějak špatně, každý nějak začínal, jde o to, že C znáš příliš špatně na to, abys v něm mohl úspěšně udělat projekt podle zadání. Pár rad:
Kód: [Vybrat]
char nazev [50];
....
void pridat_parametry(KATALOG **pps, char nazev, int radial_rychlost, int hmotnost, int jasnost) {
Do pole nazev, které má 50 znaků, chceš dát ve funkci prida_parametry parametr nazev, který má jeden znak?

Kód: [Vybrat]
ps->radial_rychlost; // tohle nic nedělá
ps->radial_rychlost = radial_rychlost; // tohle jsi chtěl

Kód: [Vybrat]
void pridat_parametry(KATALOG **pps, char nazev, int radial_rychlost, int hmotnost, int jasnost) {
pridat_parametry(&ps, 0);  /* Tady to hodí během překladu tuhle hlášku: too few arguments to function
Co by to asi mělo udělat, máš funkci, která má 5 parametrů a dáváš jí jen 2 parametry?

Neberu to zle, C si totiž kompletně opakuji. Nedělal jsem v něm dost dlouho.
No u toho char jsem si ani nevšiml co jsem nahrál za kravinu, no stane se komukoli.
Ale díky, za konstruktivní nakopnutí! :). Už jen uložení do souboru.
No, tu fci s více parametry zase zrušim a pro každý parametr si napíšu prasácky vlastní fci.