2 ES.PUNTATORI!!!

IlaCrazy
Salve! :-D :-D :-D :-D
avrei bisogno di una mano x risolvere 2 esercizi in Visual C++
che richiedono l'uso di puntatori...

1. Invertire una stringa utilizzando i puntatori
(posto qui la mia soluzione: dove sbaglio????????)

#include
#include
#include
#define LUN 10
void main ()
{
char s[LUN];
int lunghezza;
char ris;
void inverti ( char parola[], int l, char *p);
printf (" parola?");
scanf ("%s", s);
lunghezza= strlen(s);
inverti (s, lunghezza, &ris);
printf (" la nuova parola è %s", ris);
exit (0);
}

void inverti (char parola [], int l, char *p){
int i,c;
char risultato[LUN];
c=0;
for (i=l; i>0; i=i-1){
risultato[c]= risultato[c]+ parola;
c=c+1;

}
risultato= *p; QUI MI Dà ERRORE!!!

return;
}




2. Trovare il minimo di un vettore mediante la funzione
Int TrovaMinimo( int *Vettore, int num)
in cui siano dati come parametri un vettore di interi e il numero indicante
quanti numeri si trovano nel vettore..


NE avrei bisogno entro sabato!!! Perchè ho un esame in avvicinamentoooooooOoOoOooOO!!!!!!
:shock: :shock: :shock: :shock: :shock: :shock: :shock:
Thank You!!

Risposte
apatriarca
Nel tuo codice ci sono tantissime cose sbagliate. Mi stupisce che il codice che hai scritto sia stato compilato da Visual C++ (che versione stai usando?). Il problema in quella riga è che restituisci il puntatore ad una locazione di memoria che viene "deallocata" all'uscita dalla funzione. La stringa che contiene il risultato deve essere allocata nel main e passata alla funzione. Ci sono comunque parecchi altri errori sia logici sia a livello di programmazione, appena torno (sto uscendo) vedo se riesco ad elencarteli tutti.

EDIT: Ho riletto il codice e il motivo dell'errore non era quello che avevo scritto. Cerca di ristudiarti bene la differenza tra un array ed un puntatore e capirai che cosa c'è di sbagliato in quella riga, l'errore di compilazione dovrebbe inoltre aiutarti a capirlo.

apatriarca
Come ti ho già detto nel post precedente non puoi passare l'indirizzo di una variabile locale come valore di ritorno (anche se avevo letto velocemente il codice e non era quello il motivo per cui veniva restituito un errore in quella riga). Hai quindi due possibilità: lasciare all'utente della funzione l'onere di allocare la stringa in cui verrà scritto il risultato o usare l'allocazione dinamica della memoria. Immagino che tu non abbia fatto l'allocazione dinamica della memoria e quindi ti spiegherò come comportarti nel primo caso. Ti scrivo prima il codice e poi te lo commento.

void inverti(char *src, int len, char *dest)
{
    int i = len - 1;

    for (; i >= 0; --i, ++dest) {
        *dest = src[i];
    }
    *dest = '\0';
}


Il codice precedente è privo di ogni controllo degli errori. Normalmente si dovrebbe almeno verificare che src e dest puntino a locazioni di memoria valide. Inoltre src e dest non devono puntare a locazioni di memoria sovrapposte (allo stesso array insomma...). Il codice è poi abbastanza semplice: la stringa sorgente viene letta al contrario a partire da (len - 1) fino a 0, mentre quello di destinazione viene scritto nel normale ordine (utilizzando questa volta l'aritmetica dei puntatori invece che gli indici). Nota che non viene modificato il puntatore originale ma solo il parametro della funzione che è locale alla funzione. Ti è tutto chiaro?

Nello scrivere questa funzione non ho seguito la logica della tua perché sinceramente non ho capito che cosa volevi ottenere. Sicuramente dal codice si denota una grossa confusione tra array e puntatore (questa è la vera causa del tuo errore). Dovresti ripassarti meglio questa differenza perché è abbastanza fondamentale.

Per quanto riguarda il resto del programma ho invece i seguenti commenti da fare:
1. main secondo lo standard C deve restituire int. Il valore di ritorno è quello che passi a exit (che non è necessario nel main... basta return 0).
2. I prototipi delle funzioni sono normalmente inseriti al di fuori di ogni funzione prima del loro uso. Sono abbastanza importanti e quindi è meglio se siano in bella vista.
3. Usa fgets per leggere le stringhe da console o da file invece che scanf o fscanf. fgets controlla che la stringa letta non sia più grossa dell'array nel quale deve essere scritta.

Cosa non riesci a fare del secondo problema?

IlaCrazy
Allora.. x quanto riguarda i comandi quelli ke tu utilizzi
sn 1 pò diversi dalla versione ke noi usiamo (si tratta di Visual c++ 6.0)

Nel secondo esercizio il mio problema sta nell'indicare il puntatore all'interno di una function.
non so come comportarmi, poichè abbiamo sempre applicato puntatori all'interno del main
senza ricorrere a funzioni.
Se potessi indirizzarmi verso la soluzione te ne sarei grata
GRAZIE!

apatriarca
Immagino che tu voglia imparare il C, o che almeno questo sia lo scopo del corso, e non quello di imparare la sintassi specifica di qualche compilatore che a quanto pare non è conforme allo standard. Visual C++ 6 è datato e ti consiglio vivamente di buttarlo via e cambiarlo con un IDE più moderno e conforme. Le versioni express dell'IDE della Microsoft sono gratuite. Mi rendo conto che probabilmente la tua scelta è caduta su quello che si usa in laboratorio ma è bene che tu sappia che c'è di meglio in giro.

Il puntatore lo passi come argomento della funzione e il suo valore è accessibile tramite il parametro Vettore nella funzione. Un esempio è già visibile nel mio scorso post per la funzione inverti. Il prossimo codice ad esempio restituisce la somma di tutti gli elementi dell'array. Come struttura non è molto diversa da quella del tuo problema e quindi credo sia un esempio adeguato.

#include <stdio.h>

int sum(int *arr, int len);

int main()
{
    int array[7] = {1, 2, 3, 4, 5, 6, 7};
    int s = sum(array, 7);

    printf("La somma degli elementi è: %d\n\n", s);    

    return 0;
}

int sum(int *arr, int len)
{
    int i;
    int ret = 0;

    for (i = 0; i < len; ++i) {
        ret += arr[i];
    }

    return ret;
}


Come vedi accedo all'array presente nel main utilizzando il parametro della funzione, utilizzando la normale sintassi degli array. Potevo anche utilizzare l'aritmetica dei puntatori per fare la stessa cosa ma così mi sembra più chiaro. Nel tuo problema dovrai semplicemente calcolarti il massimo invece che la somma (che immagino non sia un problema...).

minavagante1
ciao, scusate l'intromissione, volevo chiedere una cosa riguardo a questo ultimo programma scritto da apatriarca.
Allora, quando io scrivo array, indico la locazione di memoria del primo elemento dell'array giusto??? Quindo quando lo passi alla funzione, scrivi array, e passi la locazione di memoria. Nel prototipo inserisci un puntatore, che punta a quella locazione (quindi al valore no??): non riesco a capire perchè nella funzione (quando fai la somma) ci sia arr e non *arr

apatriarca
Vi invito a prendere un qualsiasi manuale di C e cercare di leggervi la differenza tra puntatori e array e capire quanto sono intercambiabili. Cerco comunque di dare una breve spiegazione.

Gli array e i puntatori sono due oggetti differenti in C ma che in molte occasioni sono interscambiabili. Prima di tutto delle definizioni:
- ARRAY: Un array è un insieme non vuoto di oggetti dello stesso tipo allocati sequenzialmente uno dopo l'altro. Non ci sono cioè spazi vuoti tra elementi di un array. Gli array sono caratterizzati dal tipo degli elementi e dal numero di elementi. Vengono dichiarati nel modo seguente
T array[N];
dove T è il tipo ed N la dimensione.

- PUNTATORI: Un puntatore è un oggetto che contiene un riferimento (indirizzo di memoria) ad un altro oggetto di un certo tipo. Viene dichiarato nel modo seguente
T *puntatore;
dove T è il tipo.

Come definizione i due tipi sono quindi completamente distinti e rappresentano oggetti completamente diversi. In particolare ci sono le seguenti differenze:
1. Comportamento con sizeof. sizeof(array) restituisce sizeof(T)*N mentre sizeof(puntatore) == sizeof(T *). array non è quindi semplicemente un puntatore al primo elemento dell'array come vi hanno spiegato. Inoltre questo permette di ottenere la dimensione dell'array scrivendo sizeof(array)/sizeof(T). sizeof viene comunque calcolato durante la compilazione e quindi a runtime questa scrittura è equivalente ad aver scritto semplicemente N.
2. array può essere usato solo un un r-value (può stare cioè solo a destra dell’operatore di assegnamento). In questo caso array si comporta in un certo senso come un puntatore costante al primo elemento dell'array. Il valore restituito da array è infatti uguale a &(array[0]). È possibile invece modificare la locazione di memoria a cui fa riferimento un puntatore.

In cosa sono invece uguali quindi?
1. In entrambi i casi si possono usare sia l'aritmetica dei puntatori (a patto di non cercare la locazione a cui fa riferimento l'array) e la notazione usando gli indici. La notazione array è in effetti del tutto equivalente ad *(array + i). È talmente equivalente che è anche possibile (provate se non ci credete) scrivere qualcosa come 5[array] al posto di array[5]. Quando ad un puntatore (o un array) viene sommato un numero intero la locazione di memoria viene incrementata di quel numero intero moltiplicato per la dimensione del tipo a cui fa riferimento l'array.
2. Quando entrambi vengono passati ad una funzione appaiono (dalla funzione) come dei puntatori. Nel caso di un array viene quindi passata solo la posizione del primo elemento e si viene a perdere quindi qualsiasi informazione sulla sua dimensione. Nella funzione si lavora quindi con parametri (che sono variabili locali alla funzione e non i puntatori o gli array che ci sono nel main) che vengono inizializzati con i valori contenuti nei puntatori o con l'indirizzo del primo elemento nel caso di array.

minavagante1
:-k
ho ancora qualche difficoltà nel capire il programma: tu nel main hai scritto sum(array,...) . Quando scrivo array, indico la locazione di memoria del primo elemento no?? Siccome nella funzione hai scritto *arr, non sarbbe il valore stesso contenuto in quella locazione di memoria?? Cioè non riesco ancora a capire perchè dentro la funzione, arr rappresenti il valore della i-esima locazione di memoria del vettore :? a me verrebbe da scrivere *(arr+i) che penso che non abbia neache senso :(

apatriarca
Quando chiami la funzione
sum(array, 7)
il parametro arr viene inizializzato con l'indirizzo del primo elemento di array e len a 7. A questo punto posso accedere agli elementi dell'array utilizzando uno qualsiasi dei metodi possibili con i puntatori. In particolare arr è uguale (per la definizione di questo operatore) a *(arr + i) che è l’i-esimo elemento del vettore (per come è definita l'aritmetica dei puntatori). Avrei anche potuto usare direttamente *(arr + i) o incrementare di volta in volta il puntatore come segue:
for (i = 0; i < len; ++i, ++arr) {
    ret += *arr;
}

Sono tutti metodi corretti.

minavagante1
:shock: me le andavo a cercare da solo, sono tutte identiche è vero, scusate :lol:
Scusate l'intromissione, e grazie apatriarca :D

IlaCrazy
Grazie mille! Ora ho capito la differenza tra le 2 cose, infatti ho risolto il programma e sn riuscita
inaspettatamente a farne altri :P

Grande apatriarca! Molte grazie

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