Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Thomas 21. 10. 2016, 00:48:22

Název: Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 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!
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: mr. big 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
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Thomas 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.
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Martin Dráb 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.
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Kit 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.
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Thomas 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.
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Thomas 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...
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Kit 21. 10. 2016, 01:22:27
Atribut "nazev" má jen jeden znak?
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Kit 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.
Název: Re:Spojový seznam -zápis do souboru
Přispěvatel: Thomas 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.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: anonym 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.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Karel 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".
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 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.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: gamer 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?
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 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.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Jenda 22. 10. 2016, 10:12:23
No, tu fci s více parametry zase zrušim a pro každý parametr si napíšu prasácky vlastní fci.

Jenže to bude mít jinou sémantiku. Místo toho, aby měla jedna položka k sobě přiřazené atributy, budeš mít ve spojáku náhodný mix položek a různých atributů.

Kód: [Vybrat]
typedef struct katalog {
  char nazev [50];
Doporučil bych spíš paměť alokovat dynamicky podle délky toho řetězce, tj. mít tam char*. Zase teda záleží na užití.

Jakmile název bude obsahovat mezeru, už to asi nepůjde ukládat a načítat tak triviálně přes fprintf/scanf. Asi bych si napsal vlastní ukládání a načítání řetězců, a to buď jako délka+obsah, nebo null-terminated. A pokud bych to chtěl mít do budoucna rozšiřitelné a kompatibilní se zbytkem světa, vykašlal bych se na nějakou vlastní serializaci a použil třeba Procotol Buffers. Pro tvůj případ stačí opsat example z dokumentace.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Jenda 22. 10. 2016, 10:15:37
A pokud fakt mocí mermo potřebuješ variabilní množství argumentů (v tomto případě bych ale raději použil parametr, který bude obsahovat bitmapu nastavovaných parametrů), tak se podívej na stdarg(3).
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 22. 10. 2016, 11:42:59
A pokud fakt mocí mermo potřebuješ variabilní množství argumentů (v tomto případě bych ale raději použil parametr, který bude obsahovat bitmapu nastavovaných parametrů), tak se podívej na stdarg(3).

No, já na ten projekt koukal do 3 ráno, takže to zjednodušim na přidání 2 položek.
S tím by snad problém být nemusel. Ono je tam dost striktní zadání u té semestrálky a já C neovládám v takové  míře, abych v něm dělal složitější úpravy. Kdysi jsem ho měl kvuli PIC a projel jsem si celého Herouta
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Kit 22. 10. 2016, 12:59:39
Asi bych začal výběrem serializačního formátu pro ukládání dat. V daném případě by mohl vyhovovat formát CSV.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 22. 10. 2016, 19:37:46
Tak už se mi konečně podařilo oživit základy C, přidávám parametry, ale mam problém s přidáním názvu, ona to určitě bude zase nějaká blbost, která mi uniká :-/
Tady je zdroják headeru:

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#define HODNOTA 100



typedef struct katalog {

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

} KATALOG;


void vloz_parametr(KATALOG **pps, int parametr_1, int parametr_2, int parametr_3, char *parametr_4) {
   
    KATALOG *ps;
   
    ps = (KATALOG *) malloc(sizeof(KATALOG));
   
    if(ps == NULL) {
        fputs("Chybna alokace pameti!\n", stderr);
       
        return;
    }
   
   
   ps->hmotnost = parametr_1;
   ps->nasledujici;
   ps->jasnost = parametr_2;
   ps->nasledujici;
   ps->radial_rychlost = parametr_3;
   ps->nasledujici;
   ps->nazev = parametr_4;
   
   
   
   
    *pps = ps;   
   
};


#endif

A tady main:

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

void vypis_katalog(const KATALOG *ps);
void vloz_parametr(KATALOG **pps, int parametr_1, int parametr_2, int parametr_3, char *parametr_4);

void vypis_katalog(const KATALOG *ps) {
   
    if(!ps)
        return;
   
    printf("Hmotnost: %i\n", ps->hmotnost);
    vypis_katalog(ps->nasledujici);
    printf("Radialni rychlost: %i\n", ps->radial_rychlost);
    vypis_katalog(ps->nasledujici);
    printf("Jasnost: %i\n", ps->jasnost);
    vypis_katalog(ps->nasledujici);
    printf("Nazev: %c\n", ps->nazev);
    vypis_katalog(ps->nasledujici);
   
};



int main() {
   
   
   
    FILE *fa;
   
    fa = fopen("/home/teodor/Plocha/parametry_exoplanet.txt", "w");
   
    if(fa == NULL) {
       
        fputs("Nelze otevrit soubor!\n", stderr);
       
        return 1;
       
    } else if(fa != NULL) {
       
        printf("Soubor uspesne otevren!\n");
       
    }
             
   
   
    int a, b, c;
    char jmeno[ROZSAH];
   
    printf("Zadejte radialni rychlost: \n");
    scanf("%d", &a);
    printf("Zadejte jasnost: \n");
    scanf("%d", &b);
    printf("Zadejte hmotnost: \n");
    scanf("%d", &c);
    printf("Zadejte nazev: \n");
    scanf("%c", &jmeno);
   
        KATALOG *s;
       
        s = NULL;   
       
        vloz_parametr(&s, a, b, c);
    //    fprintf(fa, "%d%d%d\n", a, b, c);       
       
        vypis_katalog(s);
       
       
       
   
   
   
    fclose(fa);
     
   
    return 0;
       
}

Bude mi stačit nějaký nakopnutí, u názvu nechci mít dynamicky přidělenou paměť. Název nebude obsahovat mezery, jen jedno slovo.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: nou 22. 10. 2016, 22:40:51
Treba pouzit
Kód: [Vybrat]
strcpy(ps->nazev, parametr_4);
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 22. 10. 2016, 23:08:07
Treba pouzit
Kód: [Vybrat]
strcpy(ps->nazev, parametr_4);


Díky, já už jsem opravdu přepracovaný; dva dny po sobě jsem šel spát ve tři ráno a unikaji mi tyhle maličkosti.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: linuxtardis 22. 10. 2016, 23:57:29
Okej, patnáctiletej beďatej tydýt se právě vyřádil. :D

Pevně doufám, že to budeš brát jenom jako návrh řešení a ne jako hotovou věc. Byl bych rád, kdyby sis všiml některých kontrol na selhání funkcí (např. scanf).

Soubor jsem změnil na /tmp/soubor.txt, kdybys jej hledal.
Kód: (parametry.h) [Vybrat]
/*
 * Projekt Bla
 *
 * Datové struktury katalogu.
 */

#ifndef PARAMETRY_H
#define PARAMETRY_H

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



///////////////
// STRUKTURY //
///////////////

/// \brief položka seznamu
typedef struct katalog {
    int radial_rychlost;
    int jasnost;
    int hmotnost;
    char *nazev;
   
    struct katalog *nasledujici;
} KATALOG;



//////////////////////
// PROTOTYPY FUNKCÍ //
//////////////////////


/// \brief Vytvoří položku spojového seznamu.
///
/// \param p_p_clanek    Ukazatel k ukazateli článku.
/// \param rychlost      Rychlost položky.
/// \param jas           Jas položky.
/// \param hmotnost      Hmotnost položky.
/// \param nazev         Název položky.
/// \return              EXIT_SUCCESS při úspěchu, EXIT_FAILURE při selhání.
int nova_polozka(KATALOG **p_p_clanek, int rychlost, int jas, int hmotnost, char *nazev);

/// \brief Smaže položku spojového seznamu.
///
/// POZOR: Na položku již nesmí být ukazováno.
///
/// \param p_clanek      Článek ke smazání.
/// \return              EXIT_SUCCESS při úspěchu, EXIT_FAILURE při selhání.
int smaz_polozku(KATALOG *p_clanek);

/// \brief Smaže katalog (spojový seznam).
///
/// \param p_clanek      První článek seznamu.
/// \return              EXIT_SUCCESS při úspěchu, EXIT_FAILURE při selhání.
int smaz_katalog(KATALOG *p_clanek);

/// \brief Vypíše na standardní výstup informace o položce.
///
/// \param p_clanek      Ukazatel na položku.
void vypis_polozku(const KATALOG *p_clanek);

/// \brief Vypíše všechny položky z katalogu.
///
/// \param p_polozka     Ukazatel na první položku.
void vypis_katalog(const KATALOG *p_clanek);


/////////////////////////
// IMPLEMENTACE FUNKCÍ //
/////////////////////////

int nova_polozka(KATALOG **p_p_clanek, int rychlost, int jas, int hmotnost, char *nazev) {
   
    // -- deklarace -- //
    KATALOG *p_clanek;
    size_t nazev_delka;
    char *nazev_kopie;
   
    // -- kontrola argumentů -- //
   
    if (p_p_clanek == NULL) {
        fputs("CHYBA V PROGRAMU: nova_polozka() zavolána s NULL-ovým cílovým umístěním.\n", stderr);
        return EXIT_FAILURE;
    }
   
    if (nazev == NULL) {
        fputs("CHYBA V PROGRAMU: nova_polozka() zavolána s NULL-ovým názvem.\n", stderr);
        return EXIT_FAILURE;
    }
   
    // -- zkopírování názvu -- //
   
    // zjištění délky původního názvu ve znacích
    nazev_delka = strlen(nazev);
   
    // alokace kopie o délce počet znaků + null terminator
    nazev_kopie = malloc(nazev_delka + 1);
   
    // kontrola alokace
    if (nazev_kopie == NULL) {
        fputs("Chyba: nemohu alokovat pamet pro nazev polozky.\n", stderr);
       
        return EXIT_FAILURE;
    }
   
    // samotné kopírování
    strncpy(nazev_kopie, nazev, nazev_delka);
   
    // kontrola na null terminator
    nazev_kopie[nazev_delka] = '\0';
   
    // -- vytvoření položky -- //
   
    // alokace položky
    p_clanek = (KATALOG *) malloc(sizeof(KATALOG));
   
    // kontrola alokace
    if(p_clanek == NULL) {
        fputs("Chybna nemohu alokovat pamet pro datovou polozku.\n", stderr);
       
        return EXIT_FAILURE;
    }
    // kopírování dat
    p_clanek->radial_rychlost = rychlost;
    p_clanek->jasnost         = jas;
    p_clanek->hmotnost        = hmotnost;
    p_clanek->nazev           = nazev_kopie;
    p_clanek->nasledujici     = NULL;
    // navrácení ukazatele na novou položku
    *p_p_clanek = p_clanek;   
   
    return EXIT_SUCCESS;
};


int smaz_polozku(KATALOG *p_clanek) {
   
    // -- kontrola argumentu -- //
    if (p_clanek == NULL) {
        fputs("CHYBA V PROGRAMU: smaz_polozku() zavolána s NULL-ovým pointerem.\n", stderr);
       
        return EXIT_FAILURE;
    }
   
    // smazání kopie názvu
    if (p_clanek->nazev != NULL)
        free(p_clanek->nazev);
   
    // smazání položky
    free(p_clanek);
   
    return EXIT_SUCCESS;
}

int smaz_katalog(KATALOG *p_katalog) {
    KATALOG *p_clanek = p_katalog;
   
    while (p_clanek != NULL) {
        KATALOG *p_dalsi = p_clanek->nasledujici;
       
        if (!smaz_polozku(p_clanek))
            return EXIT_FAILURE;
       
        p_clanek = p_dalsi;
    }
}

void vypis_polozku(const KATALOG *p_clanek) {
   
    // kontrola argumentů
    if(p_clanek == NULL)
        return;
   
    // výpis na standardní výstup
    printf("\"%s\":\n", p_clanek->nazev);
    printf(" * Hmotnost:          %d\n", p_clanek->hmotnost);
    printf(" * Jasnost:           %d\n", p_clanek->jasnost);
    printf(" * Radialni rychlost: %d\n", p_clanek->radial_rychlost);
    printf("\n");
   
};

void vypis_katalog(const KATALOG *p_katalog) {
    const KATALOG *p_clanek = p_katalog;
   
    int n = 1;
    while (p_clanek != NULL) {
   
        printf("%d. ", n++);
        vypis_polozku(p_clanek);
       
        p_clanek = p_clanek->nasledujici;
    }
}

#endif
Kód: (main.c) [Vybrat]
/*
 * Projekt Bla
 *
 * Hlavní část programu.
 */
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "parametry.h"

// maximální délka názvu
#define INPUT_BUFFER 256

//////////////////////
// PROTOTYPY FUNKCÍ //
//////////////////////

/// \brief Vstupní bod programu.
///
/// \return     0 při úspěchu, 1 při chybě.
int main(void);

/// \brief Přečte od uživatele číselnou hodnotu.
///
/// \param vyzva    Výzva k zadání údaje.
/// \return         Přečtené číslo.
int ziskej_cislo(const char *vyzva);

/// \brief Přečte od uživatele text.
///
/// \param vyzva     Výzva k zadání údaje.
/// \param buffer    Buffer pro uložení textu.
/// \param max       Maximální počet přečtených znaků.
void ziskej_text(const char *vyzva, char *buffer, size_t max);

/// \brief Přečte všechny dostupné znaky ze standardního vstupu a zahodí je.
void vycisti_vstup(void);

/// \brief Vypíše exoplanety do souboru.
///
/// \param soubor       Soubor, do kterého zapisovat.
/// \param p_katalog    Katalog k vypsání.
/// \return             EXIT_SUCCESS při úspěchu, EXIT_FAILURE při selhání.
void vypis_soubor(FILE *soubor, KATALOG *p_katalog);

/////////////////////////
// IMPLEMENTACE FUNKCÍ //
/////////////////////////


void vycisti_vstup(void) {
    char ch;
       
    do {
        ch = getchar();
    } while (ch != '\n' && ch != EOF);
}


int ziskej_cislo(const char *vyzva) {
    int hodnota;
   
    // opakuj, dokud nezískáš platnou hodnotu
    while (1) {
        int precteno;
       
        if (vyzva != NULL) {
            fputs(vyzva, stdout);
            fflush(stdout);
        }
       
        precteno = scanf(" %d", &hodnota);
       
        vycisti_vstup();
        if (precteno == 1) {
            break;
        }
    }
   
    return hodnota;
}

void ziskej_text(const char *vyzva, char *buffer, size_t max) {
    // stackoverflow: http://stackoverflow.com/a/4023921/1561345
    size_t delka;
   
    // opakuj, dokud nezískáš neprázdnou hodnotu
    do {       
        if (vyzva != NULL) {
            fputs(vyzva, stdout);
            fflush(stdout);
        }
    } while (fgets(buffer, max, stdin) == NULL);
   
    delka = strlen(buffer);
   
    // pokud uživatel zadal příliš dlouhé jméno, je třeba odhodit zbytek v zásobě.
    if (buffer[delka-1] != '\n') {
        vycisti_vstup();
        return;
    }

    // jinak jen ořízneme nový řádek.
    buffer[delka-1] = '\0';
    return;
}

void vypis_soubor(FILE *soubor, KATALOG *p_katalog) {
    KATALOG *p_clanek = p_katalog;
    while (p_clanek != NULL) {
        fprintf(soubor, "%s,%d,%d,%d\n",
                          p_clanek->nazev,
                          p_clanek->hmotnost,
                          p_clanek->jasnost,
                          p_clanek->radial_rychlost);
        p_clanek = p_clanek->nasledujici;
    }
}

int main(void) {
    FILE *fa = NULL;
    KATALOG *p_katalog = NULL, *p_clanek_posledni = NULL;
    int n = 1;
    char vstup[INPUT_BUFFER];
   
    // -- otevření souboru -- //
    fa = fopen("/tmp/soubor.txt", "w");
   
    if (fa == NULL) {
        fprintf(stderr, "Nepodarilo se otevrit soubor: %s!\n", strerror(errno));
       
        return EXIT_FAILURE;
       
    }
    printf("Soubor uspesne otevren!\n");
   
   
    // -- čtení exoplanet ze standardního vstupu -- //
    while(1) {
        int rychlost, jasnost, hmotnost;
        KATALOG *p_polozka = NULL;
       
        printf("Exoplaneta cislo %i\n", n++);
        ziskej_text("Zadejte nazev: \n", vstup, INPUT_BUFFER);
        hmotnost = ziskej_cislo("Zadejte hmotnost: \n");
        jasnost  = ziskej_cislo("Zadejte jasnost: \n");
        rychlost = ziskej_cislo("Zadejte radialni rychlost: \n");
       
        if (nova_polozka(&p_polozka, rychlost, jasnost, hmotnost, vstup) == EXIT_FAILURE)
            return EXIT_FAILURE;
       
        // aktualizace ukazatelů
        if (p_katalog == NULL) {
            p_katalog = p_polozka;
        }
        if (p_clanek_posledni != NULL) {
            p_clanek_posledni->nasledujici = p_polozka;
        }
        p_clanek_posledni = p_polozka;
       
        // dotaz na pokračování
        ziskej_text("Prejete si pridat dalsi exoplanety? [Y/n] ", vstup, INPUT_BUFFER);
        if (strcmp(vstup, "n") == 0 || strcmp(vstup, "N") == 0)
            break;
       
    }
   
    // -- výpis exoplanet na standardní výstup -- //
   
    fputs("\nExoplanety:\n\n", stdout);
    vypis_katalog(p_katalog);

    // -- výpis exoplanet do souboru -- //
   
    vypis_soubor(fa, p_katalog);

    // -- smazání seznamu -- //
   
    if (!smaz_katalog(p_katalog)) {
        return EXIT_FAILURE;
    }
   
    // -- uzavření souboru -- //
   
    if (fclose(fa) == EOF) {
        printf("Soubor se nepodarilo uzavrit: %s.\n", strerror(errno));
        return EXIT_FAILURE;
    }
   
    return EXIT_SUCCESS;
       
}
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: linuxtardis 23. 10. 2016, 00:14:20
Citace
operace přidání, mazání, hledání
Výchozí stav je toto:
Kód: [Vybrat]
[0]->[2]Pak vytvoříš položku a jako její nasledujici nastavíš budoucí následující položku ([2]):
Kód: [Vybrat]
[0]->[2]
[1]--^
Pak upravíš [0], aby ukazovala na [1]:
Kód: [Vybrat]
[0]->[1]->[2]Výchozí pseudostav:
Kód: [Vybrat]
[0]->[1]->[2]Pak v [0] nastavíš ukazatel nasledujici na [2]:
Kód: [Vybrat]
[0]->[2]
[1]--^
Pak smažeš [1].
Něco zajímavého: https://en.wikipedia.org/wiki/Read-copy-update (https://en.wikipedia.org/wiki/Read-copy-update).
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Teo_90 03. 12. 2016, 20:24:09
Všem díky,
momentálně se točim kolem mazání souborů v C.
Našel jsem, že existuje fce remove() z stdio.h. jenže mne to nefunguje :(

tady je můj kód:

Kód: [Vybrat]
#define CESTA "/home/teodor/Plocha/parametry_exoplanet.csv"
#include <stdio.h>

Kód: [Vybrat]
if( remove(CESTA) != 0) {
       
        perror("Soubor se nesmazal!\n");
    } else {
       
        printf("Soubor byl uspesne smazan!\n");
       
    }

Mažu spojový seznam a gcc mi ještě vypíše tuhle hlášku: free(): invalid pointer: 0x00007fff7ca16930

Chci jen nějak nakopnout, nechci aby to tu někdo řešil za mne.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: robotron 03. 12. 2016, 20:48:26
OT: osobne bych parametry_exoplanet.csv zpracovaval radsi v Julii nez v C.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Teo_90 03. 12. 2016, 21:32:05
OT: osobne bych parametry_exoplanet.csv zpracovaval radsi v Julii nez v C.


No já bych to raději dělal pomocí objektů v C++, ale tohle je semestrálka na VŠ a mí striktní zadání :(
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Teo_90 03. 12. 2016, 21:52:09
Mazání seznamu je opraveno, byla to moje zbrklost.
Chyba v pointeru.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: ByCzech 03. 12. 2016, 23:03:27
Všem díky,
momentálně se točim kolem mazání souborů v C.
Našel jsem, že existuje fce remove() z stdio.h. jenže mne to nefunguje :(

Já teda na mazání souborů raději používám unlink a ne "alias", který volá unlink nebo rmdir podle toho, jestli cesta je soubor nebo adresář... Něco se vymastí a smaže to adresář i když předpokládám soubor. To já nerad :D
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Teo_90 04. 12. 2016, 11:56:51
Všem díky,
momentálně se točim kolem mazání souborů v C.
Našel jsem, že existuje fce remove() z stdio.h. jenže mne to nefunguje :(

Já teda na mazání souborů raději používám unlink a ne "alias", který volá unlink nebo rmdir podle toho, jestli cesta je soubor nebo adresář... Něco se vymastí a smaže to adresář i když předpokládám soubor. To já nerad :D

No, docela na to čumim jako puk, protože soubor si vytvořim a pak ho chci smazat, tak použiji fci remove() z stdio.h a ona prostě nejde :D Soubor zůstane tam kde je :D Byl bych rád, kdyby mne tu někdo nakopl, jak to udělat i s tou cestou co mam výše.
Já rád používám statická makra kvůli přehlednosti kódu.
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Michal Kovacic 04. 12. 2016, 12:29:28
Bývá obvyklé, že funkce která neudělá svoji práci vrátí nějaký chybový kód. Ten alespoň orientačně napoví co se stalo...
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Teo_90 04. 12. 2016, 16:18:51
Bývá obvyklé, že funkce která neudělá svoji práci vrátí nějaký chybový kód. Ten alespoň orientačně napoví co se stalo...

To já vim taky, nicméně ono se to zkompiluje a fce se tváří, že se provedla, nicméně nic neudělá.
Soubor zůstane tam kde je...
Takže to přisuzuji tomu, že používám st. makro, který mi definuje cestu k souboru?
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Jenda 04. 12. 2016, 20:54:07
To já vim taky, nicméně ono se to zkompiluje a fce se tváří, že se provedla, nicméně nic neudělá.
Přečti si man 3 remove:
Citace
On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
a vypiš si to číslo (a pokud možno i perror(3)).
Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 27. 12. 2016, 18:46:37
Zdravim,
potřeboval bych pomoct s indexováním prvků při vkládání do spojového seznamu.
A pak ještě pomoct s rozběhem jednotlivých modulů v C.

tady jsou zdrojáky pro indexování při vkládání parametrů:

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include "katalog.h"
#define CESTA "/home/teodor/Plocha/Parametry_exoplanet.txt"                     // definovana cesta ke ctenemu souboru
#define ROZSAH 100                                                              // Staticka makro konstanta pro velikost nazvu parametru
#define ROZSAH_RADKY 300                                                        // Staticka makro konstat pro velikost radky



void menu();                                                                                                                           // Prototyp fce pro menu
void smaz_katalog(KATALOG **pps);                                                                                                      // Prototyp fce pro smazani katalogu
void smaz_soubor();                                                                                                                    // Prototyp fce pro smazani souboru
void vkladani_parametru(KATALOG **pps, char *parametr_1, long int parametr_2, long int parametr_3, long int parametr_4, int index);         // Prototyp fce pro vkladani parametru exoplanet
void hledani_parametru(const KATALOG *pps, int index);                                                                                 // Prototyp fce pro mazani jednotlivych parametru
int zapis_do_souboru(char *parametr_1, long int parametr_2, long int parametr_3, long int parametr_4);                                    // Prototyp fce pro ukladani do souboru
int cteni_ze_souboru();                                                                                                                  // Prototyp fce pro cteni ze souboru                                                                                     




#endif

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include "funkce.h"
#define ROZSAH_NAZVU 100




typedef struct katalog {                                            // Struktura prvku

    char nazev[ROZSAH_NAZVU];                                            // Prvek nazvu exoplanety
    int hmotnost;                                                   // Prvek hmotnosti exoplanety
    int jasnost;                                                    // Prvek jasnosti exoplanety
    int radial_rychlost;                                            // Prvek radialni rychlosti exoplanety
   
    struct katalog *nasledujici;                                    // Pointer struktury katalog na nasledujici prvek

} KATALOG;




#endif

Kód: [Vybrat]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include "funkce.h"
#include "katalog.h"



void vkladani_parametru(KATALOG **pps, char *parametr_1,long int parametr_2, long int parametr_3, long int parametr_4, int index) {
   
    KATALOG *ps;                                                                            // Pointer na strukturu katalog
       
    int idx = 0;                                                                            // pomocna promenna k porovnavani indexu od 0
   
     
   
    if(idx == index) {                                                                      // Porovnani parametru s hodnotou indexu
       
        ps = (KATALOG *) malloc(sizeof(KATALOG));                                           // Osetreni dynamickeho prideleni pameti
   
                if(ps == NULL) {   
       
                    fputs("Chybna alokace pameti!\n", stderr);                              // Pokud se neprideli pamet, vypise se chybove hlaseni
                                                                                            // a na chybovy vystup stderr
        return;   
       
    }
       
        if(ps) {
           
                                                                                     // Vsechny parametry exoplanety budou mit stejny index pro hledani
                 strcpy(ps->nazev, parametr_1);                                      // Pridani prvku do spoj. seznamu
                 ps->nasledujici;                                                    // Posun na dalsi prvek v rade
                 ps->hmotnost = parametr_2;                                          //            -//-
                 ps->nasledujici;   
                 ps->jasnost = parametr_3;
                 ps->nasledujici;                                                                 
                 ps->radial_rychlost = parametr_4 ;
               //  ps->nasledujici = NULL;                                             // Ukazuje na konec seznamu
             
   
                 *pps = ps;     
                   
           
        }     
         
    }
   
   
};

K té modulárnosti...mám implementaci jednotlivých fcí v .c souborech, třeba cteni_ze_souboru.c, v NetBenas se to přeloží, ale program nedělá to co má. Asi jsem někde něco neprovázal nebo nevim, ale když to udělám prasácky a výkonný kód nacpu do headers tak to běží tak jak má. Stejně když ty jednotlivé moduly kompiluji přes gcc -wall, přeloží se to, ale program nic nedělá.

Název: Re:Spojový seznam v C - zápis do souboru
Přispěvatel: Thomas 27. 12. 2016, 19:57:39
Modulárnost je už vyřešena, volal jsem si fci menu úplně zbytečně, proto to nic nedělalo.