[C] Conversione binario decimale

floppyes
Ciao a tutti!
Sono alle prese con questo nuovo esercizio di programmazione in C in cui non mi tornano alcune cose. So che in internet ci sono un sacco di esempi già pronti, però ho provato a realizzarne uno io e la conversione non torna :-D
#include <stdio.h>
#include <math.h>
void scambia(int *);
int main()
{
int binario[4], i, conv=0, pot=0, nuovo[4];
int *pi;
pi = binario;
printf("Inserisci i singoli numeri del codice binario uno per volta:\n");
// L'utente inserisce i singoli numeri del suo codice binario
for (i=0;i<4;i++)
{
printf("==> ");
scanf("%d", &binario[i]);
// Se i numeri immessi sono diversi da 0 e 1 allora deve inserire nuovamente il numero
if (binario[i]!=0 && binario[i]!=1)
{
i--;
}
}
// Scambio gli elementi del vettore per riuscire a convertire correttamente il numero
scambia(pi);
for (i=0;i<4;i++)
{
nuovo[i]=binario[i];
}
// Funzione di debug per verificare che lo scambio sia stato effettuato correttamente
printf("\nNuovo binario inserito:\t");
for (i=0;i<4;i++)
{
printf("%d", nuovo[i]);
}
// Eseguo la conversione utilizzando la funzione pow del file <math.h>
for (i=0;i<4;i++)
{
if (binario[i]==1)
{
pot = pow (2,i);
conv=conv+pot;
}
}
// Stampo il numero convertito in decimale
printf("\nEcco il numero converito: %d", conv);
return 0;
}
// Dichiaro la funzione scambio
void scambia(int *p)
{
int temp;
int i;
for (i=0;i<4;i++)
{
temp = p[0+i];
p[i] = p[3-i];
p[3-i] = temp;
}
}

L'utente inserisce le cifre del numero binario (in questo caso fino a 4 cifre). Il programma scambia gli elementi acquisiti ed esegue la conversione utilizzando la funzione
pow(x,y)
della libreria
math.h

Ho aggiunto la funzione chiamata
scambia
perchè altrimenti se l'utente inserisce:
1100
al posto di avere 12 ottiene 3, a causa dell'ordine dei numeri nel vettore.
Se provo ad eseguire il codice ed inserire la sequenza
1100
ottengo sempre 3 al posto di 12.

Dov'è l'errore? :D
Grazie mille
Ciaoo!

Risposte
Atem1
Se inserisci 1100 non risulta 12 ma 3 (cioè 0011)
Se inserisci 1000 non risulta 8 ma 1 (cioè 0001)
Se inserisci 0010 non risulta 2 ma 4 (cioè 0100)

Il motivo è che non hai scambiato nulla.

L'errore e' qui;
"floppyes":

for (i=0;i<4;i++)


Devi scrivere i<2 e non i<4 altrimenti fai lo scambio due volte ed è come se non avessi scambiato nulla.

floppyes
Ciao Atem!
Grazie mille.. in effetti non ci avevo pensato!!
Altra domanda :D
Mettiamo il caso che sia l'utente a decidere quanto è lungo il vettore, in quel caso allora modifico il codice in questo modo:
#include <stdio.h>
#include <math.h>

void scambia(int *);
int main()
{
    int dim;
    printf("Quanto è lungo il tuo codice binario? ");
    scanf("%d", &dim);
    int binario[dim], i, conv=0, pot=0, nuovo[dim];    
    int *pi;
    pi = binario;
    
    printf("Inserisci i singoli numeri del codice binario uno per volta:\n");
    
    // L'utente inserisce i singoli numeri del suo codice binario
    for (i=0;i<dim;i++)
    {
        printf("==> ");
        scanf("%d", &binario[i]);
        // Se i numeri immessi sono diversi da 0 e 1 allora deve inserire nuovamente il numero
        if (binario[i]!=0 && binario[i]!=1)
        {
            i--;
        }
    }

    // Scambio gli elementi del vettore per riuscire a convertire correttamente il numero
    scambia(pi);
    for (i=0;i<dim;i++)
    {
        nuovo[i]=binario[i];
    }
    
    // Funzione di debug per verificare che lo scambio sia stato effettuato correttamente
    printf("\nNuovo binario inserito:\t");
    for (i=0;i<dim;i++)
    {
        printf("%d", nuovo[i]);
    }   
    
    // Eseguo la conversione utilizzando la funzione pow del file <math.h>
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            pot = pow (2,i);
            conv=conv+pot;    
        }
    }
    
    // Stampo il numero convertito in decimale
    printf("\nEcco il numero converito: %d", conv);
    return 0;
}

