[C++] esercizio strutture

cooper1
ciao a tutti. ho il seguente esercizio:

Un vettore di interi contiene la rappresentazione, cifra per cifra, di un intero: il posto 0
contiene la cifra più significativa, i posto 1 la seconda cifra più significativa e così via... .
Una variabile intera, poi, indica il numero di cifre utili del vettore; una seconda variabile
intera, invece, contiene il numero intero rappresentato nel vettore (in forma “compatta”).
a. Descrivere una struttura/classe idonea a rappresentare quanto sopra.

b. Scrivere una porzione di codice che consenta di caricare da tastiera il vettore di cui
sopra. Il vettore dovrà essere creato dinamicamente di una lunghezza idonea a
contenere le cifre del numero. I valori in ingresso, inoltre, dovranno essere
controllati tramite la funzione guarda (prototipo: int guarda(char)): la funzione
prende in ingresso un carattere e restituisce il numero corrispondente se il carattere
è una cifra (0,1,2,3,...9), -1 altrimenti.

c. Descrivere l’algoritmo che trasforma l’intero in forma compatta.

d. Facoltativo: mettere a punto la funzione guarda.

pensavo di fare in questo modo
#include <iostream>
#include <cstring>
using namespace std;

struct numero{
	int* punt;
	int dimensione;
	int valore;
};

int guarda(char a){
	int l;
	char b[10]={'0','1','2','3','4','5','6','7','8','9'};
	if(strcmp(a,b) == 0) l=a;
	return a;
}

int main(){

	numero es;
	cout<<"inserire dimensione"<<endl;
	cin>>es.dimensione;
	es.punt=new int[es.dimensione];
	for(unsigned int i=0; i<es.dimensione; i++){
		int p;
		cout<<"carica il vettore"<<endl;
		cin>>p;
		if(guarda(p) != -1){
			es.punt[i]=p;
		}else{
			continue;
		}
	}
	for(unsigned int i=0; i<es.dimensione; i++){
		cout<<es.punt[i]<<endl;
	}
	return 0;
}

ma non mi permette di confrontare b ed a (ovvero mi da come errore la riga [inline]if(strcmp(a,b) == 0) l=a;[/inline]). come posso modificare?
oltretutto per il punto c non ho proprio idee. non ho neanche capito cosa dovrebbe fare. come posso fare?

Risposte
Super Squirrel
strcmp() deve avere come argomento 2 c-stringhe, mentre nel tuo caso "a" è una variabile char e non un puntatore a char.
Detto questo sai cosa fa strcmp()? Chiedo perché sinceramente io non ne vedo l'utilità.

La funzione guarda() si aspetta una variabile di tipo char, invece tu gli passi un intero; inoltre dovrebbe ritornare un intero, invece ritorna la variabile "a" che è di tipo char... in fin dei conti non è un gran problema perché avvengono delle conversioni implicite, ma sinceramente non ha molto senso.

Dal punto di vista logico poi la funzione guarda() è completamente inutile... gli passi un valore e ritorna lo stesso valore!

Sempre da un punto di vista prettamente logico, quel continue nel main è completamente inutile visto che il corpo del ciclo for termina subito dopo. Infatti nei cicli for il continue dà inizio ad una nuova iterazione dopo aver effettuato la MODIFICA (i++ in questo caso).
Ciò significa che se effettui un inserimento non valido il programma non ti dà la possibilità di riprovarci.

cooper1
anzitutto, grazie per la risposta. veniamo ora alle critiche.
"Super Squirrel":
Detto questo sai cosa fa strcmp()? Chiedo perché sinceramente io non ne vedo l'utilità.

sapevo che confrontava due stringhe e restituisce 0 se sono uguali un positivo se il primo carattere è maggiore del secondo oppure negativo nel caso opposto. alla luce di questo pensavo di confrontare i numeri ammissibili (cioè b) con il numero che do in ingresso quando carico il vettore. quindi confronto con strcmp() e se sono uguali assegno il valore, altrimenti no.
tu come faresti altrimenti?
"Super Squirrel":
strcmp() deve avere come argomento 2 c-stringhe, mentre nel tuo caso "a" è una variabile char e non un puntatore a char.

