DOMANDA Problemino in c

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
il mio prof di programmazione diceva sempre che nel caso non si conoscesse a prescindere il numero di elementi, la lista é sempre l'unica opzione plausibile, perché l'array puoi farlo anche di 1000 elementi, ma se poi lo usi per uno-due allochi memoria per niente, cosí come se vuoi memorizzare piú di 1000 numeri e allora non ti basta. Sinceramente la lista la vedo come l'opzione piú efficiente in termini di memoria proprio perché viene allocata dinamicamente.

@filoippo97

Allora mi trovo in disaccordo con il tuo docente, o comunque non così d'accordo.

A questo punto è d'uopo una mia spiegazione/motivazione in merito alla divergenza, visto che non siamo in politica (:D) e non è sufficiente, secondo me, non motivare la mia affermazione.



La lista non è l'unica struttura dati allocata dinamicamente, esistono anche gli array dinamici. Due esempi sono std::vector (C++) e java.utils.ArrayList (Java).
L'array viene inizializzato con un determinato numero di elementi (una decina) e poi, quando si raggiunge la dimensione allocata, viene espanso ulteriormente.

In inserimento o rimozione, la linked list è efficiente, considerando l'accesso in un tempo costante (tuttavia vi è dell'overhead dovuto al puntatore).
Le posizioni di un array sono contigue in memoria... quelle di una lista collegata molto probabilmente non lo sono. Questo ha impatti tanto sulla cache, quanto sulla pagine presenti in memoria (nel senso che gli elementi potrebbero trovarsi su più pagine di memoria, per altro anche distanti tra loro, e magari dover essere caricate in quanto non presenti nel TLB o nella MMU).

Ci sono situazioni dove è preferibile utilizzare l'una, ed altre dove è preferibile utilizzare l'altra (e le implementazioni di vector ed ArrayList ne sono una prova).

In questo caso la scelta migliore è un array allocato con calloc e poi l'utilizzo di realloc per allocare memoria aggiuntiva raddoppiando la dimensione precedente dell'array.
 
Ultima modifica:
  • Mi piace
Reazioni: over_coder

filoippo97

Utente Èlite
14,067
7,617
CPU
Intel Core I7 4930K @4.5GHz
Dissipatore
EKWB supremacy nickel
Scheda Madre
ASUS Rampage IV Black Edition
HDD
OCZ vertex 4 512GB | WD RE4 Enterprise Storage 2TB
RAM
16GB Corsair Dominator Platinum 2133MHz cas9 OC @2400MHz 9-11-11-31-2 1.65V
GPU
2-way SLI GTX 780Ti DirectCUII OC
Audio
TEAC UD-503 MUSES + HiFiMan HE-560 V2 + Anaview AMS1000 + Tannoy Revolution XT8F
Monitor
ASUS VG278HR 144Hz 3D 1920x1080p
PSU
Corsair AX1200i Fully sleeved red
Case
Corsair Graphite 760T Arctic White
Periferiche
Corsair K95 | Steelseries Rival
OS
windows 10 Pro
  • Beh, la diffrenza fra un'array dinamico e una listà è parecchia, anche in termini di prestazioni.
  • Il cast è implicito, è necessaio solo in caso si usino vecchissimi compilatori. Il "GNU C Library Reference" dice
  • Per qualcuo che sta imparando a programmare in C è sempre una buona cosa ricordarsi di mettere gli argomenti al main (proprio a livello di apprendiment, così, nel caso debba usarli in un qualche caso più avanti conosca già la sintassi corretta). Inoltre, non è che se non gli impieghi quegli argomenti non esistano...
  • Si preferisce dichiarare le varibili all'inizio delle funzioni proprio per questo caso: immagina di avere un funzione lunga qualche centinaia di righe, se dichiari una varibile in mezzo al programma impiegherai certamente più tempo a trovarla in caso tudebba farci qualcosa, rispetto ad averla all'inizio.
  • NULL è semplicemente una define dello 0, nulla di più. Non mi pareva il caso di introdurre il NULL quando poteva tranquillamente esserev evitato.
  • Tanto è un carattere ascii, lo puoi mettere tranquillamente nella stringa senza disturbare il %c.
  • Le parentesi graffe per i for, if ed else con un'istruzione sola si possono tranquillamente evitare, soprattutto se il codice è identato bene.
  • Ecco come non programare: l'heap non è infinito (tantmeno la memoria disponibile), quando finisci di usare una spazio allocato liberalo sempre.
PS: il codice l'ho provato e andava perfettamente.
PPS: il Deitel non l'ho mai letto, però una volta me l'hanno addirittura sconsigliato.
  • beh prestazioni... non é che lo dobbiamo far girare su uno zilog Z80 :asd: in entrambi i casi a livello operativo la differenza é minima.
  • non é assolutamente vero, tant'é che sia visual studio che dev C++ lo riportano come errore di compilazione e non riescono a compilarlo. E poi cioé, mi vieni a dire di aggiungere gli argomenti al main che in questo caso sono altamente inutili e dai per scontato cose fondamentali come il cast della malloc che senza di quello non funziona?
  • forse l'avró usato una volta nella mia vita :asd: La maggior parte dei programmi che ho scritto hanno main con argomento void.
  • auguri a leggere un grosso programma allora. Se per te andare sulla riga sopra é piú difficile di scrollare tutto il codice...
  • beh se restituisce null, va introdotto anche quello.
  • tant'é vero che mi stampa due barrette anziché il grado.
  • sempre meglio inserirle, alcuni ide lavorano meglio, specie visual studio. Comunque é vero che possono essere anche omesse, ma preferisco sempre aggiungerle, male non fa.
  • certo, ma visto che il programma finisce quando finisce la malloc stessa, non ha senso usare free dal momento che si libera comunque con il termine del programma.
PS: il codice l'ho provato e a me non funziona né in visual studio né in dev C++ :asd:
PPS: Il deitel é il libro di riferimento per il C :asd: ci ho studiato sopra e sono ben pochi i libri fatti cosí bene.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
Finalmente riesco a rispondere, a distanza di una settimana.
A titolo esemplificativo, questo è un modo in cui può essere creato un array dinamico. Al fine di semplificarne la lettura ho evitato i controlli del caso sulla validità dei puntatori.

dynamic_array.h
C:
#ifndef _DYNAMIC_ARRAY
#define _DYNAMIC_ARRAY 1


#define INITIAL_SIZE 10


typedef struct _dynamic_array
{
    int *array;
    int size;
    int tos;
} dynamic_array;


extern void insert(dynamic_array*, int);
extern int  get(dynamic_array*, int);
extern int  size(dynamic_array*);
extern int  capacity(dynamic_array*);

#endif

dynamic_array.c
C:
#include <stdlib.h>

#include "dynamic_array.h"


void insert(dynamic_array *vector, int value)
{
    if(vector->tos >= vector->size)
    {
        int new_size  = vector->size << 1;
        vector->array = realloc(vector->array, new_size*sizeof(int));
        vector->size  = new_size;
    }
   
    vector->array[vector->tos++] = value;
}

int get(dynamic_array *vector, int index)
{
    if(index < vector->tos) return vector->array[index];
    return -1;
}

int size(dynamic_array *vector)
{
    return vector->tos;
}

int capacity(dynamic_array *vector)
{
    return vector->size;
}

dynamic_array_test.c
C:
#include <stdio.h>
#include <stdlib.h>

#include "dynamic_array.h"


int main()
{
    dynamic_array vector;
    vector.array = calloc(INITIAL_SIZE, sizeof(int));
    vector.size  = INITIAL_SIZE;
    vector.tos   = 0;
   
    int i;
    for(i = 0; i<INITIAL_SIZE+9; i++)
    {
        insert(&vector,i);
    }
   
    for(i=0; i<size(&vector); i++)
    {
        printf("%d\n", get(&vector, i));
    }
   
    printf("\n\n");
    printf("Size: %d\n", size(&vector));
    printf("Capacity: %d", capacity(&vector));
   
    return 0;
}
 

rodhellas

Utente Èlite
1,522
427
CPU
Ryzen 5 3600
Dissipatore
GELID Phantom
Scheda Madre
MSI B450 Gaming Plus Max
HDD
500GB m.2 + 2TB HDD
RAM
16GB Corsair LPX 3000mhz
GPU
Gigabyte GTX 960 OC
Audio
Integrata
Monitor
SyncMaster 223BW
PSU
Antec HCG-520M
Case
Meshify C
Net
Gigabit Fastweb
OS
Windows 10 64bit

rodhellas

Utente Èlite
1,522
427
CPU
Ryzen 5 3600
Dissipatore
GELID Phantom
Scheda Madre
MSI B450 Gaming Plus Max
HDD
500GB m.2 + 2TB HDD
RAM
16GB Corsair LPX 3000mhz
GPU
Gigabyte GTX 960 OC
Audio
Integrata
Monitor
SyncMaster 223BW
PSU
Antec HCG-520M
Case
Meshify C
Net
Gigabit Fastweb
OS
Windows 10 64bit
Cosa intendi con "soluzione scolastica"?
Questa è la soluzione che a scuola o all'università si usa all'inizio del corso ( perchè non si è ancora visto puntatori, liste ecc. ) e principalmente per farti usare il for e gli array. Come detto nei commenti precedenti, se metti 51 valori ti darà errore.
 

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili