Problema con std::vector

di il
14 risposte

Problema con std::vector

Ciao a tutti, sono alle prime armi e mi trovo a programmare con Visual C++.
Credo che dovrò usare gli std::vector ma non ho molta dimestichezza.
Ho un array è a doppia dimensione all'interno di un ciclo for e per ogni iterazione dovrò allocare e deallocare la memoria, ma con new/ delete[] mi dà problemi di allocazione quando il numero di iterazioni diventa grande.
L'array in questione ha le seguenti dimensioni a[2][n] (con n che potrebbe cambiare ad ogni iterazione).
Il codice per l'allocazione/deallocazione che ho usato finora è:

for(.....){
  ........
  delete[] a;
  a=NULL;
  a=new int *[2];
  for(int k=0; k<2; k++)
    a[k]=new int [n];
  .........
}
Non ho capito bene come scrivere la stessa cosa usando gli std::vector... devo creare una classe o posso usarli direttamente?
Spero di essere stato chiaro.
Qualcuno mi potrebbe aiutare? Grazie!

14 Risposte

  • Re: Problema con std::vector

    Ciao, prima di tutto ti consiglio di controllare il tuo programma cercando eventuali array overflow, i programmi fatti con visual C++ a volte crascano se si dealloca un vettore sul quale c'è stato overflow.

    In alternativa se vuoi utilizzare gli std::vector di seguito trovi un programma demo (di tipo console):
    #include <vector>
    
    using namespace std;
    
    typedef vector<int>     INT_VEC
    typedef vector<INT_VEC> VEC_OF_VEC
    
    int main(int argc, char **argv){
    	int n=5;
    	VEC_OF_VEC a;
    
    	// Ridimensiono a in modo che contenga due elementi
    	a.resize(2);
    
    	// Inizializzo i vettori di interi
    	for(int k=0; k<2; k++){
    		// Ridimensiono il vettore in modo che sia lungo n
    		a[k].resize(n);
    	}
    
    	// Svuoto i vettori contenuti in a
    	for(int k=0; k<2; k++){
    		// Svuoto il vettore alla posizione k in a
    		a[k].clear();
    	}
    
    	// Svuoto il vettore a
    	a.clear();
    
    	return 0;
    Per prima cosa ho deciso che non serve allocare i vettori in questo caso, ho fatto che il primo vettore a è un vetore di oggetti vector che contengono interi. Così come ho utilizzato gli oggetti vector, una volta creati, puoi accede agli elementi come con un normale vettore del C. Sappi però che sono fatti in modo che tu puoi aggiungere nuovi elementi nel vettore in qualsiasi momento, il vettore viene automaticamente ridimensionato. Per far ciò devi usare i metodi insert o push_back dell'oggetto, in alternativa fai prima un resize con la nuova dimensione è poi accedi hai nuovi elementi con la notazione a[k].

    Sperò di esserti stato utile . Ciao
  • Re: Problema con std::vector

    Grazie mille davvero. Ora mi trovo un altro problemino.

    In pratica devo passare la matrice a[][] creata come argomento di una funzione.

    Innanzi tutto nel prototipo della funzione la dovrò specificare come VEC_OF_VEC?

    All'interno della funzione gli elementi della matrice li indico normalmente come a[][] oppure devo usare una sintassi diversa?

    Grazie ancora.
  • Re: Problema con std::vector

    Ciao
    Innanzi tutto nel prototipo della funzione la dovrò specificare come VEC_OF_VEC?
    Si, il parametro lo devi definire come VEC_OF_VEC.
    All'interno della funzione gli elementi della matrice li indico normalmente come a[][] oppure devo usare una sintassi diversa?
    Per accedere agli elmenti puoi utilizzare tranquillamente la notazione a[][].

    Ciao
  • Re: Problema con std::vector

    Si, il parametro lo devi definire come VEC_OF_VEC
    Mmm, però quando definisco la funzione
    int function (int a, int b, VEC_OF_VEC c){ 
    
    .........
    
     } 
    mi dà errore di sintassi per l'identificatore VEC_OF_VEC.
    Nonostante l'abbia dichiarato nel prototipo, non so perchè nella funzione mi segna questo errore.

    Sapete dirmi qualcosa?
    Grazie ancora!
  • Re: Problema con std::vector

    Controlla che prima della definizione del corpo della funzione ci siano i due typedef che definiscono il tipo VEC_OF_VEC. Tipo:
    .........
    
    typedef vector<int>     INT_VEC
    typedef vector<INT_VEC> VEC_OF_VEC
    
    .........
    
    int function (int a, int b, VEC_OF_VEC c){
    
    .........
    
     }
    o che comunque ci siano in qualche file .h incluso prima di definire il corpo della funzione.
    Se propio non ti funziona prova a sostituire VEC_OF_VEC con vector<vector<int>>, se anche così non va l'errore è probabile che sia da qualche altra parte.
  • Re: Problema con std::vector

    Grande!!! Bastava infatti inserire i typedef all'interno del file di intestazione dove ho definito le funzioni!

    Ora però ho un nuovo problema (non finiscono mai...):
    Debug Assertion Failed!

    Expression: vector subscript out of range
    In particolare l'errore fa riferimento alla seguente parte di codice all'interno del file vector:
    #if _HAS_ITERATOR_DEBUGGING
    		if (size() <= _Pos)
    			{
    			_DEBUG_ERROR("vector subscript out of range");
    			_SCL_SECURE_OUT_OF_RANGE;
    			}

    Ora ti riporto il codice che ho scritto all'interno del ciclo for in cui dealloco e alloco la memoria per la creazione della famosa matrice a[][]definita con vector:
    
    for(....){
    
        ...........
        
        size=-1;
        for(i=0; i<2; i++)
            a[i].clear();
        a.clear();
        a.resize(2);
        for(int i=0; i<2; i++)
            a[i].resize(size+1);
    
         ..........
    
    }
    Credo che l'errore sia qui dentro perchè c'è l'iterazione della matrice.
    All'inizio pensavo che l'errore fosse dovuto al fatto che ho posto size=-1, ma ho provato a metterlo =1 e mi ha dato lo stesso errore...

    Mi sapresti aiutare?
    Grazie ancora!
  • Re: Problema con std::vector

    Debug Assertion Failed!

    Expression: vector subscript out of range
    Questo errore significa che tu, con la notazione [], tenti di accedere ad un elemento che non esiste nel vettore. Per esempio se la variabile vv, di tipo vector, è grande 5 e tu cerchi di accedere all'elemento 7, vv[7], il compilatore (o debuger) ti da questo errore.
    Oltre a questo non so cosa dirti, il codice che hai postato sembra giusto.
  • Re: Problema con std::vector

    Sì infatti l'errore stava nelle funzioni in cui non avevo lasciato le notazioni classiche dei vettori e non le avevo sostituite con le operazioni dei vector.
    Ho solo qualche dubbio sulla sintassi di alcune operazioni perchè le devo riferire sempre al caso di array multidimensionale e purtroppo non sono riuscito a trovare esempi a riguardo.

    In particolare devo riscrivere le seguenti notazioni usando gli std::vector:
    for(...){
         .....
         size++;
         a[0][size]=10;
         a[1][size]=1;
         .....
    }
    
    a[0][2]=5;
    a[1][2]=6;
    Nel primo caso credo che dovrei usare l'operatore push_back in quanto i valori sono da inserire alla fine dell'array. Ho scritto in questo modo ma non sono sicuro di aver scritto bene:
    size++
    a[0].push_back(10);
    a[1].push_back(1);
    
    Nel secondo caso invece si tratta di sostituire i valori dell'array con altri valori. Qui penso che si debba usare insert ma anche in questo caso non ho molto le idee chiare.
    Mi sai dire come effettuare queste conversioni?
    Grazie!!!!
  • Re: Problema con std::vector

    Ciao, nel primo caso devi usare il metodo push_back propio come hai scritto.
    Nel secondo caso puoi lasciar scritto a[0][2]=4; per sostituire un valore esistente va benissimo.
  • Re: Problema con std::vector

    Sì infatti è così, ho capito che l'errore era dovuto al fatto che con la nuova dicitura std::vector, la funzione non memorizzava le modifiche effettuate sulla matrice, o meglio rimanevano interne alla funzione, perciò al di fuori della funzione mi trovavo ad avere una matrice nulla con una dimensione che era quella che avrebbe dovuto avere.

    Per modificare la matrice std::vector passata come parametro della funzione e far sì che le modifiche valgano anche al di fuori della funzione devo indicare il parametro con un puntatore (o doppio puntatore)? Ci ho provato ma c'è qualcosa che non va.
    Riporto la funzione in questione che è un semplice ordinamento a bolle della matrice y di tipo std::vector:


    Prototipo:
    void bubblesort(int, VEC_OF_VEC *);
    Funzione:
    void bubblesort(int x, VEC_OF_VEC *y)
    {
    	int pass, k;
    	int *hold;
    	hold=new int [2];
    	for(pass=1; pass<=x; pass++){
    		for(k=0; k<x; k++){
    			if(*y[1][k]>*y[1][k+1]){
    				hold[0]=*y[0][k];
    				hold[1]=*y[1][k];
    				*y[0][k]=*y[0][k+1];
    				*y[1][k]=*y[1][k+1];
    				*y[0][k+1]=hold[0];
    				*y[1][k+1]=hold[1];
    			}
    		}
    	}
    }
    Chiamata:
    bubblesort(size, a);
    Mi dà (ovviamente credo) errori di conversione fra std::vector e int.
    C'è un metodo diverso dall'uso del puntatore?
  • Re: Problema con std::vector

    Ciao.
    Prima di tutto puoi provare ad accedere agli elementi in questo modo (*y)[1][k], aggiungendo le parentesi sei sicuro che venga eseguito prima l'operatore asterisco e poi l'operatore parentesi quadre.
    C'è un metodo diverso dall'uso del puntatore?
    Si, puoi passare la matrice per reference, invece che come puntatore, scrivendo:
    void bubblesort(int x, VEC_OF_VEC &y)
    e poi potrai accedere agli elementi normalmente senza aver bisogno di usare l'asterisco, il quale è usato implicitamente dal compilatore.
  • Re: Problema con std::vector

    Si, puoi passare la matrice per reference
    Ok, grande ho risolto, ora sembrerebbe quasi tutto finito.
    C'è solo una cosa di Visual C++ che non ho capito ancora bene.
    Nel main ci sono dei printf per cui una volta che faccio girare il programma mi aspetto di avere le visualizzazioni printf, invece il programma finisce di girare senza che mi visualizzi niente.
    Sono riuscito ad avere le visualizzazioni di output solo mettendo un break point sulla parentesi di chiusura del main, in quel modo mi visualizza tutto.
    A questo punto non credo sia normale, forse devo scrivere diversamente il main, anche perchè l'ho scritto con le notazioni del C e da quello che ho visto finora potrebbe essere completamente diverso.

    Ora riporto il modo in cui ho scritto la struttura del programma:
    #include <stdio.h>
    #include <stdlib.h>
    #include "funzioni.h"
    #include <vector>
    
    using namespace std;
    
    typedef vector<int> INT_VEC;
    typedef vector<INT_VEC> VEC_OF_VEC;
    
    
    int main()
    {
         .............
         printf(........);
         ..............
    }	
    Devo inserire qualche return, file di inclusione o qualche parametro all'interno del main?
  • Re: Problema con std::vector

    Il prototipo corretto del main sarebbe questo:
    int main(int argc, char **argv);
    ma su vc++ funziona anche come l'hai scritto tu.

    Il motivo per cui non vedi niente quando avvii il programma è che quando questo parte crea una console, come quella di cmd.exe, in cui vengono stampate tutte le scritte, altermine dell'esecuzione la console viene chiusa immediamente. E' per questo che non vedi niente, prova a mettere una scanf che prenda in input un carattere al fondo del main, così il programma non termina subito ma aspetta che venga premuto invio prima di terminare. In alternativa puoi usare la getch(), il questo caso però devi includere in più il file conio.h
    #include <conio.h>
    
    int main() 
    { 
         ............. 
         printf(........); 
         .............. 
         // così
         char a;
         scanf("%c", &a);
         // oppure
         getch();
    }
  • Re: Problema con std::vector

    Grazie mille, chiarissimo ed efficace come al solito!
    Sembra che con questo programma abbia finito!
    Al prossimo (spero con meno domande...)!
Devi accedere o registrarti per scrivere nel forum
14 risposte