|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
[C++] ancora su puntatori ad indirizzi, * e &
se ho una funzione
void esempio(double *x) { double i; double numero=7; for (i = 0; i<numero; i++) { *(x+i)=i; } } //end function se nel main attivo double test[7]; esempio(&test[0]); alla fine avrò: test[0]=0; test[1]=1; test[2]=2; test[3]=3; test[4]=4; test[5]=5; test[6]=6; domanda: ma...se io NON so a priori il ciclo for dentro la funzione quante volte verrà attivato (al posto del "numero=7" ho un valore che saprò solo durante lo svolgimento della funzione).Ebbene: poichè nel main ho definito double test[7]; ovvero è come se avessi detto (tanto per capire) test[numero]; visto che numero=7 come faccio? io num non lo so. se la funzione mi "spara" numero=12 che ne so io a priori da scrivere nel listato double test[12]; come risolvo? cioè come faccio a apssare alla funzione l'indirizzo del primo elemento di un array di cui però non ho idea di quanti elementi avrà l'array e quindi non posso definirlo a priori? oppure c'è un altro metodo? insoma io devo costruire un array dentro una funzione, atrray che sarà poi visibile come variabile globale nel main e di cui non so quanto deve essere grosso a priori ma solo durante lo svolgimento della function stessa.
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII Ultima modifica di vermaccio : 01-06-2006 alle 12:39. |
|
|
|
|
|
#2 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Spiega meglio cosa vorresti fare.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
la situazione è questa: devo creare tramite un function un array bidimensionale nX2 (una matrice di 2 righe e n colonne).
iquesta matrice, una volta chiusa la funziona che la crea, deve esere visibile da altre funzioni che si attiveranno in seguito. quiandi la "matrice" deve essre una variabile globale. il problem è che finchè la funzione creatirce non si attiva non saprò quante colonne "n" avrà la matrice. quindi la domanda è: data una function che al suo interno "dichiara" il numero di colonne...... come faccio nel main a dichiarare una variabile globale in cui mettere i dati della matrice? qualsiasi soluzione va bene. quindi 1)si attiva la funzione 2)nella funzione vine e detto, in base al suo scopo, che n=qualcosa (es:21) che varia ad ogni chiamata 3)viene riempita una matrice 2Xn 4)la funzione si chiude come fare per avere fuori della funzione, una volta chiusa, quella matrice o un qualcosa del genere che contenga i dati della matrice?
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Io farei così:
Codice:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
double **array;
int rows;
int columns;
} DOUBLE_2D;
DOUBLE_2D alloc_double_2d (int rows, int columns)
{
int i;
DOUBLE_2D double2d;
double2d.array = (double**) malloc (rows * sizeof (double*));
for (i = 0; i < rows; i++)
double2d.array[i] = (double*) malloc (columns * sizeof (double));
double2d.rows = rows;
double2d.columns = columns;
return double2d;
}
void free_double_2d (DOUBLE_2D *double2d)
{
int i;
for (i = 0; i < double2d->rows; i++)
free (double2d->array[i]);
free (double2d->array);
double2d->array = NULL;
double2d->rows = 0;
double2d->columns = 0;
}
DOUBLE_2D tua_funzione (void)
{
int n = 21;
DOUBLE_2D double2d;
/* .... */
double2d = alloc_double_2d (2, n);
return double2d;
}
int main (void)
{
DOUBLE_2D arr;
arr = tua_funzione ();
free_double_2d (&arr);
return 0;
}
Come avevo detto io, un array di questo tipo non è esattamente un array come inteso dal linguaggio "C". Perché i dati non sono tutti contigui in memoria, in pratica così è semplicemente "un array di array". Ma in molti casi va bene, non frega niente se non è contiguo ma solo se la dimensionalità è uguale 2.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
mumble.. mumble...
quindi usi una struttura! grande idea! A) DOUBLE_2D alloc_double_2d alloca e crea la "matrice" rowXcolumns B) void free_double_2d (DOUBLE_2D *double2d) cancella e dealloca la memoria occupata dalla matrice rowXcolumns prima creata C) DOUBLE_2D tua_funzione (void) qui dentro richiamo la A per creare la matrice rowXcolumns in base ai valori row e columns che qui dentro vengono definiti D) ne main free_double_2d (&arr); uccide quella matrice. domanda1: ------------ ma se non la uccido viene sovrascritta oppure rimane ad occupare memoria perchè la successiva chiamata della funzione A crea un altra matrice ma quella "vecchia" è ancora li ma senza puntatore per usarla? quindi se non cancello ogni volta la matrice creata alla lunga la memoria si riempie? domanda2: ----------- nella A double2d.array = (double**) malloc (rows * sizeof (double*)); alloca la memoria necessaria per le row righe ognuna avente columns colonne. ma che significa "**" nel double? domanda3: ----------- sempre nella A: for (i = 0; i < rows; i++) double2d.array[i] = (double*) malloc (columns * sizeof (double)); riempie i campi dell'array. domanda4: ------------ nel main int main (void) { DOUBLE_2D arr; /definisco la "variabile" globale arr! ma non si sa ancora quanto è grande l "array" la dentro! arr = tua_funzione (); qui dentro riempio la variabile arr dopo averne definito il contenuto. visto che la arr è globale ogni modifica sarà visibile ancora dopo aver chiuso chiuso la funzione tua_funzione. free_double_2d (&arr); ammazzo la arr ora creata return 0; } tutto ok? ps: ci speravo fossi tu a rispondere al mio quesito! sei il mio micio preferito!
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII |
|
|
|
|
|
#6 | ||||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
![]() In pratica è "un array di array". C'è un primo array che contiene dei puntatori agli array della seconda dimensione. Ecco perché serve allocare prima un array delle righe che contengono double* e poi per ogni riga allocare un array di N elementi double. double** perché solo così si può fare: double2d.array[r][c] Quote:
Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||||
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
usi operativi della matrice "double2d" rowXcolumns:
1) nella funzione DOUBLE_2D tua_funzione (void) se row=2 columns=21 e se volessi settare gli elementi come faccio? con un ciclo for. ma come setto UN elemento dentro il ciclo for? per dire che voglio che l'elemento riga 2, colonna 8 sia un double uguale a 999, come scrivo? [tra parentesi: la numerazione va da 0 in poi per gli elementi?] 2) e invece nel main se voglio leggere l'elemento riga2 e colonne 12 di double2d ed assegnarlo alla variabile "double estratto;"? 3) se devo passare ad un altra funzione la matrice bidimensionale, come gliela passo? cioè se ho: void altra_funzione (DOUBLE_2D interna) { ... blabla ... } la richiamo dal main con altra_funzione (double2d); ?
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII |
|
|
|
|
|
#8 | ||||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Quote:
Quote:
Nota: in ANSI "C" è permesso passare/ritornare strutture per valore.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||||
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
A2)
(quesito3) se NON voglio passarla per valore ma per qualcosa=indirizzo? nel main la richiamo con altra_funzione (&arr[0][0]); ? e dentro la funzione void altra_funzione (DOUBLE_2D* interna) { con dentro la funzione cose del tipo -->per assegnare (*interna)=qualcosa; per modificare il primo elemento e (*interna+column+row*column)=qualcosa; per modificare l'elemento alla posizione row,column? -->per leggere qualcosa=(*interna); e qualcosa=(*interna+column+row*column); ??? B2) inoltre essendo una variabile del main posso comunque evitare questa paranoia ed usare direttamente definire void altra_funzione2 (altre cose) { e chiamarla con altra_funzione2 (...); al cui interno faccio diretamente arr.array[row][column]=qualcosa; e qualcosa=arr.array[row][column]; ???
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII Ultima modifica di vermaccio : 01-06-2006 alle 15:40. |
|
|
|
|
|
#10 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
altra_funzione (&arr); arr è una struttura, NON il double** (che è invece contenuto all'interno della struttura). nella funzione si userà quindi: interna->array[r][c] = ....; ... = interna->array[r][c]; Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#11 | ||
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
Quote:
per una struttura passta con la & io faccio struttura->campo[x][y] se campo è un array bidimensionale. Quote:
ok. è il mio caso. quindi invece di impazzirmi con passaggi "&" e le conseguenti "->" faccio prima così.
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII Ultima modifica di vermaccio : 01-06-2006 alle 16:10. |
||
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
FACCIAMOCI DEL MALE!!!!!!
sempre più contorto
sino ad ora abbiamo chiarito come creare e riempire una struttura con dentro un array bidimensionale le cui dimensioni sono decide dentro una funzione che poi la riempie anche. Però si è dato per scontato che la funzione "decida" row e columns una volta per tutte, poi crea l'array rowXcolmns e lo riempie. che fare nel caso in cui la funzione solo alla fine saprà columns MA (dolore!) a mano a mano che aggiunge columns deve salvare i dati? esempio: sono ad occhi chiusi in una stanza piena di sedie. apro gli occhi e mano mano che giro su me stesso (sino a fare un giro completo di 360°) per ogni 10gradi di rotazione conto quante sedie vedo davanti a me. alla fine columns=numero sedie viste. Però nell'array bidimensionale devo stoccare, per ogni colonna: riga1=numero totali gambe delle sedie che vedo in quel momento riga2=numero totali delle sedie che vedo io creo una nuova colonna solo se nel punto di osservazione istantaneo vedo sedie. se non ne vedo non faccio nulla a ruotoun altro po. se ad esempio ho solo 1 sedia alla mia sinistra ,due dietro, e una a destra: io avrò tre colonne. 4 8 4 1 2 1 con il metodo prima visto io avrò ALLA FINE columns=3 e creo array 2X3 e lo riempio... ma... con cosa? io devo riempirlo MENTRE giro (quando non so che alla fine columns=3), NON a giro finito (quando so columns=3)! quindi devo riempire a mano a mano la struttura senza sapere quanto è grossa! una soluzione è far si che nella function: 1)giro su me stesso 2)a mano a mano stocco dati dentro un altra entità locale 3) a fine giro so il numero colonne 4)creo struuttura esterna come detto in tutto il resto del thread 5)copio valori da entità locale e struttura esterna ma.. entità=???? siamo da capo: che uso per stoccare dati a mano a mano senza sapere quanti saranno alla fine??????????? arghhhhhhhh!
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII Ultima modifica di vermaccio : 01-06-2006 alle 16:31. |
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Non puoi creare una volta sola un array di dimensioni "ragionevolmente" grandi in modo che ti vada bene??? Se questa soluzione non ti piace, non ti va bene o non ti basta, si può fare in un altro modo: creare una apposita funzione di riallocazione dell'array. Come gestire la riallocazione dell'array ... bisogna vedere. Il problema è questo: se ogni volta che devi aggiungere 1 elemento, allarghi le colonne dell'array ... credo che il tuo programma passerà più tempo a fare (ri)-allocazioni che altro! Comunque ci penso un attimo. Risistemo il codice che avevo postato mettendo magari anche la gestione degli errori ... e poi riposto il codice.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#14 | |
|
Member
Iscritto dal: Apr 2006
Città: Trieste
Messaggi: 141
|
Quote:
Saluti |
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Sep 2001
Città: Roma
Messaggi: 2141
|
Quote:
puoi postare un esempietto pratico? comunque non posso permettermi sovraccarichi di cpu: il codice cpp una volta lanciato lancia altre applicazioni e già così un AMD2600+ fa fatica a stargli dietro. e se la simulazione inizia a "scattare" è la fine! preferisco sprecare memoria che avere sovraccarichi di cpu. credo che la soluzione "a spanne" di creare un entità di appoggio sovrabbondante sia valida. ad esempio double entità[2][100]; magari nel 99% dei casi ne riempirò solo le prima 5 colonne. a 100 non arriverà MAI.
__________________
..strisc...strisc...oooooOOoooO http://digilander.iol.it/pentiumII Navi da battaglia giapponesi classe Yamato WWII |
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Genova
Messaggi: 937
|
Per quanto riguarda l'esempio scemo sull'uso del vector<T> eccoti questa cavolata:
Codice:
#include <vector>
#include <iostream>
void stampaAllaC(const std::vector<int>& arr)
{
unsigned int i;
for (i = 0; i < arr.size(); i++)
{
std::cout << "vettore[" << i << "] = " << arr[i] << std::endl;
}
}
void stampaAllaCPP(const std::vector<int>& arr)
{
std::vector<int>::const_iterator it;
for (it = arr.begin(); it != arr.end(); ++it)
{
std::cout << *it << std::endl;
}
}
int main()
{
const int minLimit = 0;
const int maxLimit = 200;
int i;
std::vector<int> vect;
for (i = minLimit; i <= maxLimit; i++)
{
if ((i % 3) == 0)
{
vect.push_back(i);
}
}
std::cout << "Alla fine gli elementi nel vettore sono " << vect.size() << std::endl;
// puoi recuperare i dati con l'operatore [] come si fa in C
stampaAllaC(vect);
// oppure usare gli iteratori
stampaAllaCPP(vect);
return 0;
}
1) li puoi usare non solo con i tipi "standard" (int come in questo caso, long, float, car ecc ecc) ma anche con tipi definiti da te (unica accortezza: per certi contenitori devi definire l'ogetto da memorizzare come una classe che abbia l'operatore di assegnazione (operator=), il costruttore di defult, il costruttore di copia e l'operatore di ordinamento < (operator<) 2) qui ho usato un "vector" che era quello che ti era gia' stato nominato: in realta' ne esistono numerosi altri (map, set...) Uno che trovo molto utile e' la map<KEY,VAL> che e' un contenitore associativo. Ti permette di associare una chiave (di qualsiasi tipo, anche definito da te) ad un valore da memorizzare (di qualsiasi tipo, anche definito da te). Ad esempio se hai Codice:
std::map<std::string, float> coeff; // creo una mappa vuota Codice:
// inizio a popolare la mappa
coeff[std::string("metro")] = 1.0;
coeff[std::string("kilometro")] = 1000.0;
coeff[std::string("decimetro")] = 0.1;
3) i contenitori hanno gia' operazioni quali ad esempio l'ordinamento, l'operatore di copia (quindi puoi copiare tutto un vettore semplicemente usando il carattee "=") 4) tramite i connettori (ma questo per favore non farmelo spigare) puoi "applicare" diverse operazioni su ogni elemento del contenitore senza scrivere il solito ciclo per scorrere tutti gli elementi presenti nel contenitore 5) come gia' detto prima gli elementi e le chiavi possono essere di qualsiasi tipo. Questo permette anche di memorizzare un contenitore in un contenitore, ovvero puoi ad esempio creare vettori di mappe e mappe di mappe di mappe (giuro, l'ho visto fare) Questi sono solo i primi vantaggi che mi sono venuti in mente. Altra cosa: spesso si dice che il C++ e' piu' lento (in termini di tempi di esecuzione) rispetto al C. Per esperienza personale (con il C e C++ ci campo da una vita), e stando anche a quanto affermato piu' volte da B. Stroustrup (speriamo stavolta di averlo scritto bene... e' l'inventore del C++) , SE IL CMPILATORE CHE USI E' FATTO BENE e se hai scritto in maniera decente il tuo programma, non dovresti avere problemi di prestazioni negative rispetto all'analogo algoritmo implementato in C. IMHO se non usi le classi e tutto il mondo del C++, e' uno spreco usare il C++ per far girare un algoritmo scritto in C. Ciao, Mr Hyde
__________________
MacMini Late 2009/MacMini 2018 Ultima modifica di mr_hyde : 01-06-2006 alle 23:07. Motivo: aggiunta |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 21:28.




