devo quindi dare in ingresso un char* ? non mi sembra molto sensato. forse ho proprio concepito male la funzione, che però non saprei modificare.
"Super Squirrel":
La funzione guarda() si aspetta una variabile di tipo char, invece tu gli passi un intero; inoltre dovrebbe ritornare un intero, invece ritorna la variabile "a" che è di tipo char... in fin dei conti non è un gran problema perché avvengono delle conversioni implicite, ma sinceramente non ha molto senso.

per quanto riguarda il passare un intero mi sono confuso nello scrivere, ma avevo in mente di passare un qualsiasi carattere. quindi correggendo avrei [inline]char p[/inline] in luogo di [inline]int p[/inline].
quanto al tipo di variabile che ritorno, a questo non ci avevo minimamente pensato. non saprei però come correggere volendo rimanere con questa impostazione.
"Super Squirrel":
Dal punto di vista logico poi la funzione guarda() è completamente inutile... gli passi un valore e ritorna lo stesso valore!

essendo questo un tema d'esame, penso che il professore voglia vedere se abbiamo dimestichezza con la chiamata di funzione, stringhe, ecc.
"Super Squirrel":
Sempre da un punto di vista prettamente logico, quel continue nel main è completamente inutile visto che il corpo del ciclo for termina subito dopo. Infatti nei cicli for il continue dà inizio ad una nuova iterazione dopo aver effettuato la MODIFICA (i++ in questo caso).
Ciò significa che se effettui un inserimento non valido il programma non ti dà la possibilità di riprovarci.

giusto, basta solo l'if.

Super Squirrel
sapevo che confrontava due stringhe e restituisce 0 se sono uguali un positivo se il primo carattere è maggiore del secondo oppure negativo nel caso opposto. alla luce di questo pensavo di confrontare i numeri ammissibili (cioè b) con il numero che do in ingresso quando carico il vettore. quindi confronto con strcmp() e se sono uguali assegno il valore, altrimenti no.
tu come faresti altrimenti?

devo quindi dare in ingresso un char* ? non mi sembra molto sensato. forse ho proprio concepito male la funzione, che però non saprei modificare.

Stando alla traccia la funzione guarda() deve semplicemente controllare se il carattere "a" passato alla funzione sia o meno una cifra. Se è una cifra allora ritorna quella cifra (intesa come numero e non come carattere), altrimenti ritorna -1. A tal proposito conosci il codice ASCII?

giusto, basta solo l'if.

No in realtà, altrimenti non avrai la possibilità di reinserire il carattere se la funzione guarda() ritorna -1.

cooper1
"Super Squirrel":
Stando alla traccia la funzione guarda() deve semplicemente controllare se il carattere "a" passato alla funzione sia o meno una cifra. Se è una cifra allora ritorna quella cifra (intesa come numero e non come carattere), altrimenti ritorna -1. A tal proposito conosci il codice ASCII?

così avevo capito anche io. e purtroppo no non lo conosco.
"Super Squirrel":
No in realtà, altrimenti non avrai la possibilità di reinserire il carattere se la funzione guarda() ritorna -1.

benchè forse inutile potrebbe andare uno switch? qualcosa del tipo:
char p;
cin>>p;
switch(guarda(p)){
                 case 0:
                             es.punt[i]=p;
                             break;
                 case 1: 
                 ....
                 case 9:
                            es.punt[i]=p;
                            break;
                 default:
                           cout<<"valore non ammesso, inserisci ancora"
}

Super Squirrel
così avevo capito anche io. e purtroppo no non lo conosco.

Un char non è altro che un int a 8 bit (quindi 256 valori) che associa ad ogni valore un carattere. Per quanto riguarda la corrispondenza che esiste tra valore e carattere basta cercare codice ASCII tra le immagini di google.
Alla luce di ciò non dovrebbe essere particolarmente difficile implementare la funzione guarda(). Se hai dubbi chiedi pure.

cooper1
provo così, spero abbia qualche barlume di senso.
int guarda(char a){
	int l;
	char b[10]={'0','1','2','3','4','5','6','7','8','9'};
   	for(unsigned int i=0; i<10; i++){
		if(a == b[i]) l=a;
	}
   	return l;
}

ammesso che così possa andare, continuo ad assegnare un char ad un int facendo una conversione implicita. non so non ho altre idee sinceramente. :roll:
"Super Squirrel":
Per quanto riguarda la corrispondenza che esiste tra valore e carattere basta cercare codice ASCII tra le immagini di google.

questa non ho ben capito come sfruttarla sinceramente.
grazie per l'aiuto e la pazienza :D

axpgn
$A=65$, $a=97$, ecc. ecc.

cooper1
che si potessero assegnare come codice ASCII ok, ma non so come sfruttarle all'interno della funzione.
int guarda(char a){
                 int l;
                 a=getchar();
                 if((a >= 48) and (a <= 57)) l=a;
                 return a;
}

può andare?

Super Squirrel
Secondo te va bene? Cosa dovrebbe ritornare la funzione?

A cosa serve il getchar()?

P.S.
al posto di a>=48 puoi anche scrivere a>='0'.

cooper1
il getchar() da una veloce letta su internet (potrei quindi tranquillamente sbagliarmi) dovrebbe prendere il codice ASCII del carattere.
int guarda(char a){
                 int l;
                 if((a >'0') and (a <= '9')) l=a;
                 return l;
}

how about this? volevo fare un return l anche prima ma non so perchè ho scritto a.

Obidream
Purtroppo non ho modo di testarla ma immagino che debba essere qualcosa del genere:

int guarda(int c)
{
    if(c >= '0' && c <= '9')
        return c - '0';
    else
        return -1;
}

vict85
Da un punto di vista teorico, non c'è alcuna ragione per ritenere che si stia usando l'ASCII. Siccome però la condizione importante è che [inline]c - '0'[/inline] sia uguale alla cifra rappresentata da [inline]c[/inline], per essere sicuro di non avere un errore nel codice, sarebbe sufficiente aggiungere uno static_assert:
int
guarda(char c)
{
  // questo e' un assert a tempo di compilazione
  static_assert('1' - '0' == 1 && '2' - '0' == 2 && '3' - '0' == 3
                    && '4' - '0' == 4 && '5' - '0' == 5 && '6' - '0' == 6
                    && '7' - '0' == 7 && '8' - '0' == 8 && '9' - '0' == 9,
                "L'encoding attuale e' incompatibile con la funzione corrente");

  if (c >= '0' && c <= '9')
    {
      return static_cast<int>(c) - static_cast<int>('0');
    }

  return -1;
}


Ovviamente, la libreria [inline]ctype.h[/inline] contiene la funzione [inline]isdigit[/inline] che permette di vedere se il valore è una cifra. D'altra parte, è possibile che alcuni encoding segnino come digit qualcosa che non è nell'insieme [inline]'0123456789'[/inline].

Obidream
Da quel che so, sia lo standard del C che del C++ dicono questo:


In both the source and execution basic character sets, the
value of each character after 0 in the above list of decimal digits shall be one greater than
the value of the previous.


Per cui quella conversione dovrebbe essere ok a prescindere dalla codifica usata

cooper1
vi ringrazio per gli interventi che domani mi leggerò con calma. :D
detto questo, mi sembra strano ci richiedesse una risoluzione di quel tipo per due ragioni: la prima, come detto, è che non abbiamo trattato codice ASCII e quindi per me quei pezzi di codice sono nuovi; la seconda è che è una prova scritta (con carta e penna) e sarebbe impensabile sapere a memoria tutti i codici. :|

vict85
"Obidream":
Da quel che so, sia lo standard del C che del C++ dicono questo:


In both the source and execution basic character sets, the
value of each character after 0 in the above list of decimal digits shall be one greater than
the value of the previous.


Per cui quella conversione dovrebbe essere ok a prescindere dalla codifica usata


Non sapevo che questo aspetto fosse nello standard (è interessante che usino praticamente le stesse parole tutte e due). In effetti, non avrebbe molto senso avere una codifica che non rispettasse quella proprietà.

vict85
"cooper":
vi ringrazio per gli interventi che domani mi leggerò con calma. :D
detto questo, mi sembra strano ci richiedesse una risoluzione di quel tipo per due ragioni: la prima, come detto, è che non abbiamo trattato codice ASCII e quindi per me quei pezzi di codice sono nuovi; la seconda è che è una prova scritta (con carta e penna) e sarebbe impensabile sapere a memoria tutti i codici. :|


Il punto del mio messaggio è appunto che non dovresti usare proprietà specifiche dell'ASCII. Come ha detto Obidream la proprietà che usa lui è prevista dallo standard e quindi da tutti i sistemi (o per lo meno da tutti i compilatori).

Per altre cose risulta utile usare la libreria standard cctype .

cooper1
"vict85":
Il punto del mio messaggio è appunto che non dovresti usare proprietà specifiche dell'ASCII. Come ha detto Obidream la proprietà che usa lui è prevista dallo standard e quindi da tutti i sistemi (o per lo meno da tutti i compilatori).

non avevo recepito questa cosa.
l'ultimo dubbio e poi credo di essere apposto:
anzichè passare come argomento un [inline]int c[/inline] è lo stesso se passo un [inline]char c[/inline], giusto? anche perchè i char in qualche modo comprendono gli int. è giusto perchè nel testo è specificato esattamente che prende in ingresso un char e non un int. l'algoritmo ora mi è chiaro.

Super Squirrel
Se la traccia dice di passargli un char, allora passagli un char.

Poi hai aggiustato il for nel main?

Obidream
"cooper":
[quote="vict85"]Il punto del mio messaggio è appunto che non dovresti usare proprietà specifiche dell'ASCII. Come ha detto Obidream la proprietà che usa lui è prevista dallo standard e quindi da tutti i sistemi (o per lo meno da tutti i compilatori).

non avevo recepito questa cosa.
l'ultimo dubbio e poi credo di essere apposto:
anzichè passare come argomento un [inline]int c[/inline] è lo stesso se passo un [inline]char c[/inline], giusto? anche perchè i char in qualche modo comprendono gli int. è giusto perchè nel testo è specificato esattamente che prende in ingresso un char e non un int. l'algoritmo ora mi è chiaro.[/quote]
Sono gli int a comprendere i char, comunque è un refuso da parte mia, è che nella libreria standard del C le funzioni che hanno a che fare coi caratteri hanno sempre(? o quasi) come parametro un int per cui tendo a fare così anche io, per cui sì, va bene anche un char

cooper1
"Obidream":
Sono gli int a comprendere i char, comunque è un refuso da parte mia, è che nella libreria standard del C le funzioni che hanno a che fare coi caratteri hanno sempre(? o quasi) come parametro un int per cui tendo a fare così anche io, per cui sì, va bene anche un char

:smt023
"Super Squirrel":
Poi hai aggiustato il for nel main?

avrei risolto con uno switch (anche se forse è un po' tedioso). qualche post fa ho postato come avrei cambiato il tutto
EDIT: ho pensato che non va bene nemmeno così perchè se la inserisco sbagliata salto un'entrata del vettore. lo modificherei così:
unsigned int counter=0;
for( ; ;){
  char p;
  cin>>p;
  switch(guarda(p)){
           case 0: 
                     es.punti[i]=p;
                     counter++;
                     break;
             ecc ecc
   }
  if(counter == es.dimensione) break;
}

così dovrei poter continuare ad inserire fino ad esaurimento posti

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.