Come si crea una tabella in C in memoria

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
Come si crea una tabella in C?

Il mio intento è quello di creare una tabella non intera cioè che non sia di N * N righe e colonne ma N righe con alcune celle come colonne.
Mi spiego con una figura

TAB-PARZIALE.PNG

E' una tabella di 4 righe * 4 righe di massima dimensione. Puo avere anche solo 2 colonne utilizzate invece che 4 e avere 5 o piu righe.

Quale struttura dati dovrei utilizzare tra: liste concatenate, grafo, albero binario. Oppure altre non elencate?
potete aiutarmi con qualche tutorial o guide, e qualche giorno che ci sto pensando. Vi ringrazierò infinitamente.

Ciao
 

Dumah Brazorf

Utente cAttivo
Utente Èlite
7,629
3,551
Scusa che senso daresti ai dati se non li incaselli in una specifica colonna?
Poi riga per riga popoli solo le colonne che ti servono lasciando gli altri nulli.
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
Creo comunque la mia tabella di 4 colonne e molte righe e lascio i campi, le celle vuote di quelle che non uso. A proposito di creare una tabella in modo dinamico cioè non conoscendo ne quante righe ne quante colonne iniziare come posso fare?
Una' istruzione semplice come:
C:
#include <stdio.h>
#define QLIB 5           /* Quantità libri caricati */

struct rec {    /*1*/
  char titolo[50];
  char autore[20];
  char editore[20];
  float prezzo;
};

typedef struct rec libro;
libro libreria[QLIB];

Crea 5 righe di una tabella con 4 colonne.

Ora con le colonne come faccio a renderle dinamiche? Possono assumere due tipi di dati char * oppure int. Si potrebbero utilizzare una struttura liste concatenate in cui ho sempre char * e int, e aggiungere la colonna dinamicamente con la malloc. Puo starci come ragionamento?
Post unito automaticamente:

Poi riga per riga popoli solo le colonne che ti servono lasciando gli altri nulli.
grazie per la risposta.

C:
struct rec{
    char sgenerico[100]
    int igenerico;
    int iposizione; //posizione della colonna 1 - 2 - 3 - 4 e altri.
   struct  rec *successivo;
}

typedef struct rec libro;
libro libreria[QLIB]; //ho creato di certo 5 righe di una struttura che ha N colonne a piacere
//in cui sfrutto solo uno dei campi: stringa oppure intero.
Post unito automaticamente:

libro libreria[QLIB]; //ho creato di certo 5 righe di una struttura che ha N colonne a piacerev
//in cui sfrutto solo uno dei campi: stringa oppure intero.
Ora il problema è come rendere dinamico il numero di righe, perchè cosi è statico: di default alloco memoria per 5 o N inseriti dall'utente quando invece vorrei aggiungere una alla volta di riga.
 
Ultima modifica:

leleferrari99

Nuovo Utente
133
15
CPU
Intel Core i5-4570
Scheda Madre
Asus H97 Pro Gamer
HDD
Western Digital Caviar Blue 1TB 7200Rpm
RAM
Kingston 2x4gb
GPU
Asus Geforce GTX 960 2gb OC edition
PSU
Antec HCG-620M 620w 80+ Bronze
Case
Antec GX500
OS
Windows 10
Potresti inserire una riga alla volta impiegando una lista
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
Potresti inserire una riga alla volta impiegando una lista

Ho scritto questo programmino. Con le colonne ci siamo. Ora sto cercando di capire come fare la lista con le righe.

C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QLIB 5           /* Quantità libri caricati */

int main()
{

    struct rec{
        char sgenerico[100];
        int igenerico;
        int iposizione; //posizione della colonna 1 - 2 - 3 - 4 e altri.
        struct rec *successivo;
    };

    typedef struct rec libro;

    libro *nuovolibro0;
    libro *nuovolibro1;
    libro *libreria[QLIB];

    libreria[0] = (libro*)malloc(sizeof(libro));

    strcpy(libreria[0]->sgenerico , "Primo libro"); //titolo del libro
    libreria[0]->igenerico = 0;
    libreria[0]->iposizione = 2;
    libreria[0]->successivo = NULL;

    nuovolibro0 = (libro *)malloc(sizeof(libro));
    strcpy(nuovolibro0->sgenerico ,"");
    nuovolibro0->igenerico = 30; //costo del libro
    nuovolibro0->iposizione = 1;
    nuovolibro0->successivo = libreria[0];

    libreria[0] = nuovolibro0;

    nuovolibro1 = (libro *)malloc(sizeof(libro));
    strcpy(nuovolibro1->sgenerico,"Nicola Paganotti");//autore del libro
    nuovolibro1->igenerico = 0;
    nuovolibro1->iposizione = 0;
    nuovolibro1->successivo = libreria[0];

    libreria[0] = nuovolibro1;

    for(; libreria[0] != NULL; libreria[0] = libreria[0]->successivo ){
        printf("colonna posizione %d sgenerico:%s, igenerico:%d \n", libreria[0]->iposizione,
                                                                  libreria[0]->sgenerico,
                                                                  libreria[0]->igenerico );
    }


    printf("Hello world!\n");
    return 0;
}
 
