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
Niente ci penso su. Attualmente è una tabella a schema fisso. Per averla di qualsiasi tipo non saprei. Proverò a guardare sqlite come è fatto a parte l'utilizzo dei btree.
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
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.)
Ho optato nuovamente per le liste concatenate.

C:
struct interolista{
    int valore;
    int nonusata;
    struct interolista *successivo;
};

struct varcharfissolista{
    char valore[100];
    int nonusata;
    struct varcharfissolista *successivo;
};

struct doppiolista{
    double valore;
    int nonusata;
    struct doppiolista *successivo;
};

struct record{
    int indiceriga;
    char numerocolonne;

    struct interolista *il;
    struct varcharfissolista *vfl;
    struct doppiolista *dl;

};

In questo modo ho tutti i campi a priori che mi servono per inserire un numero intero oppure un stringa oppure un doppio numero reale.
Rimane però il problema dell'input dell'utente.
Al momento è necessario modificare la struttura per aggiungere un campo in piu. Pero Ora provo a mettere tutto in un file in cui la colonna viene descritta. Cosi ho la possibilità di aggiungere una colonna senza modificare la struttura.
 
Ultima modifica:
  • Triste
Reazioni: Andretti60

Andretti60

Utente Èlite
6,440
5,091
Scusa ma quello che stai facendo non ha alcun senso. Una lista concatenata per valori di tipo diverso? Tanto vale avere una sola struttura con un membro per ognuno dei tipi che vuoi, ma è uno spreco di memoria (per quello ho suggerito una Union, che viene usata proprio per casi come questo).
Le liste concatenate vanno usare per ben altri scopi, ossia allocazione dinamica della memoria quando non si sa a priori quanta ne occorra, e la possibilità di inserire/cancellare elementi. Non certo il tuo caso.
 

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
è difficile da spiegare. E' senza dubbio uno spreco di spazio. Ma con il linguaggio C

non posso "inniettare" un membro in piu in una struct.​

L'obiettivo che voglio raggiungere è creare una tabella di tante colonne come si fa con i database, in cui lo schema lo definisce l'utente. Quindi con il modello "libro" ci sono riuscito perchè ho creato a priori la struct che descriveva il problema. Ora non è piu così. Il problema dice che dal descrittore della struttura devi costruirti la struttura. Cio che non si riesce a fare in C per quanto mi sforzi di pensarci.

Senza dubbio non si è sentito mai parlare di database che usassero liste concatenate per descrivere campi generici.

Allora ho optato per "lo spreco di memoria": pero se ci pensi non è uno spreco perchè dato lo schema:
create table animale{
id int,
name varchar(100)
type int
bite int,
claws int
}

In quel modo nella lista inserisco "interolista":id,type,bite,claws invece nella lista "varcharfissolista":name.
Quindi rimangono 5 campi piu doppiolista che vuota quindi NULL, totali 6 campi invece che creare un vettore multidimensionale N*N statico.

Scusa quello che stai facendo non ha alcun senso
Guarda che non è sbagliato del tutto secondo me. E' vero che non è questo il modo di implementare un db ma con cio che dici non sono d'accordo. grazie del supporto @Andretti60. Perchè 6 campi nelle liste non mi sembra uno spreco di memoria ma giustamente le liste collegate si usano per altri scopi ;)
 
Ultima modifica:

BAT

Moderatore
Staff Forum
Utente Èlite
22,668
11,452
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Senza dubbio non si è sentito mai parlare di database che usassero liste concatenate per descrivere campi generici.
c'è un motivo:
non ci sono database che usano liste perché la lista concatenata non è la struttura dati adatta ai database, te lo dico chiaro e tondo e SENZA nessun intento offensivo: lista concatenata per database = scelta sciocca! ?

Non importa quanto tu possa essere bravo a programmare o iperesperto in C, alla fine ti scontri con l'inefficienza intrinseca di una struttura dati completamente lineare.
Non ci sono database che usano liste perché esse non sono le strutture dati giuste con cui implementarli:
servono strutture molto più complicate, chiamate B*Tree, molto più sofisticate ma immensamente più efficienti nella gestione di grandi quantità di dati. La loro struttura non è lineare ma bilanciata e consentono di fare praticamente tutte le operazioni in tempo logaritmico.
NOTA BENE: chiaramente tu puoi implementare di tutto con le strutture dati con cui ti trovi meglio, ma questo non significa che viene fuori una cosa efficiente.
 
  • 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
