PDA

Visualizza la versione completa : Problema puntatori linguaggio C


QuickSL
07-01-2017, 17:27
Buonasera a tutti,
sono nuovo qui sul forum dato che ho iniziato da poco a programmare siccome devo affrontare l'esame di Fondamenti di Informatica a breve.
Ho un problema con un esercizio: il testo mi chiede di scrivere un programma che permetta all'utente di scrivere una parola (o comunque una sequenza di caratteri, max 100), di seguito il programma dovrÓ visualizzare a schermo quante volte compaiono le lettere nella parola scritta(per esempio, inserita la parola "cassa", il programma dovrÓ visualizzare a schermo che la lettera "c" compare una volta sola, la lettera "s" invece due volte, ecc.).

Ho strutturato il programma in modo che una volta inserita la parola, ne vengano contati i caratteri tramite la funzione strlen, il tutto memorizzato in una variabile intera.
Successivamente richiamo una funzione che mi restituisci un puntatore: tale puntatore riconduce ad un array, che ha le stesse dimensioni dell'array che contiene la parola inserita.
La funzione che ho scritto in teoria dovrebbe permettermi di confrontare ogni cella dell'array contenente la parola con le altre celle, inclusa se stessa. Ogni volta che due celle risultano identiche, il valore della cella dell'array "vettore_numerativo[NUM]" corrispondente alla posizione della lettera in esame viene aumentato di 1, mi spiego: inserendo la parola "ciao", in teoria la funzione dovrebbe confrontare una per una le lettere tra di loro, a partire dalla prima. Quindi, la funzione prende la lettera "c" e la confronta con se stessa, con "i", con "a" e con "o", poi prende la lettera "i" e ripete il ciclo. Ogni volta che due lettere risultano identiche, la cella dell'array "vettore_numerativo[NUM]" corrispondente alla posizione della lettera esaminata, viene incrementata di 1.

Il programma Ŕ questo:


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

#define MAX_LET 100

int *cardinalitalettere(char *p, int NUM) {
int i, k, t;
int vettore_numerativo[NUM];
int *v;
v = vettore_numerativo;
for (t = 0; t < NUM; t++) {
v[t] = 0;
}
for (i = 0; i < NUM; i++) {
for(k = 0; k < NUM; k++) {
if (p[i] == p[k]) {
v[i] = v[i] + 1;
}
}
}
return v;
}



int main() {
char s[MAX_LET];
int NUM, i;
int *c;
printf("Inserire una frase composta sia da lettere minuscole che maiuscole, con al massimo %d caratteri:\n", MAX_LET);
scanf("%s", s);
NUM = strlen(s);
c = cardinalitalettere(s, NUM);
printf("La numerositÓ delle lettere nella parola inserita Ŕ la seguente:\n");
for (i = 0; i < NUM; i++) {
printf("%c --> %d\n", s[i], c[i]);
printf("\n");
}
return 0;
}

Il problema Ŕ che, una volto che lo eseguo, i valori che restituisce la funzione sono sballati e anche randomici, nel senso che eseguendo pi¨ volte il programma ed immettendo sempre la stessa parola, vengono stampati a schermo valori sempre differenti tra di loro.
Due esempi:


Inserire una frase composta sia da lettere minuscole che maiuscole, con al massimo 100 caratteri:
ciao
La numerositÓ delle lettere nella parola inserita Ŕ la seguente:
c --> 0

i --> 0

a --> 1279985408

o --> 32766



Inserire una frase composta sia da lettere minuscole che maiuscole, con al massimo 100 caratteri:
ciao
La numerositÓ delle lettere nella parola inserita Ŕ la seguente:
c --> 0

i --> 0

a --> -1997601392

o --> 32764



L'ho riguardato pi¨ volte ma non riesco a capire dov'Ŕ l'errore.
Se poteste aiutarmi mi sareste di grande aiuto.
Grazie in anticipo,

Samuele

boots
07-01-2017, 18:23
Non dovresti mai restituire il puntatore di una variabile definita nello stack, perchŔ potrebbe non avere pi¨ i valori che ti aspetti una volta terminata la funzione. In questo caso creala nell'heap (e ricordati di liberarne la memoria):


int *cardinalitalettere(char *p, int NUM) {
int i, k, t;
//int vettore_numerativo[NUM];
//v = vettore_numerativo;
int *v = (int*)malloc(sizeof(int) * NUM);
...
}

int main(){
...
free(c);
return 0;
}

QuickSL
08-01-2017, 12:16
Perdonami se ti rispondo soltanto ora ma sono andato ad informarmi per quanto riguarda le funzioni free e malloc dato che non ho ancora avuto modo di studiarle. In pratica credo si tratti di un problema di allocazione dinamica della memoria.
Dimmi se ho capito bene: se definisco, in una funzione diversa dal main (per esempio int f(int a), una variabile che viene restituita al termine della funzione, quando chiamo la suddetta funzione nel main, mi viene restituito il valore assunto dalla variabile definita nella funzione int f(int a), senza nessun problema. Invece, se tale funzione restituisce un puntatore ad una variabile(ancora una volta definita nella funzione esterna al main), stampando il valore puntato dal puntatore potrei ritrovarmi dei valori diversi da quelli corretti, questo perchŔ non ho allocato memoria dinamica tramite la funzione malloc.
Inoltre, una volta che il programma termina, mi devo ricordare di liberare lo spazio di memoria occupata dal puntatore tramite la funzione free.
E' corretto ci˛ che ho detto?

Quindi, quando definisco una funzione che mi restituisce un puntatore devo sempre allocare memoria dinamica tramite la funzione malloc?

Ultima cosa: il (int*) anteposto al malloc serve per convertire il valore restituito dalla funzione malloc ad un int, dato che malloc dovrebbe restituire un char, giusto?

Grazie ancora! :)

oregon
08-01-2017, 15:14
Non Ŕ proprio come hai scritto ...

La questione Ŕ che il puntatore che restituisci indica un indirizzo di una zona di memoria dove c'Ŕ il dato che ti interessa.

Se questa zona punta allo stack (dato che punta a variabili locali ad una funzione), essendo quest'area distrutta alla fine della funzione, il tuo dato lo sarÓ di conseguenza e il puntatore inutile.

Una soluzione Ŕ far puntare il puntatore ad un'area (detta heap) che viene trattata in maniera diversa e che non viene eliminata automaticamente alla fine della funzione ma solo esplicitamente con la free.

Sembra che tutti questi concetti tu non li conosca ancora, quindi mi sembra che sia necessario per te attendere un po' e studiare con calma dai libri con metodo, altrimenti rischi di fare una gran confusione.

QuickSL
09-01-2017, 17:05
Si lo penso anche io, grazie comunque per la risposta! :)

Loading