U

Utente cancellato 371741

Ospite
Hai un moderno pc immagino, potra contenere comodamente tutte le scansie di una grande libreria.
Piuttosto che complicarti la vita con liste concatenate, forse puoi crearti la tabella completa, statica, senza pensieri

Codice:
struct libro {
    int codice;  
    ...
};

static struct libro *tabella[MAX_COLS][MAX_RIGHE];

e marcarti inizialmente tutte le celle con un flag "unused", tipo un -1.
Dove metti libro salvi il puntatore.
Per cercarlo fai un semplice for(), con "continue" in caso di -1, altrimenti verifichi il codice.
 

Andretti60

Utente Èlite
6,440
5,091
Usando solo il linguaggio C senza nessuna libreria di supporto (questi sono i tipi di problemi per cui si usa una database) è di usare una lista concatenata (un elemento per ogni “riga”) dove un membro del soggetto è a sua volta un’altra lista concatenata, dove gli elementi sono appunto solo le caratteristiche del libro che sono valide. Ovvio che ogni elemento di questa lista “interna” deve avere un membro che lo definisca in maniera univoca, che può essere una stringa (per esempio “autore” o “titolo”) oppure un intero definito come una enumerazione.
Non dico che questa sia la soluzione migliore (dipende da tanti dettagli), è solo una soluzione “possibile” in base alle indicazioni che ci hai dato.
 
  • Mi piace
Reazioni: leleferrari99

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
dove un membro del soggetto è a sua volta un’altra lista concatenata, dove gli elementi sono appunto solo le caratteristiche del libro che sono valide. Ovvio che ogni elemento di questa lista “interna” deve avere un membro che lo definisca in maniera univoca, che può essere una stringa (per esempio “autore” o “titolo”) oppure un intero definito come una enumerazione.
L'interpretazione del codice scritto è corretta. Come dice @bigendian perchè complicarsi la vita, basta farla statica. Ma cosi ho una tabella grossa a priori. Nel database quando l'utente definisce la tabella definisce anche il numero di colonne. Non definisce però il numero di righe. Come si puo fare che aumento la dimensione statica dell'array?
Provo a ipotizzare che inizio con il copiare i dati dall'array multidimensionale al nuovo array di dimensioni piu grosse.

Ora mi resta di capire come usare un puntatore a puntatore per creare un elenco dinamico di liste. Pare che si riesca.
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
Il codice della creazione della tabella dinamica la trovate nel file main.txt.
E' da cambiare l'estensione da txt->c per poterlo compilare.
Stampa le prime due righe di una tabella dinamica di 4 colonne! Ci siamo riusciti. grazie dei consigli e di rispondere nel breve tempo.

Rimane la creazione delle funzioni di aggiungi riga, aggiungi colonna, aggiungi colonne,
Inoltre provo a fare gli inserimenti acid. Nel caso succede un guasto delle poter ripulire l'intera tabella cancellandola o provare a sistemare la tabella con le colonne che devono essere aggiunte per completare la tabella.
 

Allegati

  • main.txt
    3.3 KB · Visualizzazioni: 22

Andretti60

Utente Èlite
6,440
5,091
..
perchè complicarsi la vita, basta farla statica. Ma cosi ho una tabella grossa a priori. Nel database quando l'utente definisce la tabella definisce anche il numero di colonne.
Appunto, va bene solo se la dimensione della tabella rientra nello spazio che il SO riserva ai dati del programma, se si hanno decine di colonne e decine di righe non è un problema.
Dipende dal database, se il numero delle colonne è fisso e ben poche rimarranno non utilizzate va benissimo definire una tabella statica, altrimenti si definisce una tabella separata con una chiave secondaria, che andrà poi unita alla tabella principale mediante un JOIN. Questo per un database di tipo SQL, per un NoSQL (tipo Mongo) il problema non si pone, infatti il problema da te proposto va benissimo con un database di tipo key–value (che è poi quello che ho proposto nel mio messaggio precedente)
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
questi sono i tipi di problemi per cui si usa una database
Ora mi resta di capire come usare un puntatore a puntatore per creare un elenco dinamico di liste
si definisce una tabella separata con una chiave secondaria, che andrà poi unita alla tabella principale mediante un JOIN.
A proposito di join, ora il mio passo successivo è quello di implementare la CROSS join. Uitlizzerò quindi le mie liste concatenate per metterle in prodotto cartesiano.
Per esempio ho due insiemi A {x,y,z} e B {1,2,3}, il prodotto cartesiano è un insieme che comprende tutte le copie ordinate
(x,1) (x,2) (x,3)
(y,1) (y,2) (y,3)
(z,1) (z,2) (z,3)

E' l'ecquivalente dell' istruzione SQL:
SQL:
SELECT column_list
FROM
    A,
    B;

Nel caso di "libro"
SQL:
CREATE TABLE `tbook` (
  `ctitle` varchar(100) NOT NULL,
  `ccost` int NOT NULL,
  `cauthor` varchar(100) NOT NULL,
  PRIMARY KEY (`ctitle`)
)

cosi la query CROSS join sulla stessa tabella
SQL:
insert into tbook(ctitle,ccost,cauthor) values ("primo libro",30,"zabit");
insert into tbook(ctitle,ccost,cauthor) values ("secondo libro",50,"andretti60");

select t1.*,t2.*
from tbook t1,
     tbook t2;

ottengo questo risultato

CROSS-JOIN.PNG

Mi rimane di capire come liste concatenate si prestano a essere messe in prodotto cartesiano senza selezione per il momento.
Ricordate il "Mi piace"
 
U

Utente cancellato 371741

Ospite
Rispetto a tavola statica, liste concatenate hanno svantaggio che i dati non si cache-ano, per via dell'utilizzo di puntatori, quindi poco performanti, anche se in un moderno pc te ne freghi. Come appunto te ne freghi di allocare 100'000 libri, 800K di memoria di puntatori, piu dati libro, metti altri 2 o 3 Mega ? Anche con malloc se vuoi. Se ti piacciono le liste concatenate, giocale pure, sempre bene esercitarsi :)

Puoi anche dare un occhiata alle liste del kernel linux se ti va

 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
Se ti piacciono le liste concatenate, giocale pure
Si ci gioco su un po', cosi sò fino a dove arrivo. Dovrò fare anche una simulazione in cui gli inserimenti cella per cella dovrà essere "coerente" in caso di guasto, non devono rimanere "mezze tabelle o dati appesi".
Ora sto pensando come fare la cross join sulla stessa tabella. ci lavoro su un'altra mezza giornata senza metterci altro tempo. Se potete postate qualche soluzione cross join su array.
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
La tabella sono riuscita a crearla, ma pultroppo ha una "schema fisso".

Il problema del C è che non fornisce un meccanismo per creare strutture generiche e dinamiche.

It isn't possible to dynamically define a struct that is identical to a compile-time struct.

It is possible, but difficult, to create dynamic structures that can contain the information equivalent to a struct. The access to the data is less convenient than what is available at compile-time.

All else apart, you cannot access a member somestruct.not_seen_at_compile_time using the dot . or arrow -> notation if it was not defined at compile-time.
fonte stackoverflow.com
Sapete in che linguaggio è stato scritto Mysql Server? in C soltanto o anche in C++?

Da qualche lettura scolastica come si fa a ottenere l'aggiunta di un campo di tipo qualsiasi (int, char *, double) nella struttura struct? La struct va definita al livello codice quindi i dati devono essere conosciuti. ma allora non si puo in definitiva con il linguaggio C definire uno schema.

Ho guardato Sqlite i sorgenti sono scritti in C. probabilmente quello che voglio ottenere è un sistema cache in memoria efficiente e non un dbms. Potrei utilizzare la tabella per salvare le collisioni che si verificano quando uso una struttura array limitata implementando di fatto le funzioni hash sugli array.
 
Ultima modifica:

Andretti60

Utente Èlite
6,440
5,091
Puoi usare una Union, dove inserire tutti i tipi di dato a cui sei interessato, ovvio poi hai bisogno di un ulteriore membro che definisce che tipo di dato da usare per quel particolare valore. È quello che si fa anche in C++, un sacco di istruzioni “switch” tutte le volte che si accede ai valori (ma almeno in C++ sono incapsulati dentro a una classe.)
 
  • Mi piace
Reazioni: BigIssue

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili