Problema lista di caratteri con C++

  • Autore discussione Mattia Campagna
  • Data d'inizio
M

Mattia Campagna

Ospite
Quanto posterò sotto è un piccolo scorcio abbastanza semplice relativo ad un programmino per creare le mie password. Questa porzione di codice recupera una serie di caratteri da un file di testo tuttavia quando vado a stamparli a video mi stampa due volte l'ultima lettera del file. Deve essere un errore banale ma mi sto arrovellando sempre di più senza uscirne.

Codice:
struct matrice {       
       char info;
       int indice;
       matrice* pun;
};
/******************************GESTIONE MATRICE********************************/              
// Inserisce in coda di una lista l'elemento passato
matrice* insCodaMatrice(matrice*& m, char x, int i) {
      if(m==NULL) {m = new matrice; m->info=x; m->pun=NULL; m->indice=i;}
      else insCodaMatrice(m->pun, x, i);
}


// Carica in memoria la matrice prelevandola dal file
void caricaMatrice(matrice*& m) {
     char c; int i=1;
     ifstream mat ("caratteri.txt", ios::in);
     while(mat) {
                   mat >> c;
                   insCodaMatrice(m, c, i);
                   i++;
     }
     mat.close();
}


// Stampa a video la lista delle coppie matrice/indice
void stampaMatriceIndici(matrice* m) {
     if(m==NULL) return;
     cout << m->indice << ": " << m->info << endl;  
     stampaMatriceIndici(m->pun);
}

Chiaramente nel main le chiamate sono:
Codice:
matrice* matrix=NULL;
caricaMatrice(matrix);
stampaMatriceIndici(matrix);
 

signore del tempo

Utente Èlite
3,228
491
CPU
Intel Core i5 4670K
Scheda Madre
Asus Z87-Plus
HDD
WD Caviar Green 500GB
RAM
G.Skill Ares 2x4GB 1600MHz
GPU
Sapphire 7850 1GB @ 1050MHz
Audio
Integrata
Monitor
Acer V193w
PSU
XFX ProSeries 550W Core Edition
Case
CM HAF 912 plus
OS
ArchLinux + KDE - Windows 10
Scusa ma il codice lo hai scritto tu?
 

signore del tempo

Utente Èlite
3,228
491
CPU
Intel Core i5 4670K
Scheda Madre
Asus Z87-Plus
HDD
WD Caviar Green 500GB
RAM
G.Skill Ares 2x4GB 1600MHz
GPU
Sapphire 7850 1GB @ 1050MHz
Audio
Integrata
Monitor
Acer V193w
PSU
XFX ProSeries 550W Core Edition
Case
CM HAF 912 plus
OS
ArchLinux + KDE - Windows 10
Perché quel codice non può essere scritto da uno studente di IF.
È privo di logica, sintassi mixata tra C/C++, errori sintattici, etc.
Cioè per dirne una tra tante, istanzi un puntatore di tipo matrice che punta al nulla e lo passi alle varie funzioni?
 
M

Mattia Campagna

Ospite
Cioè per dirne una tra tante, istanzi un puntatore di tipo matrice che punta al nulla e lo passi alle varie funzioni?

E' il puntatore ad una lista, inizialmente vuota, passandola a caricaMatrice recupero i caratteri da file e li metto in coda uno per volta con l'ausilio della funzione insCodaMatrice. Ho modificato funzioni che già conosco prese da slide, ma non saprei come altro implementare tutto ciò. Il programma compila e gira...

Comunque potrebbe anche essere fuorviante la parola matrice che nel caso specifico non è la matrice nel senso array di vettori...
 

signore del tempo

Utente Èlite
3,228
491
CPU
Intel Core i5 4670K
Scheda Madre
Asus Z87-Plus
HDD
WD Caviar Green 500GB
RAM
G.Skill Ares 2x4GB 1600MHz
GPU
Sapphire 7850 1GB @ 1050MHz
Audio
Integrata
Monitor
Acer V193w
PSU
XFX ProSeries 550W Core Edition
Case
CM HAF 912 plus
OS
ArchLinux + KDE - Windows 10
Codice:
matrice* insCodaMatrice([B]matrice*& m[/B], char x, int i) {
void caricaMatrice([B]matrice*& m[/B]) {
matrice* &m è insensato. Basta semplicemente matrice &m.
Dettagli implementativi a parte, la soluzione è:
Codice:
void caricaMatrice(matrice& m) {
     char c; int i=1;
     ifstream mat ("caratteri.txt", ios::in);
     while(mat >> c ) {
                   insCodaMatrice(m, c, i);
                   i++;
     }
     mat.close();
}
o
Codice:
void caricaMatrice(matrice& m) {
     char c; int i=1;
     ifstream mat ("caratteri.txt", ios::in);
     while ( (mat >> c ).good() ){
                   insCodaMatrice(m, c, i);
                   i++;
     }
     mat.close();
}
se preferisci.
 
Ultima modifica:
M

Mattia Campagna

Ospite
matrice* &m è insensato. Basta semplicemente matrice &m.
Dettagli implementativi a parte, la soluzione è:
Codice:
void caricaMatrice(matrice*& m) {
     char c; int i=1;
     ifstream mat ("caratteri.txt", ios::in);
     while(mat >> c ) {
                   insCodaMatrice(m, c, i);
                   i++;
     }
     mat.close();
}
o
Codice:
void caricaMatrice(matrice*& m) {
     char c; int i=1;
     ifstream mat ("caratteri.txt", ios::in);
     while ( (mat >> c ).good() ){
                   insCodaMatrice(m, c, i);
                   i++;
     }
     mat.close();
}
se preferisci.

Funziona, ho capito, grazie :)
Come mai matrice* &m è insensato? Qualora dovessi modificare il puntatore alla testa potrebbe servirmi. O no? :grat:
 

signore del tempo

Utente Èlite
3,228
491
CPU
Intel Core i5 4670K
Scheda Madre
Asus Z87-Plus
HDD
WD Caviar Green 500GB
RAM
G.Skill Ares 2x4GB 1600MHz
GPU
Sapphire 7850 1GB @ 1050MHz
Audio
Integrata
Monitor
Acer V193w
PSU
XFX ProSeries 550W Core Edition
Case
CM HAF 912 plus
OS
ArchLinux + KDE - Windows 10
Funziona, ho capito, grazie :)
Come mai matrice* &m è insensato? Qualora dovessi modificare il puntatore alla testa potrebbe servirmi. O no? :grat:
Cioè vuoi passare la lista sia per riferimento che puntatore? Perché le sintassi d'accesso sono differenti (. e ->), oltre che il concetto logico dietro.
Attento che in C puro il passaggio per riferimento non esiste, non noti l'errore dato che compili con g++/msvc++. Mi permetto di dirti di mantenere separati i due linguaggi, perché se non fosse per new e gli stream sarebbe C. Non era meglio utilizzare le classi?
 
M

Mattia Campagna

Ospite
Cioè vuoi passare la lista sia per riferimento che puntatore? Perché le sintassi d'accesso sono differenti (. e ->), oltre che il concetto logico dietro.
Attento che in C puro il passaggio per riferimento non esiste, non noti l'errore dato che compili con g++/msvc++. Mi permetto di dirti di mantenere separati i due linguaggi, perché se non fosse per new e gli stream sarebbe C. Non era meglio utilizzare le classi?

Allora, per quanto riguarda la lista non ho ben capito cosa vuoi dirmi, all'uni mi hanno insegnato che la testa della lista va sempre trattata con cura, qualora si dovesse modificare la testa con una funzione, questa va passata per riferimento. E' sbagliato? Se rimuovo il riferimento il programma non funziona.

Per quanto riguarda il codice ibrido io ho impiegato il codice che mi hanno insegnato, non so fare differenze perché da quanto so quello è tutto c++ :blush: Potresti darmi una mano ad individuare il codice "abusivo"?

Purtroppo io so programmare solo per quello che mi hanno insegnato, non ho esperienza sul campo e spesso trovo difficoltà a stendere codice ex novo, ma sono qui per imparare :) Come hai ben detto una volta scritta una bozza di programma mi piacerebbe implementarlo anche con le classi, per ora devo capire fino a dove riesco a spingermi con questo progetto. Inoltre devo ancora definire bene gli algoritmi da impiegare per creare le password, non escludo che rispolverando le conoscenze di algoritmi possa trovare in un secondo momento algoritmi con complessità minore.

- - - Updated - - -

Intanto ho cominciato ad aggiustare questa parte di codice, con le classi effettivamente è più gestibile. Così se devo rimuovere il codice del c lo faccio una cola volta. :)

file.h
Codice:
#include <iostream>
#include <fstream>
using namespace std;


class Base
{
      private:
              struct elem {
                  char info;
                  int ind;
                  elem* pun;
              };
              elem* testa;
      
      public:
             Base(){testa=NULL;}
             void insCoda(char, int);
             void caricaCaratteri();
             friend ostream & operator <<(ostream &, const Base &);
};

file.cpp
Codice:
#include "pass.h"


// Inserisce in coda l'elemento passato col relativo indice
void Base::insCoda(char c, int i)
{
     elem* p; elem* q;
     for (q = testa; q != NULL; q = q->pun) p = q;
     q = new elem; 
     q->info = c;
     q->ind = i;
     q->pun = NULL;
     if (testa == NULL)
        testa = q; 
     else 
          p->pun = q;
}


// Carica i caratteri consentiti da file
void Base::caricaCaratteri() 
{
     char c; int i=1;
     ifstream f ("caratteri.txt", ios::in);
     while(f>>c) {
                   insCoda(c, i);
                   i++;
     }
     f.close();
}


// Ridefinizione dell'operatore di uscita
ostream & operator <<(ostream &os, const Base &b)
{
        Base::elem* q = b.testa; // controlla
        while(q)
        {
                if(q->ind<10) os << q->ind << ":  " << q->info << endl;
                else os << q->ind << ": " << q->info << endl;
                q=q->pun;
        }
        return os;
}

main.cpp
Codice:
#include "pass.h"
using namespace std;


int main()
{
    Base b;
    b.caricaCaratteri();
    cout << b << endl;
    system("pause");
    return 0;
}

Per ora ho fatto la funzione per inserire nella lista, la funzione per caricare da file i caratteri ed ho ridefinito l'operatore di uscita. Pareri? Codice del C da rimuovere? :blush:
 
M

Mattia Campagna

Ospite
Hai già utilizzato le classi al posto delle struct? Gà fatto una lista di classi?

Si, guarda sopra :) In questo caso non mi occorre una lista di classi perché mi basta istanziare un solo elemento della mia classe per avere quello che mi serve. Dentro infatti contiene una lista :)
 

signore del tempo

Utente Èlite
3,228
491
CPU
Intel Core i5 4670K
Scheda Madre
Asus Z87-Plus
HDD
WD Caviar Green 500GB
RAM
G.Skill Ares 2x4GB 1600MHz
GPU
Sapphire 7850 1GB @ 1050MHz
Audio
Integrata
Monitor
Acer V193w
PSU
XFX ProSeries 550W Core Edition
Case
CM HAF 912 plus
OS
ArchLinux + KDE - Windows 10
Anziché Base::caricaCaratteri, usa un overload di >>.
 

signore del tempo

Utente Èlite
3,228
491
CPU
Intel Core i5 4670K
Scheda Madre
Asus Z87-Plus
HDD
WD Caviar Green 500GB
RAM
G.Skill Ares 2x4GB 1600MHz
GPU
Sapphire 7850 1GB @ 1050MHz
Audio
Integrata
Monitor
Acer V193w
PSU
XFX ProSeries 550W Core Edition
Case
CM HAF 912 plus
OS
ArchLinux + KDE - Windows 10
Quello mi è servito per ridefinire l'operatore di uscita per stampare la classe :)
Quello è <<; io intendo >>.
Anziché:
Codice:
[COLOR=#333333]   Base b;[/COLOR] 
    b.caricaCaratteri();
    cout << b << endl;
    system("pause"); [COLOR=#333333]    
return 0;[/COLOR]
usi
Codice:
[COLOR=#333333]   Base b;[/COLOR] 
    cin >> b;
    cout << b << endl;
    system("pause"); [COLOR=#333333]   
return 0;[/COLOR]

per addolcire la sintassi.
 
Ultima modifica:
M

Mattia Campagna

Ospite
Quello è <<; io intendo >>.
Anziché:
Codice:
[COLOR=#333333]   Base b;[/COLOR] 
    b.caricaCaratteri();
    cout << b << endl;
    system("pause"); [COLOR=#333333]    
return 0;[/COLOR]
usi
Codice:
[COLOR=#333333]   Base b;[/COLOR] 
    cin >> b;
    cout << b << endl;
    system("pause"); [COLOR=#333333]   
return 0;[/COLOR]

per addolcire la sintassi.

E' vero! Grazie :D
Per il resto? Va bene? Avevi menzionato sintassi ibrida col C, puoi indicarmi qualcosa?
 

Entra

oppure Accedi utilizzando

Hot: E3 2021, chi ti è piaciuto di più?

  • Ubisoft

    Voti: 15 16.7%
  • Gearbox

    Voti: 1 1.1%
  • Xbox & Bethesda

    Voti: 65 72.2%
  • Square Enix

    Voti: 3 3.3%
  • Capcom

    Voti: 5 5.6%
  • Nintendo

    Voti: 14 15.6%
  • Altro (Specificare)

    Voti: 7 7.8%

Discussioni Simili