Non importa quanto tu possa essere bravo a programmare o iperesperto in C, alla fine ti scontri con l'inefficienza intrinseca di una struttura dati completamente lineare.
Non ci sono database che usano liste perché esse non sono le strutture dati giuste con cui implementare i database:
servono strutture molto più complicate, chiamate B*Tree, molto più sofisticate ma immensamente più efficienti nella gestione di grandi quantità di dati. La loro struttura non è lineare ma bilanciata e consentono di fare praticamente tutte le operazioni in tempo logaritmico.
Tutto chiaro. Infatti probabilmente occorre pensare al design del db in termini di chunk di file per pagina. Salvare i dati nel file assieme alla loro struttura e leggere i file non in forma di tabella ma di Btree. Conosco i Btree e cosa sono da un esame di algoritmi e strutture dati.

Ma non mi capacito come posso "creare una tabella" nella astrazione utilizzando i Btree.​

Ci penso su:
"i Btree sono alberi binari di ricerca bilanciati adatti ad effettuare in maniera efficiente le operazioni di r,w.
Sono bilanciati
Ogni nodo puo contenere un numero n di chiavi e avere n + 1 figli.
Definiscono un ordine cui partire cosichè abbiamo "al piu" m - 1 elementi chiave per nodo e deve "almeno" avere m/2 - 1 elementi. Ogni nodo ha una struttura puntatore,chiave,lettura e le chiavi vengono salvate in maniera ordinata etc.."

Ci sono dei manuali di design di db in cui posso prendere spunto? esempio Sqlite nel codice usa i Btree.
Il mio blocco sta nel fatto che non riesco a trovare una relazione astratta tra BTree e Tabella.

SI puo chiudere il post ma resta a mio avviso interessante.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,210
1,845
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Premetto di aver fatto solo una ricerca sommaria (e non vi ho seguiti fin dall'inizio, non ho letto tutto). Mi soffermo quindi a quanto chiedi qui sopra...
Da una rapida ricerca: How Does a Database Work?
Puoi studiarti https://sqlite.org/index.html

Aggiungo solo che rispetto al codice che ho visto li sopra, puoi fare come suggerito da Andretti. Sono due righe "buttate li", ma credo che anche lui si riferisse a qualcosa di analogo:

C:
enum data_type {no_type, int_type, double_type, char_type};

union data {
    double double_value;
    int int_value;
    char char_value[100];
};

struct {
    union data value;
    enum  data_type type; 
};
 
  • Mi piace
Reazioni: Krona e Andretti60

Andretti60

Utente Èlite
6,440
5,091
è difficile da spiegare. E' senza dubbio uno spreco di spazio. Ma con il linguaggio C

non posso "inniettare" un membro in piu in una struct.​
Certo che non puoi, ma è così che funzionano i database di tipo relazionale, i recordset sono “cablati” quando le tabelle vengono create, mediante appunto lo schema. Se in futuro si vogliono aggiungere o togliere colonne, sono dolori, in quanto occorre riscrivere tutto il database (buona fortuna...) per cui si usano tabelle aggiuntive che si accedono medianti opportune chiavi. Ma è anche quello che rende il database efficiente e veloce. Se vuoi tabelle dinamiche il solo modo è quello di usare un Database noSQL (tipo appunto chiave-valore, come per esempio il Registry di Windows), che usa tutto un altro approccio per renderlo efficiente. Lo puoi fare anche con un database di tipo relazionale, ma le query diventano complicatissime e la velocità fa schifo (ci sono passato di mezzo, lo so)

Il link postato da @DispatchCode è perfetto per capire come funzioni un database nella sua forma essenziale.
 
Ultima modifica:

Andretti60

Utente Èlite
6,440
5,091
Aggiungo solo che rispetto al codice che ho visto li sopra, puoi fare come suggerito da Andretti. Sono due righe "buttate li", ma credo che anche lui si riferisse a qualcosa di analogo:
...
esatto, qualcosa di simile:
C:
struct Membro {
    char key[100];            // l'dentificatore di questo membro, per esemio "autore" (puo anche essere una enumerazione)
    union data value;        // il valore di questo membro
    enum  data_type type;     // il tipo di dato
    struct Membro *next;    // il valore successivo
};
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili