DOMANDA Problemino in c

Pubblicità

Stefanokj

Utente Attivo
Messaggi
333
Reazioni
7
Punteggio
55
Ciao ragazzi, dovrei fare un programmino in c che acquisisca da tastiera n numeri, calcoli il valore assoluto (senza libreria math), salvi il numero in un vettore di lunghezza n e infine stampi l'intero vettore.
Io l'ho fatto in questo modo:
C:
#include <stdio.h>
int main(){
int q,n,v[q];
printf("Quanti numeri vuoi inserire?\n");
scanf("%d",&q);
for(int i=1;i<=q;i++){
    printf("Inserisci %d numero \n",i);
    scanf("%d",&n);
    if(n<0){
    n=n*-1;  //valore assoluto
    }
    v[i]=n;
}
printf("Vettore: \n");
for(i=1;i<=q;i++){
printf("v[%d]=%d\n",i,v[i]);
}
}

Dove sto sbagliando?
 
Ultima modifica da un moderatore:
Ciao ragazzi, dovrei fare un programmino in c che acquisisca da tastiera n numeri, calcoli il valore assoluto (senza libreria math), salvi il numero in un vettore di lunghezza n e infine stampi l'intero vettore.
Io l'ho fatto in questo modo:
Codice:
#include <stdio.h>
int main(){
int q,n,v[q];
printf("Quanti numeri vuoi inserire?\n");
scanf("%d",&q);
for(int i=1;i<=q;i++){
    printf("Inserisci %d numero \n",i);
    scanf("%d",&n);
    if(n<0){
    n=n*-1;  //valore assoluto
    }
    v[i]=n;
}
printf("Vettore: \n");
for(i=1;i<=q;i++){
printf("v[%d]=%d\n",i,v[i]);
}
}

Dove sto sbagliando?
hai sbagliato in due punti, il primo é che gli array non si possono dichiarare cosí e che se non conosci a prescindere il numero di elementi che vuoi inserire devi usare o una pila o una lista linkata, il secondo punto é che nel secondo ciclo for non hai dichiarato i. Ora vado a mangiare, appena torno ti scrivo il codice giusto :)
 
hai sbagliato in due punti, il primo é che gli array non si possono dichiarare cosí e che se non conosci a prescindere il numero di elementi che vuoi inserire devi usare o una pila o una lista linkata, il secondo punto é che nel secondo ciclo for non hai dichiarato i. Ora vado a mangiare, appena torno ti scrivo il codice giusto :)
Grazie mille!
 
C:
#include <stdio.h>
#define TOP 10
int main(){
int i,n,v[TOP];
printf("Quanti numeri vuoi inserire?\n");
scanf("%d",&q);
for(i=0;i<q;i++){
    printf("Inserisci %d numero \n",i);
    scanf("%d",&n);
    if(n<0){
    n=n*-1;  //valore assoluto
    }
    v[i]=n;
}
printf("Vettore: \n");
for(i=0;i<q;i++){
printf("v[%d]=%d\n",i,v[i]);
}
}
 
Ultima modifica da un moderatore:
Grazie mille!
et vuallá, ho usato una coda per fare un bel programmino, questo chiede quanti numeri vuoi inserire e fa anche alcuni controlli di sicurezza (vedi il controllo sul numero inserito)
C:
#include <stdio.h>
#include <stdlib.h>

//dichiarazione coda
typedef struct numero {
    int num;
    struct numero *nextPtr;
}numero;
typedef numero* NumeroPtr;

//dichiarazione funzioni
void printlist(NumeroPtr sPtr);
int insertnum(NumeroPtr *hPtr, NumeroPtr *tPtr, int number);

int main(void) {

    //all'inizio non ci sono elementi nella coda
    NumeroPtr HeadPtr = NULL;
    NumeroPtr TailPtr = NULL;

    printf("Quanti numeri vuoi inserire?\n");
    int a;
    scanf("%d", &a);

    //controllo di aver inserito un numero consentito
    if (a > 0) {
        int num;
        for (int cycle = 1; cycle <= a; cycle++) {

            printf("inserisci il %d%c numero\n", cycle, 167); //167 é il codice della o di primo in alto, in ascii
            scanf("%d", &num);
            //verifica se il numero é stato inserito correttamente
            int verificainserimento = insertnum(&HeadPtr, &TailPtr, num);

            if (verificainserimento == 1) {
                printf("memory error\n");
            }
        }
    }
    else {
        printf("il numero massimo di numeri che vuoi inserire non é corretto!\n");
    }
    //stampa la lista
    printlist(HeadPtr);
}

    int insertnum(NumeroPtr *hPtr, NumeroPtr *tPtr, int number) {
        NumeroPtr newPtr = (NumeroPtr)malloc(sizeof(numero));

        if (newPtr != NULL) {

            newPtr->num = number;
            newPtr->nextPtr = NULL;
            if (*hPtr == NULL) {
                *hPtr = newPtr;
            }
            else {
                (*tPtr)->nextPtr = newPtr;
            }
            (*tPtr) = newPtr;
            return 0;
        }
        else {
            return 1;
        }
    }

    void printlist(NumeroPtr sPtr) {
        if (sPtr == NULL) {
            printf("the list is empty\n");
        }
        else {
            printf("ecco i valori assoluti dei numeri appena inseriti:\n");
            int printnum, counter = 1;
            while (sPtr != NULL) {

                if (sPtr->num < 0) {
                    printnum = sPtr->num * (-1);
                }
                else {
                    printnum = sPtr->num;
                }
                printf("%d%c numero: %d\n", counter, 167, printnum);
                sPtr = sPtr->nextPtr;
            }
        }
    }
edit: ho letto ora che bisognava salvarlo in modo che venga visualizzato come vettore, beh basta cambiare l'ultima printf in fondo e basta :)
 
Ultima modifica da un moderatore:
Codice:
#include <stdio.h>
#define TOP 10
int main(){
int i,n,v[TOP];
printf("Quanti numeri vuoi inserire?\n");
scanf("%d",&q);
for(i=0;i<q;i++){
    printf("Inserisci %d numero \n",i);
    scanf("%d",&n);
    if(n<0){
    n=n*-1;  //valore assoluto
    }
    v[i]=n;
}
printf("Vettore: \n");
for(i=0;i<q;i++){
printf("v[%d]=%d\n",i,v[i]);
}
}
si ma questo che hai scritto tu se metti un numero oltre 10 va in ovf... dai un occhio al mio, é piú lungo effettivamente, ma contempla tutti i casi, compreso quello in cui non sai quanti numeri puoi inserire come massimo.
 
si ma questo che hai scritto tu se metti un numero oltre 10 va in ovf... dai un occhio al mio, é piú lungo effettivamente, ma contempla tutti i casi, compreso quello in cui non sai quanti numeri puoi inserire come massimo.
Non ci piove, ma credo che stefano non sia ancora arrivato a strutture, puntatori e liste ( suppongo, ha ancora problemi con gli array:giudice: ).
 
Quello di rod in effetti ha un errore; ma la presenza della lista sicuramente non migliora l'efficienza in inserimento, estrazione e ricerca - anzi. Inoltre perdi il vantaggio offerto dall'array.
Sempre se non ci sono dati complessi da gestire è meglio utilizzare un array (di interi in questo caso) e ridimensionarlo all'occorrenza allocando una certa quantità di memoria

In questo caso il problema non si porrebbe nemmeno se si considera il fatto che il numero di elementi viene comunque inserito prima del popolamento dell'array. ;)
 
Quello di rod in effetti ha un errore; ma la presenza della lista sicuramente non migliora l'efficienza in inserimento, estrazione e ricerca - anzi. Inoltre perdi il vantaggio offerto dall'array.
Sempre se non ci sono dati complessi da gestire è meglio utilizzare un array (di interi in questo caso) e ridimensionarlo all'occorrenza allocando una certa quantità di memoria

In questo caso il problema non si porrebbe nemmeno se si considera il fatto che il numero di elementi viene comunque inserito prima del popolamento dell'array. ;)
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.
 
Si, in effetti non ho mai utilizzato code o puntatori...infatti il programma deve essere eseguito con un vettore :/
 
Si, in effetti non ho mai utilizzato code o puntatori...infatti il programma deve essere eseguito con un vettore :/
beh allora l'unico modo per farlo é mettere un numero sufficientemente grosso come dimensione dell'array in modo che si andrá il meno possibile delle volte a raggiungerlo, ad esempio giá 30 puó andare. Comunque quando farai i puntatori e le liste torna a vederti questo esempio e vedrai che é il modo piú giusto per fare l'esercizio rispettando la consegna :sisi:
 
beh allora l'unico modo per farlo é mettere un numero sufficientemente grosso come dimensione dell'array in modo che si andrá il meno possibile delle volte a raggiungerlo, ad esempio giá 30 puó andare. Comunque quando farai i puntatori e le liste torna a vederti questo esempio e vedrai che é il modo piú giusto per fare l'esercizio rispettando la consegna :sisi:
Falso: esistono sempre gli array dinamici. Usare una lista in questo caso è come voler uccidere una formica con una testata nucleare...
Questo è il codice corretto:
C:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){

  int q,n,i;
  int *v;

  printf("Quanti numeri vuoi inserire?\n");
  scanf("%d",&q);

  if(v=malloc(q*sizeof(int))){

    for(i=0;i<q;i++) {
 
        printf("Inserisci %dº numero \n",i+1);
        scanf("%d",&n);
   
        if(n<0)
          n*=-1;  //valore assoluto
   
        v[i]=n;
    }
 
    printf("Vettore: \n");
    for(i=0;i<q;i++)
      printf("v[%d]=%d\n",i,v[i]);
 
    free(v);
  }
  else
    printf("Errore nell\'allocazione della memoria.");

  return 0;
}

Ecco le differenze dal tuo(in ordne di comparsa):
  • Ho include stdlib.h per poter usare la malloc
  • Ho messo gli argmenti al main: è sempre una buona cosa metterli anche se non vengono impiegati
  • Ho dichiarato "i" insieme alle altre varriabili: è una biona consuetudine quando si programma di dichiarare all'inizio della funzione tutte le variabili che verranno usate al suo interno, e non quando iniziano a venir impiegate.
  • "int *v" è la dichiarazione di un puntatore che punta ad un intero: probabilmnete fari i punatori tra poco, quindi ti basta sapere che sono tipi di variabili che contengono l'inidrizzo di una porzione di memoria che contiene altri dati.
  • Ho impiegato una malloc per allocare un arrey di interi di q interi. Funziona cosi: tu gli dai la dimensione dello spazio che ti serve e la malloc ti restituisce il il puntatore dell'inzio di quello spazio. Dato che in realtà quando dchiari un vettore con nomevettore[dimensione] succede la stessa cosa, solo che si alloca lo spazio in una parte diversa della memoria e lo puoi fare solo se sai già a priori la dimensione dell'array. L'if-else serve solo per gestire il caso in cui non sia possibile allocare la memoria necessaria: un buon programma deve sempre gestire queste eccezzioni. Se ti chiedi il perchè di quella "strana" sintassi dell'if funziona cosi: se la malloc non riesce ad allora restituisce 0, che viene assegnato a v; in un'espressione logica, l'operatre = restitisce il valore dell'assegnazione, quindi se la malloc fallisce tutta quell'espressione equivale a 0, che in c è falso (mentre qualsiasi numero diverso da 0 è vero).
  • Solitamente si scorre un array da 0 a dim-1 quindi ho cambiato il ciclo for. PS: se dichiari un array v[5], significa chè è composto da cinque elementi, quindi va da v[0] a v[4] (in c il primo indice è 0).
  • Ho messo una printf un po' più carina :)
  • Ho tolto le prentesi inutili all'if (e l'ho fatto anche dopo) e ho cambiato "n=n*-1" con "n*=-1" (è solo un mio vizio estetico...)
  • Ho cambiato nuovamente il for
  • La funione free() serve per liberare la memoria allocata dinamicamente dopo aver finito di usarla: in un buon pogramma va sempre fatto.
  • Ho aggiunto una printf che ti segnala l'errore
  • Ho aggiunto il return
 
Ultima modifica:
Falso: esistono sempre gli array dinamici. Usare una lista in questo caso è come voler uccidere una formica con una testata nucleare...
Questo è il codice corretto:
Codice:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){

  int q,n,i;
  int *v;

  printf("Quanti numeri vuoi inserire?\n");
  scanf("%d",&q);

  if(v=malloc(q*sizeof(int))){

    for(i=0;i<q;i++) {
  
        printf("Inserisci %dº numero \n",i+1);
        scanf("%d",&n);
    
        if(n<0)
          n*=-1;  //valore assoluto
    
        v[i]=n;
    }
 
    printf("Vettore: \n");
    for(i=0;i<q;i++)
      printf("v[%d]=%d\n",i,v[i]);

  }
  else
    printf("Errore nell\'allocazione della memoria.");

  return 0;
}

Ecco le differenze dal tuo(in ordne di comparsa):
  • Ho include stdlib.h per poter usare la malloc
  • Ho messo gli argmenti al main: è sempre una buona cosa metterli anche se non vengono impiegati
  • Ho dichiarato "i" insieme alle altre varriabili: è una biona consuetudine quando si programma di dichiarare all'inizio della funzione tutte le variabili che verranno usate al suo interno, e non quando iniziano a venir impiegate.
  • "int *v" è la dichiarazione di un puntatore che punta ad un intero: probabilmnete fari i punatori tra poco, quindi ti basta sapere che sono tipi di variabili che contengono l'inidrizzo di una porzione di memoria che contiene altri dati.
  • Ho impiegato una malloc per allocare un arrey di interi di q interi. Funziona cosi: tu gli dai la dimensione dello spazio che ti serve e la malloc ti restituisce il il puntatore dell'inzio di quello spazio. Dato che in realtà quando dchiari un vettore con nomevettore[dimensione] succede la stessa cosa, solo che si alloca lo spazio in una parte diversa della memoria e lo puoi fare solo se sai già a priori la dimensione dell'array. L'if-else serve solo per gestire il caso in cui non sia possibile allocare la memoria necessaria: un buon programma deve sempre gestire queste eccezzioni. Se ti chiedi il perchè di quella "strana" sintassi dell'if funziona cosi: se la malloc non riesce ad allora restituisce 0, che viene assegnato a v; in un'espressione logica, l'operatre = restitisce il valore dell'assegnazione, quindi se la malloc fallisce tutta quell'espressione equivale a 0, che in c è falso (mentre qualsiasi numero diverso da 0 è vero).
  • Solitamente si scorre un array da 0 a dim-1 quindi ho cambiato il ciclo for. PS: se dichiari un array v[5], significa chè è composto da cinque elementi, quindi va da v[0] a v[4] (in c il primo indice è 0).
  • Ho messo una printf un po' più carina :)
  • Ho tolto le prentesi inutili all'if (e l'ho fatto anche dopo) e ho cambiato "n=n*-1" con "n*=-1" (è solo un mio vizio estetico...)
  • Ho cambiato nuovamente il for
  • La funione free() serve per liberare la memoria allocata dinamicamente dopo aver finito di usarla: in un buon pogramma va sempre fatto.
  • Ho aggiunto una printf che ti segnala l'errore
  • Ho aggiunto il return
Hai usato anche te i puntatori e funzioni che non ha fatto... hai semplicemente rigirato il mio codice senza usare la struct in alto, ma alla fine il principio é quello :asd:
Inoltre, ti sei assicurato che funzioni il codice? Non mi pare :asd: La malloc va assegnata al giusto tipo di dato, perché di per sé cosí come é scritta assegna un void a un int causando un errore. Pertanto il codice corretto é questo:
if (v = (int*)malloc(q * sizeof(int)))
per il resto:
  • ho incluso anche io stdlib.h ovviamente, altrimenti non avrei potuto usare la malloc
  • se non vengono impiegati non ha senso, é preferibile usare void
  • sbagliatissimo. E questa é la cosa peggiore che hai scritto. Per la mantenibilitá del codice é fondamentale dichiarare le variabili prima di usarle, immaginati di avere un programma molto piú grosso e doverti andare a cercare variabile per variabile all'inizio. Non esiste, ed é specificato anche a lettere cubitali sul Deitel.
  • si beh, non é poi cosí facile per lui capire da quello che hai scritto cosa é un puntatore, é la cosa piú difficile del c l'aritmetica dei puntatori... Semmai suggerisco un buon libro per studiarsi come funzionano, il Deitel sopra menzionato é perfetto.
  • si beh non é proprio cosí... se la malloc fallisce restituisce NULL, non 0. Sono due cose diverse, uno é un numero, l'altro é il niente. Infatti guarda il mio codice, nell'if ho messo newPtr != NULL.
  • e qua siamo d'accordo
  • Nella printf della richiesta del numero hai sbagliato che dovevi indicare la o di grado in alto non nella stringa da stampare ma come carattere ascii numerico (vedi mio codice) oppure usare un comando all'inizio come setlocale(LC_ALL, "") e includendo <locale.h>
  • non ho capito bene a quali parentesi ti riferisci, ma ad ogni modo non sono mai inutili. Il mio prof diceva "meglio una parentesi inutile in piú che un errore".
  • e va bene
  • no. La funzione free serve ad esempio per eliminare nodi da liste linkate. Una volta che termini il programma la memoria si libera di default, quindi non serve specificarlo.
  • ok, l'abbiamo giá detto
  • e va bene.
Rimango dell'opinione che il testo cosí come é scritto si presta per l'utilizzo di code.
 
Hai usato anche te i puntatori e funzioni che non ha fatto... hai semplicemente rigirato il mio codice senza usare la struct in alto, ma alla fine il principio é quello :asd:
Inoltre, ti sei assicurato che funzioni il codice? Non mi pare :asd: La malloc va assegnata al giusto tipo di dato, perché di per sé cosí come é scritta assegna un void a un int causando un errore. Pertanto il codice corretto é questo:
if (v = (int*)malloc(q * sizeof(int)))
per il resto:
  • ho incluso anche io stdlib.h ovviamente, altrimenti non avrei potuto usare la malloc
  • se non vengono impiegati non ha senso, é preferibile usare void
  • sbagliatissimo. E questa é la cosa peggiore che hai scritto. Per la mantenibilitá del codice é fondamentale dichiarare le variabili prima di usarle, immaginati di avere un programma molto piú grosso e doverti andare a cercare variabile per variabile all'inizio. Non esiste, ed é specificato anche a lettere cubitali sul Deitel.
  • si beh, non é poi cosí facile per lui capire da quello che hai scritto cosa é un puntatore, é la cosa piú difficile del c l'aritmetica dei puntatori... Semmai suggerisco un buon libro per studiarsi come funzionano, il Deitel sopra menzionato é perfetto.
  • si beh non é proprio cosí... se la malloc fallisce restituisce NULL, non 0. Sono due cose diverse, uno é un numero, l'altro é il niente. Infatti guarda il mio codice, nell'if ho messo newPtr != NULL.
  • e qua siamo d'accordo
  • Nella printf della richiesta del numero hai sbagliato che dovevi indicare la o di grado in alto non nella stringa da stampare ma come carattere ascii numerico (vedi mio codice) oppure usare un comando all'inizio come setlocale(LC_ALL, "") e includendo <locale.h>
  • non ho capito bene a quali parentesi ti riferisci, ma ad ogni modo non sono mai inutili. Il mio prof diceva "meglio una parentesi inutile in piú che un errore".
  • e va bene
  • no. La funzione free serve ad esempio per eliminare nodi da liste linkate. Una volta che termini il programma la memoria si libera di default, quindi non serve specificarlo.
  • ok, l'abbiamo giá detto
  • e va bene.
Rimango dell'opinione che il testo cosí come é scritto si presta per l'utilizzo di code.
  • 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
    You can store the result of malloc into any pointer variable without a cast, because ISO C automatically converts the type void * to another type of pointer when necessary. But the cast is necessary in contexts other than assignment operators or if you might want your code to run in traditional C.
  • 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.
 
Pubblicità
Pubblicità
Indietro
Top