// Dichiaro la funzione scambio
void scambia(int *p)
{
    int temp;
    int i;
    for (i=0;i<(dim/2);i++)
    {
        temp = p[0+i];
        p[i] = p[(dim-1)-i];
        p[(dim-1)-i] = temp;
    }
}


Tutto funziona bene tranne il pezzo del void, perchè non tiene in memoria la dimensione dim acquisita all'interno del
int main ()

Sai se esiste un modo per mantenere in memoria la dimensione dim anche nel void? Così da fare lo scambio all'interno del vettore e convertire poi il numero.
Grazie
Ciao :)

Atem1
dim è un parametro che devi passare alla procedura.

scambia(pi);
diventa
scambia(pi, dim);

E poi la funzione e'
void scambia(int *p, int dim)

Ovviamente devi modificare anche il prototipo.

floppyes
Grazie mille ora funziona alla perfezione!! :D

Devo ricordarmi allora di utilizzare questo metodo per richiamare le variabili anche nelle altre funzioni!

Grazie mille per l'aiuto
Ciaoo :)

floppyes
Ciao!

Una sola domanda. Nel caso in cui la sequenza di numeri inserita sia in complemento a due, allora dovrò scambiare tutti i numeri del vettore, se 0 mettere 1 e se 1 mettere 0, e poi sottrarre 1 al nuovo vettore?

Grazie
Ciaoo :)

Atem1
Se il primo bit è uno 0 allora il numero è positivo e non devi fare niente.

Se il primo bit è un 1 allora il numero è negativo.
In questo caso prima devi sottarre uno, e poi complementare tutti i bit in modo da ottenere il corrispondente numero positivo.
Oppure (sempre che il primo bit sia 1) puoi fare come c'è scritto su Wikipedia e cioè prima complementi tutti i bit e poi sommi 1:
http://it.wikipedia.org/wiki/Complement ... ento_a_due

floppyes
Ciao!

Perfetto grazie mille, ora finisco l'altro esercizio e poi completo questo :D perchè la richiesta era proprio in complemento a due!

Grazie
Ciaoo :)

floppyes
Ciao!

Ho provato a riscrivere il codice:
/*
Programma che serve a convertire un numero binario in decimale. L'utente inserisce la lunghezza del numero e poi ogni singola cifra. Tema esame di Guida.
*/

#include <stdio.h>
#include <math.h>

void scambia(int *p, int dim);
int main()
{
    int dim;
    // Qui definisco quanto è lungo il mio codice
    printf("Quanto è lungo il tuo codice binario? ");
    scanf("%d", &dim);
    int binario[dim], i, conv=0, pot=0, nuovo[dim];    
    // Questo mi serve per scambiare i numeri del vettore in modo da convertirlo giusto
    int *pi;
    pi = binario;
    
    printf("Inserisci i singoli numeri del codice binario uno per volta:\n");
    
    // L'utente inserisce i singoli numeri del suo codice binario
    for (i=0;i<dim;i++)
    {
        printf("==> ");
        scanf("%d", &binario[i]);
        // Se i numeri immessi sono diversi da 0 e 1 allora deve inserire nuovamente il numero
        if (binario[i]!=0 && binario[i]!=1)
        {
            i--;
        }
    }

    // Scambio gli elementi del vettore per riuscire a convertire correttamente il numero
    
    if (binario[0]==1)
    {
        printf("\nComplemento a due:\n");
        for (i=0;i<dim;i++)
        {
            if (binario[i]==1)
            {
                binario[i]=0;
            } 
            else (binario[i]=1);
        }
        for (i=0;i<dim;i++)
        {
            binario[i]=binario[i]+1;
        }
        for (i=0;i<dim;i++)
        {
            if (binario[i]==1)
            {
                binario[i]=0;
            } else (binario[i]=1);
        }
        for (i=0;i<dim;i++)
        {
            printf("%d", binario[i]);
        }
    }
    scambia(pi,dim);
    for (i=0;i<dim;i++)
    {
        nuovo[i]=binario[i];
    }
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            pot = pow (2,i);
            conv=conv+pot;    
        }
    }
    
    if (binario[0]==0)
    {
        printf("\n\nIl numero in decimale equivale a : -%d", conv);
    } else (printf("\n\nIl numero in decimale equivale a : %d", conv));
    
    return 0;
}


// Dichiaro la funzione scambio che mi serve per fare in modo che il vettore sia nella posizione giusta
void scambia(int *p, int dim)
{
    int temp;
    int i;
    for (i=0;i<(dim/2);i++)
    {
        temp = p[0+i];
        p[i] = p[(dim-1)-i];
        p[(dim-1)-i] = temp;
    }
}


Nel mio esercizio viene chiesto di immettere il seguente numero di 16bit:
1110111100001101

Il risultato è di -4339, mentre a me esce -4338.

Secondo te il codice è giusto? Perchè mi sa che il passaggio in cui vado a sommare 1 non è molto corretto :D

Grazie mille
Ciaoo!

Atem1
Io crerei 3 funzioni

1-scambia (l'hai già fatta)
2-complementa (l'hai scritta nel MAIN, ma sarebbe più elegante avere una procedura/funzione apposta)
3-converti (idem)

Poi nel MAIN farei così:

1.Inserisci il numero.
2.usa la funzione scambia.

3.
Se binario[dim-1]==0 //(cioè se il numero è positivo)
     a.converti
Altrimenti: //(cioè se il numero è negativo)
    a.complementa
    b.converti
    c.Al numero decimale ottenuto, somma 1


4.Visualizza il numero decimale ottenuto.

floppyes
Ciao!

Grazie mille ora provo a riscrivere il codice come mi hai suggerito. Solo una domanda, quando vado ad aggiungere 1, come posso fare per calcolare ed aggiungere i riporti?

Ad esempio, se immetto il numero:
0100

Lo complemento:
1011

Aggiungo 1:
1100


Nel terzo passaggio come posso fare per tenere conto del riporto?

Grazie mille
Ciaoo :)

Atem1
Se rileggi quello che ho scritto vedrai che non c'è nessun bisogno di tener conto dei riporti...
1 lo sommi al corrispettivo decimale, non c'è bisogno di sommarlo al binario, è solo complicarsi la vita per niente...

floppyes
Ciao Antem!

Ammetto che le funzioni non le ho ancora capite bene bene :D potrebbe andare bene questo codice per quanto riguarda le funzioni?

Perchè ho provato ad inserire un numero ma ho sempre 0 come risultato finale.
#include <stdio.h>
#include <math.h>

void scambia(int *p, int dim);
void complementa(int*comp, int dim, int binario[dim]);
void converti(int*conve, int dim, int binario[dim], int pot, int conv);
int main()
{
    int dim;
    printf("Quanto è lungo il tuo codice binario? ");
    scanf("%d", &dim);
    
    int binario[dim], i, conv=0, pot=0, nuovo[dim];    

    // Richiami alle funzioni void
    int *pi;
        pi = binario;
    int *comp;
        comp = binario;
    int *conve;
        conve = binario;
    
    printf("Inserisci i singoli numeri del codice binario uno per volta:\n");
    
    // L'utente inserisce i singoli numeri del suo codice binario
    for (i=0;i<dim;i++)
    {
        printf("==> ");
        scanf("%d", &binario[i]);
        // Se i numeri immessi sono diversi da 0 e 1 allora deve inserire nuovamente il numero
        if (binario[i]!=0 && binario[i]!=1)
        {
            i--;
        }
    }

    // Scambio gli elementi del vettore per riuscire a convertire correttamente il numero
    
    if (binario[dim-1]==0)
    {
        converti (conve,dim,&binario[dim],pot,conv);
    }
    printf("Numero convertito: %d", conv);

    if (binario[dim-1]!=0)
    {
        complementa (comp,dim,&binario[dim]);
        converti (conve,dim,&binario[dim],pot,conv);
        conv+=1;
    }
    printf("Numero convertito: %d\n", conv);
    
    return 0;
}


// Elenco tutte le funzioni di cui ho bisogno
// Funzione scambia
void scambia(int *p, int dim)
{
    int temp;
    int i;
    for (i=0;i<(dim/2);i++)
    {
        temp = p[0+i];
        p[i] = p[(dim-1)-i];
        p[(dim-1)-i] = temp;
    }
}

// Funzione complementa
void complementa(int*comp, int dim, int binario[dim])
{
    int i;
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            binario[i]=0;
        } 
        else (binario[i]=1);
    }
}

// Funzione converti
void converti(int*conve, int dim, int binario[dim], int pot, int conv)
{
    int i;
    for (i=0;i<dim;i++)
        {
            if (binario[i]==1)
            {
                pot = pow (2,i);
                conv=conv+pot;    
            }
        }
}


Grazie mille
Ciaoo!

Atem1
Alle funzioni/procedure devi passare solamente i parametri necessari.
Ad esempio, le tue 3 funzioni hanno bisogno di ricevere dal MAIN solamente 2 parametri: il vettore, e la dimensione del vettore. Il resto puoi dichiararlo internamente visto che sono cose che non ti servono nelle future istruzioni del MAIN.
Nel MAIN devi mettere solo le cose che servono, e così vale anche per le funzioni.

Te l'ho corretto:

#include <stdio.h>
#include <math.h>

void scambia(int *p, int dim);
void complementa(int binario[], int dim);
int converti(int binario[], int dim);

int main()
{
    int dim;
    printf("Quanto è lungo il tuo codice binario? ");
    scanf("%d", &dim);

    int binario[dim], i, conv;

    printf("Inserisci i singoli numeri del codice binario uno per volta:\n");

    // L'utente inserisce i singoli numeri del suo codice binario
    for (i=0;i<dim;i++)
    {
        printf("==> ");
        scanf("%d", &binario[i]);
        // Se i numeri immessi sono diversi da 0 e 1 allora deve inserire nuovamente il numero
        if (binario[i]!=0 && binario[i]!=1)
        {
            i--;
        }
    }

    scambia(binario, dim);
    // Scambio gli elementi del vettore per riuscire a convertire correttamente il numero

    if (binario[dim-1]==0)
    {
        conv=converti (binario, dim);
    }
    else
    {
        complementa (binario, dim);
        conv=converti (binario, dim);
        conv+=1;
        conv*=-1;
    }

    printf("Numero convertito: %d\n", conv);

    return 0;
}


// Elenco tutte le funzioni di cui ho bisogno
// Funzione scambia
void scambia(int *p, int dim)
{
    int temp;
    int i;
    for (i=0;i<(dim/2);i++)
    {
        temp = p[i];
        p[i] = p[(dim-1)-i];
        p[(dim-1)-i] = temp;
    }
}

// Funzione complementa
void complementa(int binario[], int dim)
{
    int i;
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            binario[i]=0;
        }
        else (binario[i]=1);
    }
}

// Funzione converti
int converti(int binario[], int dim)
{
    int pot;
    int conv=0;
    int i;
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            pot = pow (2,i);
            conv=conv+pot;
        }
    }
    return conv;

}


Inoltre il risultato finale va visualizzato dopo l'IF altrimenti visualizzi due cose e non una.
Comunque guarda quello che ti ho corretto, riflettici bene, e poi se c'è qualcosa che non hai capito, chiedi.

vict85
Solo un piccolo commento:

In questo estratto del tuo codice
int dim;
// Qui definisco quanto è lungo il mio codice
printf("Quanto è lungo il tuo codice binario? ");
scanf("%d", &dim);
int binario[dim], i, conv=0, pot=0, nuovo[dim];
[...]
stai volutamente usando i variable lenght array del c99-c11 oppure stai dando per scontato che il tuo codice usi le estensioni del c90 di gcc?

Questo opzione degli ultimi due standard del C non sono supportati da tutti i compilatori e il loro uso è spesso criticato. Detto questo, in questo programma, dato la dimensione limitata di dim, l'uso dei VLA è considerato accettabile e talvolta anche consigliato. Sinceramente trovo però che il suo uso vada fatto sempre consapevolmente. Il suo uso sconsiderato è infatti sempre da evitare.

Ho notato che Atem non l'ha corretto nel suo codice. Le alternative sono o l'allocazione dinamica o una dimensione fissa prefissata. Considerando il tipo di problema direi che l'uso di una dimensione fissa (di 32 o 64) sia accettabile.

--------------------------

Una cosa un po' più grave consiste nell'uso di int senza fare alcun controllo sul fatto o meno che un int possa contenere l'array di bit considerato. Un codice più ragionato userebbe la libreria stdint.h (o inttypes.h se hai bisogno di usare le macro per printf) introdotta negli ultimi standard o, alternativamente, controlli i limiti attraverso la libreria limits.h

-------------------------

Sarebbe infine secondo me più sensato caricare i bit come stringa di caratteri e interpretarla. Così sei invece costretto a dividere le varie cifre.

floppyes
"Atem":
Alle funzioni/procedure devi passare solamente i parametri necessari.
Ad esempio, le tue 3 funzioni hanno bisogno di ricevere dal MAIN solamente 2 parametri: il vettore, e la dimensione del vettore. Il resto puoi dichiararlo internamente visto che sono cose che non ti servono nelle future istruzioni del MAIN.
Nel MAIN devi mettere solo le cose che servono, e così vale anche per le funzioni.
Te l'ho corretto:
Inoltre il risultato finale va visualizzato dopo l'IF altrimenti visualizzi due cose e non una.
Comunque guarda quello che ti ho corretto, riflettici bene, e poi se c'è qualcosa che non hai capito, chiedi.


Ciao Atem!

Grazie per la risposta! Ora confrontando il tuo codice con la teoria sulle funzioni mi è già più chiaro :smt023
Solo due domande sul codice che hai scritto:
Nelle prime righe
void complementa(int binario[], int dim);
int converti(int binario[], int dim);

non bisognerebbe dichiarare la dimensione del vettore binario? oppure posso lasciarla anche "vuota"?

Alla riga 37 poi non ho capito questo passaggio:
    else
    {
        complementa (binario, dim);
        conv=converti (binario, dim);
        conv+=1;
        conv*=-1;
    }


Che funzione ha il
conv*=-1;
?

Infine come mai nella funzione converti hai utilizzato
int converti(int binario[], int dim)

Al posto della funzione void? Inoltre il return va inserito solamente nella dichiarazione dell'int?

Grazie mille come sempre per l'ottimo aiuto! :D

"vict85":
Solo un piccolo commento:

In questo estratto del tuo codice
int dim;
// Qui definisco quanto è lungo il mio codice
printf("Quanto è lungo il tuo codice binario? ");
scanf("%d", &dim);
int binario[dim], i, conv=0, pot=0, nuovo[dim];
[...]
stai volutamente usando i variable lenght array del c99-c11 oppure stai dando per scontato che il tuo codice usi le estensioni del c90 di gcc?

Questo opzione degli ultimi due standard del C non sono supportati da tutti i compilatori e il loro uso è spesso criticato. Detto questo, in questo programma, dato la dimensione limitata di dim, l'uso dei VLA è considerato accettabile e talvolta anche consigliato. Sinceramente trovo però che il suo uso vada fatto sempre consapevolmente. Il suo uso sconsiderato è infatti sempre da evitare.

Ho notato che Atem non l'ha corretto nel suo codice. Le alternative sono o l'allocazione dinamica o una dimensione fissa prefissata. Considerando il tipo di problema direi che l'uso di una dimensione fissa (di 32 o 64) sia accettabile.

--------------------------

Una cosa un po' più grave consiste nell'uso di int senza fare alcun controllo sul fatto o meno che un int possa contenere l'array di bit considerato. Un codice più ragionato userebbe la libreria stdint.h (o inttypes.h se hai bisogno di usare le macro per printf) introdotta negli ultimi standard o, alternativamente, controlli i limiti attraverso la libreria limits.h

-------------------------

Sarebbe infine secondo me più sensato caricare i bit come stringa di caratteri e interpretarla. Così sei invece costretto a dividere le varie cifre.


Ad essere sincero lo sto utilizzando inconsapevolmente :oops: In esercizi svolti in classe ho visto che alcune volte viene utilizzato questo metodo, anche se di solito le variabili vengono definite mediante il
#define dim1 2


Quindi per evitare problemi sarebbe meglio utilizzare l'allocazione dinamica? In questo caso il codice che ho riscritto ora potrebbe andare bene?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void scambia(int *p, int dim);
void complementa(int binario[], int dim);
int converti(int binario[], int dim);

int main()
{
    int dim;
    printf("Quanto è lungo il tuo codice binario? ");
    scanf("%d", &dim);

    int *binario = malloc(dim*sizeof(int*)); 
    int i, conv;

    printf("Inserisci i singoli numeri del codice binario uno per volta:\n");

    // L'utente inserisce i singoli numeri del suo codice binario
    for (i=0;i<dim;i++)
    {
        printf("==> ");
        scanf("%d", &binario[i]);
        // Se i numeri immessi sono diversi da 0 e 1 allora deve inserire nuovamente il numero
        if (binario[i]!=0 && binario[i]!=1)
        {
            i--;
        }
    }

    scambia(binario, dim);
    // Scambio gli elementi del vettore per riuscire a convertire correttamente il numero

    if (binario[dim-1]==0)
    {
        conv=converti (binario, dim);
    }
    else
    {
        complementa (binario, dim);
        conv=converti (binario, dim);
        conv+=1;
        conv*=-1;
    }

    printf("Numero convertito: %d\n", conv);

    free(binario);

    return 0;   
}


// Elenco tutte le funzioni di cui ho bisogno
// Funzione scambia
void scambia(int *p, int dim)
{
    int temp;
    int i;
    for (i=0;i<(dim/2);i++)
    {
        temp = p[i];
        p[i] = p[(dim-1)-i];
        p[(dim-1)-i] = temp;
    }
}

// Funzione complementa
void complementa(int binario[], int dim)
{
    int i;
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            binario[i]=0;
        }
        else (binario[i]=1);
    }
}

// Funzione converti
int converti(int binario[], int dim)
{
    int pot;
    int conv=0;
    int i;
    for (i=0;i<dim;i++)
    {
        if (binario[i]==1)
        {
            pot = pow (2,i);
            conv=conv+pot;
        }
    }
    return conv;

}


Infine per caricare i bit come stringa di caratteri, devo utilizzare la funzione getchar? Vorrei imparare ad utilizzarla perchè in tutti gli esercizi viene chiesto di immettere stringhe di caratteri.

Grazie anche a te per l'aiuto :)
Buona serata!
Ciaoo!

Atem1
"floppyes":

non bisognerebbe dichiarare la dimensione del vettore binario? oppure posso lasciarla anche "vuota"?

In C, quando si passano gli argomenti (variabili) alle funzioni, bisogna prestare attenzione al passaggio di array ad una o più dimensioni; la regola dice che la prima dimensione dell’array può non essere specificata, mentre la seconda e le altre devono esserlo.
http://www.html.it/pag/15409/le-funzioni/


Che funzione ha il
conv*=-1;
?


La funzione di conversione ti restituisce il modulo del numero decimale, quindi dato che il primo bit è 1, sappiamo che il nostro numero decimale è negativo, e per trasformare un numero positivo nel suo opposto dobbiamo moltiplicare per -1.
conv=-1 * conv


Infine come mai nella funzione converti hai utilizzato
int converti(int binario[], int dim)

Al posto della funzione void? Inoltre il return va inserito solamente nella dichiarazione dell'int?


Per convenzione chiamiamo "procedure" le funzioni che non restituiscono nessun valore, cioè le funzioni di tipo "void".
Ma le funzioni in senso stretto sono quelle che restituiscono un valore e questo valore puo' essere di qualsiasi tipo:
int, char, float, "nuovo_tipo" (cioè i nuovi_tipi che crei col typedef) etc. etc.
Nel nostro caso la funzione converti doveva trasformare un numero dal binario al decimale quindi chiaramente restituiva un valore per cui l'ho dichiarata "int".
Comunque avrei anche potuto dichiararla "void" e fornire un ulteriore parametro passato per indirizzo....


Quando si raggiunge un’istruzione “return“, il controllo del programma ritorna a chi ha chiamato la funzione. Il valore ritornato è quello posto dopo la parola return;se si chiude la funzione prima di mettere un’istruzione “return“, la funzione ritorna automaticamente, ed il valore ritornato potrebbe non avere un significato valido.
[...]
Una funzione void non deve contenere necessariamente un’istruzione return, anche se essa può essere usata per uscire dalla funzione in maniera opportuna, un po’ come l’uso del “break” all’interno dei cicli.
http://www.html.it/pag/15409/le-funzioni/

In ogni caso ti consiglio di studiare la teoria da qualche guida, risparmi tempo ed impari meglio.
Ehm diciamo che non sono molto bravo a spiegare la teoria perchè fino al... 25 Luglio... non sapevo nulla di C.
Io mi sono letto queste 2 guide:
http://www.html.it/guide/guida-c/
http://blacklight.gotdns.org/guidac.pdf

La prima è molto sintetica e si fa in poche ore, ti spiega tutti i fondamentali del C (uso delle funzioni, liste, files etc..).
La seconda è un pò più approfondita (nel senso che spiega più cose e nel dettaglio, ma è anche più facile rispetto alla prima che è molto stringata) ma è molto molto utile secondo me... (penso che t'interessi fino a pag.146)
Secondo me faresti bene a guardartele, faresti passi da gigante...
Poi, ripeto, entrambe spiegano solo i "fondamentali" infatti, ad esempio, gli alberi non sono spiegati in nessuna delle 2 guide, ma secondo me queste 2 guide sono comunque utili per farsi delle buone fondamenta...

floppyes
Ciao Atem!

Grazie mille per le guide, il secondo pdf mi sembra ottimo perchè spiega tutte le basi. Ora lo studio per bene e ti faccio sapere :D

Grazie ancora
Ciaoo!

floppyes
Ciao!

Volevo provare a realizzare lo stesso programma però utilizzando la conversione in caratteri come suggerito da vict85, in modo da poter immettere tutti i numeri in un solo colpo.

Per fare questa cosa mi conviene utilizzare la funzione fgets() e utilizzale la funzione realloc in modo da allocare la memoria in base a quanti numeri vengono inseriti?

Grazie
Ciao :)

Atem1
Intanto devi avere ben chiaro il motivo per cui vuoi dichiarare la variabile che conterrà il tuo valore binario (es: "1100") di tipo "array di caratteri" piuttosto che di tipo int. E il motivo è che gli interi hanno un limite, quindi se tu dichiarassi la tua variabile di tipo int, ad esempio non potresti convertire "11110101010100101010100" cosa che invece puoi fare dichiarandolo come array di caratteri.
I limiti di ogni tipo li puoi scoprire così:

#include <stdio.h>
#include <limits.h>

int main()
{

   printf("The number of bits in a byte %d\n", CHAR_BIT);

   printf("The minimum value of SIGNED CHAR = %d\n", SCHAR_MIN);
   printf("The maximum value of SIGNED CHAR = %d\n", SCHAR_MAX);
   printf("The maximum value of UNSIGNED CHAR = %d\n", UCHAR_MAX);

   printf("The minimum value of SHORT INT = %d\n", SHRT_MIN);
   printf("The maximum value of SHORT INT = %d\n", SHRT_MAX); 

   printf("The minimum value of INT = %d\n", INT_MIN);
   printf("The maximum value of INT = %d\n", INT_MAX);

   printf("The minimum value of CHAR = %d\n", CHAR_MIN);
   printf("The maximum value of CHAR = %d\n", CHAR_MAX);

   printf("The minimum value of LONG = %ld\n", LONG_MIN);
   printf("The maximum value of LONG = %ld\n", LONG_MAX);
  
   return(0);
}



http://www.tutorialspoint.com/c_standar ... mits_h.htm


Sulle stringhe, dipende da quello che vuoi fare.

char s1[100]; //l'array di caratteri è stato dichiarato staticamente quindi la dimensione massima sarà 100
char *s2; //qui l'allocazione è dinamica e devi usare malloc: la sua dimensione è decisa nel corso del programma tramite, malloc e realloc

Se usi l'allocazione dinamica devi scrivere
#include <malloc.h>


Per usare le funzioni delle stringhe (es: strcpy) devi scrivere
#include <string.h>


La fgets serve per le leggere un numero massimo di caratteri.
es:
fgets(s1,100,stdin) legge al più 100 caratteri e li mette in s1 quindi se tu digiti 120 caratteri ti prende solo i primi 100.
Se usi la fgets devi mettere il limite massimo di caratteri.

Se usi la scanf
scanf ("%s" , s1);
Legge i caratteri digitati fino al primo spazio.

Se vuoi leggere fino all'invio puoi usare
scanf("%[^\n]", s1);
Ma solitamente si usa comunque la fgets() quindi quella scrittura è praticamente inutile.

In questo caso dentro s1 verrà memorizzato anche l'invio. Quindi hai la stringa con "\n" incluso.
Invece diventa utile se vuoi leggere fino a un carattere determinato, ad esempio se vuoi leggere fino a "#" (escluso) è:
scanf("%[^#]", s1);

Invece per l'allocazione dinamica dinamica è sempre il solito procedimento.
Se non conosci dall'inizio la dimensione della stringa, puoi inserire un carattere alla volta usando la realloc.
Ma devi sempre ricordarti di allocare uno spazio in più rispetto alla sua dimensione effettiva perchè bisogna memorizzare anche il carattere di fina stringa. L'inserimento termina quando l'utente ha premuto INVIO. "\n".

char *get_string()
{

   char *s=malloc(1);
   char ch;
   int dim=0;

   while ((ch=getchar())!='\n')
   {
       ++dim;
       s=(char*) realloc (s, (dim+1)*(sizeof(char)));
       *(s+dim-1)=ch;
   }
   *(s+dim)=0; //carattere di fine stringa
   return s;
}



In questo modo la stringa occupa proprio lo spazio di memoria necessario.
Non sprechi memoria ma sprechi comunque risorse per niente visto che la "realloc" costa...

Oppure se proprio non ti va di "sprecare" memoria ma non ti va nemmeno di fare questo procedimento.
Potresti fare così

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

char *get_string();

int main()
{
    char *s;
    printf ("Inserisci la stringa ");
    s=get_string();
    printf ("La stringa e' %s", s);
}

char *get_string()
{
    char s1[100];
    char *s2;
    scanf ("%s", s1);
    s2 = malloc (sizeof(strlen(s1))+1);
    strcpy(s2,s1);

    return s2;

}


s1 occupa 100 bytes solamente all'interno della funzione, ma quando la funzione termina, s1 viene distrutta e la memoria liberata. Il risultato è che la memoria allocata è esattamente quella necessaria per la stringa, cioè non hai sprecato memoria e non hai nemmeno fatto tutte quelle operazioni di realloc.
In questo esempio ho usato la scanf ("%s", s1) ma ovviamente questo lo usi solamente se vuoi leggere la stringa fino al primo spazio. Altrimenti se vuoi leggere oltre o fino ad un determinato carattere riguarda quello che ho scritto sopra.

Tornando all'esercizio sui numeri binari invece penso che bisogni fare così:
1.Leggi la stringa
2.Controlli che ogni carattere della stringa inserita sia '0' oppure '1'.
Se è così converti, altrimenti lanci un messaggio d'errore.

Per trasformare un char in intero sottrai alla variabile il carattere '0'.
Cioè se tu hai un carattere c=="1" e vuoi che venga trasformato in un intero n==1 devi fare:
n=c-'0';
che equivale a
n=c-48;
Infatti '0' è esattamente la costante 48 in quanto il carattere '0' è rappresentato nel codice ascii dal valore 48.
Se premi alt+48 ti uscirà 0.
Quindi alt+49 è 1 e così via....
In ogni caso ricordarsi i valori a memoria non serve a niente.
Quindi è di gran lunga preferibile usare:
n=c-'0';

Atem1
"Atem":

La fgets serve per le leggere un numero massimo di caratteri.
es:
fgets(s1,100,stdin) legge al più 100 caratteri e li mette in s1 quindi se tu digiti 120 caratteri ti prende solo i primi 100.


Intendo dire che legge "al più" 100 caratteri, ma ovviamente se ne inserisci di meno te li legge comunque tutti fino al '\n' (incluso). Se non vuoi che '\n' sia memorizzato nella stringa devi fare così:
int main()
{
   char nome[30];
   printf ("Inserisci il tuo nome e il tuo cognome: ");
  fgets ( nome, 30, stdin );
  nome[strlen(nome)-1] = 0; //prova a commentare questa riga...
  printf ("Ti chiami %s", nome);
  printf ("Fine");
}


Se provi a commentare la riga:
nome[strlen(nome)-1] = 0;
ti accorgerai della differenza.

E cioè se commenti quella riga, "Fine" verrà visualizzato una riga di sotto.
Invece se non lo commenti, "fine" verrà visualizzato attaccato al tuo nome, perchè la fgets nella stringa memorizza anche "\n" come ultimo carattere.
La funzione memorizza al più N caratteri, dove l'ultimo è sempre il carattere di fine stringa 0 ('\0').
Se inserisci meno di N-1 caratteri allora il penultimo carattere memorizzato sarà '\n' mentre l'ultimo sarà '\0'.
Se inserisci più di N-1 caratteri, ti salverà tutti i caratteri fino a N-1, gli altri verranno tagliati, e l'N-esimo carattere sarà '\0'.

Dunque tornando al codice di sopra (preso dalla guida di Blacklight) :

"Il comando dato dopo fgets() è necessario perché tale funzione legge anche il carattere '\n', mettendolo alla fine della stringa. Se non si vuole terminare la stringa con un '\n' si piazza il carattere terminatore '\0' al suo posto (ovvero una posizione prima della fine della stringa)."
http://blacklight.gotdns.org/guidac.pdf
Poi dipende, se tu vuoi che venga memorizzato anche '\n' allora non c'è bisogno di quella riga. Dipende solo da quello che vuoi...

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.