Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Avrei dei problemi a completare un programma in cui deve:
1) Creare due vettori A e B allocati dinamicamente ( new tipo[n]; ) con dimensione scelta da input , aventi un tipo che può essere unsigned short o float , tale tipo viene scelto durante l' esecuzione dall' user ( 0 se è unsigned short , 1 se è float ) . Per tale motivo ho dovuto utilizzare i puntatori a void.
2) Creare un vettore C di stessa dimension e tipo dei vettori A e B , i quali elementi i-esimi vengono calcolati nel seguente modo:
C = A / B se i è pari;
C = A^B ( elevato a B ) se i è dispari;
Dovendo creare un puntatore a funzione ( sempre perchè la traccia me lo richiede ).
3) Stamapare il Vettore C
Punti risolti: i punti 1) e 3) funzionano poichè, una volta letti i vettori A e B li ho stampati con il sottoprogramma che dovrei utilizzare per il vettore C e funziona
Problema: il punto 2) mi da problemi , per tale motivo vi incollo il sottoprogramma che applica la divisione ( identico per la potenza ) e penso che il problema consista in quello perchè durante l' esecuzione e precisamente nella stampa del vettore C , i risultati non sono esatti:
Codice sorgente - presumibilmente C++
Codice:
void divisione (void* A, void* B, void* C,constint t){
if( t == 0 )
{
unsignedshort*u =(unsignedshort*)A;
unsignedshort*v =(unsignedshort*)B;
unsignedshort*ris =newunsignedshort;
cout<<"divisione "<<*u <<"fratto "<<*v <<endl;
*ris=*u/*v;
cout<<"il risultato di e' "<<*ris<<endl;
*(unsignedshort*)C=*ris;
}
else
{
float*u=(float*)A;
float*v=(float*)B;
float*ris=newfloat;
*ris=*u/*v;
*(float*)C=*ris;
}
}
quei cout mi servivano per utilizzare un debugging manuale cmq da quei cout ho potuto vedere che cmq vengono presi giusti i valori nelle rispettive i-esime posizioni dei vettori A e B e anche il risultato *ris è giusto . Ma quando vado a stampare ( tramite un altro sottoprogramma ) il vettore C , mi da valori random. In conlusione penso che il problema sia nel comando *(unsigned short*)C= *ris; ---> non è giusto fare così? se si o se no mi potreste dire come potrei fare?
Se non vi è chiaro vi posso incollare tutto il programma che è diviso in 3 file.
void stampa_Vettore (void* C, constint n, constint t);
int main(){
int t , n;
void*A,*B,*C;
cout<<"--> Inserisci il riemp:"<<endl;
cin>> n;
do
{
cout<<"--> 0 unsigned short"<<endl
<<"--> 1 per float "<<endl
<<"--> Inserisci il numero a seconda di che tipo vuoi creare il vettore: "<<endl;
cin>> t;
}while(( t !=1 )&&( t != 0 ));
leggi_vettore(A,n,t,'A');
leggi_vettore(B,n,t,'B');
stampa_Vettore(A,n,t);
stampa_Vettore(B,n,t);
pfunz* f= produci_pfunz(n);
produci_vettore(C,A,B,n,t,f);
cout<<"--------------------> Stampa Vettore C <--------------------"<<endl;
stampa_Vettore(C,n,t);
return0;
}
void leggi_vettore (void*& p_void, int n , constint t, constchar nome){
cout<<endl<<"---------> Lettura del Vettore "<< nome <<" <---------"<<endl;
if( t == 0 )
{
unsignedshort*u =newunsignedshort[n];
inserimento ( u,n ,nome);
p_void = u ;
}
else
{
float*u=newfloat[n];
inserimento (u,n,nome);
p_void = u ;
}
cout<<"---> Vettore "<< nome <<" creato di tipo "<<
(( t ==1)?"float":"unsigned short");
cout<<endl<<endl;
}
template<typename T>
void inserimento ( T *& u , constint n , constchar nome)
{
for(int i =0 ; i < n ; i++)
{
cout<< nome <<"["<< i <<"]: "<<endl;
cin>> u[i];
}
}
pfunz* produci_pfunz (constint n ){
pfunz* pf=new pfunz[n];
for(int i =0 ; i< n ; i++)
{
if( i%2== 0)
pf[i]=&potenza;
else
pf[i]=&divisione;
}
return pf;
}
void produci_vettore (void*C,void* A, void* B , constint n , constint t, pfunz* f ){
if( t == 0 )
{
C =newunsignedshort[n];
unsignedshort*u=(unsignedshort*)A;
unsignedshort*v=(unsignedshort*)B;
for(int i =0; i< n ; i++)
{
cout<<"vale: "<< i <<endl;
f[i](u+i,v+i,C+i,t );
}
}
else
{
C =newfloat[n];
float*u=(float*)A;
float*v=(float*)B;
for(int i =0; i< n ; i++)
f[i](u+i,B+i,v+i,t );
}
}
void stampa_Vettore (void* C, constint n, constint t)
{
if( t== 0)
{
unsignedshort*u=(unsignedshort*)C;
for(int i =0; i< n ; i++)
cout<<"C["<<i<<"]: "<< u[i]<<endl;
}
else
{
float*u=(float*)C;
for(int i =0; i< n ; i++)
cout<<"C["<<i<<"]: "<< u[i]<<endl;
}
}
Ho messo tanti sottoprogrammi nel main solo perchè sono richiesti nella traccia. Cmq per quanto riguarda la chiamata è riferita al sottoprogramma produci_Vettore nel quale c'è un puntatore a funzione void che per ogni i-esimo ciclo chiama la funzione divisione o potenza. Se lo esegui potrai vedere che la lettura e la stampa dei vettori A e B funziona e anche il risultato della divisione/potenza per ogni i-esimo ciclo . L' unica cosa che non mi funzione è la stampa del vettore C quando chiamo la funzione stampa_Vettore. Il problema penso è che il risultato di ogni divisione/potenza non viene inserito nell' indirizzo giusto, cioè quello a cui punta C.
In realta' il compilatore, quando conosce le dimensioni di u (unsigned short = 2 bytes, float = 4 bytes) cambiera' il codice in:
Codice sorgente - presumibilmente Plain Text
u + i * sizeof(tipo);
Ovviamente questo avviene implicitamente ed e' calcolato durante la compilazione. Ma e' impossibile sapere se utilizzerai un float oppure un unsigned short, quindi il compilatore probabilmente fara' un assunzione e utilizzera' uno o l'altro.
Il problema e' dimostrabile con questo programma:
Codice sorgente - presumibilmente C++
#include <iostream>
void func(void*a, int t){
if(t == 0){
std::cout<<(unsignedshort*)a << std::endl;
}else{
std::cout<<(float*)a << std::endl;
}
}
int main(void){
unsignedshort*a =newunsignedshort[4];
for(int i =0; i<4; i++){
a[i]= i;
}
for(int j =0; j<4; j++){
func(a + j, 0);
}
std::cout<< std::endl;
for(int j =0; j<4; j++){
func(a + j, 1);
}
system("pause");
return0;
}
Noterai che gli indirizzi hanno un offset di 2 bytes in entrambi i casi.
Cambiando le chiamate con:
Codice sorgente - presumibilmente C/C++
func((unsigned short *)a + j, 0);
// ...
func((float *)a + j, 1);
Definendo esplicitamente il tipo di dato che stiamo passando, l'output e' invece corretto. Per gli unsigned short l'offset e' di 2 bytes, per il float e' di 4.
Grazie per la disponibilità . Si ha ragione, i nomi non sono molto significativi , il problema è che mi devo attenere alla traccia che mi è stata data dal prof tra cui diceva anche i nomi delle funzioni, il tipo che dobbiamo utilizzare ecc.... però alcune variabili le ho assegnate io il nome per velocizzare, pensando che non avessi avuto problemi.
Comunque sia , ho capito quello che mi ha detto ma il punto è che facendo quel cambiamento la stampa è la stessa, cioè errata.
Ho risolto il problema utilizzando un debugging manuale ( utilizzando i cout ) semplicemente perchè il debugger di eclipse non mi piace molto ( e putroppo devo utilizzare eclipse ). mettendo dei cout in produci vettore :
Codice sorgente - presumibilmente C++
[Code]
void produci_vettore (void* C, void* A, void* B , constint n , constint t,pfunz* f ){
cout<<"Indirizzo dopo operazione: res: "<<res<<endl;
C=res;
cout<<"indirizzo di C: "<< C<<endl;
return C;
}
else
{
float*res =newfloat[n];
float*u=(float*)A;
float*v=(float*)B;
for(int i =0; i< n ; i++)
f[i]((float*)u+i,(float*)v+i,(float*)res+i,t );
C=res;
return C;
}
}
[/Code]
Ho notato che a fine creazione del vettore C, quest' ultimo punta all' inidirizzo giusto. L' errore , molto banale che non so come ho fatto a non pensarci è che poichè il puntatore C non viene passato per riferimento, l' indirizzo a cui punterà C alla fine del sottoprogramma verrà perso. Per ciò ho dovuto modificare il programma in questo modo:
Codice sorgente - presumibilmente C++
[Code]void* produci_vettore (void* A, void* B , constint n , constint t, pfunz* f ){