PDA

View Full Version : [C] Esercizi vari su liste


xbubbax
13-08-2007, 08:39
Si scriva una funzione ricorsiva che data una lista di caratteri L calcoli il numero di cifre contenute nella lista.

int conta_cifre(L_PTR L)

a->3->f->d->j->4->NULL la funzione restituirà 2


#include <stdio.h>
struct nodo{
int data;
struct nodo *next}
int main(){

typedef struct nodo NODO;
typedef struct nodo *NEXT;







int conta_cifre(NODO L1){
if(L1->data!=NULL){
if((L1->data>='0')&&(L1->data<=9)){
return (L1->data-'0') + conto_cifre(L1->NEXT);}
else return conto_cifre(L1->NEXT);}
else return 0;}


La funzione dovrebbe essere corretta, ma non so se ho dichiarato bene la struttura e ho usato bene i nomi della lista.

xbubbax
13-08-2007, 08:44
Ho corretto qualcosa
#include <stdio.h>
struct nodo{
int data;
struct nodo *next}
int main(){

typedef struct nodo LISTA;
typedef struct nodo *L_PTR;







int conta_cifre(l_PTR L){
if(L->data!=NULL){
if((L->data>='0')&&(L->data<=9)){
return L->data + conto_cifre(L->next);}
else return conto_cifre(L1->next);}
else return 0;}

xbubbax
13-08-2007, 08:56
Qesto eserczio invece cancella tutti i numeri K e i multipli di K dalla lista

#include <stdio.h>
struct nodo{
int data;
struct nodo *ptr;};

int main(){
typedef struct nodo LISTA;
typedef struct nodo *L_PTR;







int cancellamultipli(L_PTR L, int k){
int temp;
int elem=0;
while(L->data!=NULL){
resto=(L->data)%k;
elem=L->data;
if((elem==k)!!(resto==0){
temp=L;
free(temp);}
L=L->next;}

xbubbax
13-08-2007, 09:04
HO RISCRITTO IL PRIMO ESERCIZIO

#include <stdio.h>
struct nodo{
int data;
struct nodo *next}
int main(){

typedef struct nodo LISTA;
typedef struct nodo *L_PTR;







int conta_cifre(l_PTR L){
if(L!=NULL){
if((L>='0')&&(L<='9')){
return L + conto_cifre(L->next);}
else return conto_cifre(L->next);}
else return 0;}

Mixmar
13-08-2007, 09:08
#include <stdio.h>
struct nodo{
int data;
struct nodo *next}
int main(){

typedef struct nodo LISTA;
typedef struct nodo *L_PTR;







int conta_cifre(l_PTR L){
if(L->data!=NULL){
if((L->data>='0')&&(L->data<=9)){
return L->data + conto_cifre(L->next);}
else return conto_cifre(L1->next);}
else return 0;}

Mmmm, è una vita che non gioco col C, ma credo che riscritta così dovrebbe funzionare meglio:


int conta_cifre(l_PTR L){
if(L!=NULL){
if((L->data>='0')&&(L->data<='9'))
return 1 + conto_cifre(L->next);
else
return conto_cifre(L->next);
} else
return 0;
}


Poi potresti dichiare 'data' come char direttamente, anzichè come int. Ah, fai attenzione perchè una lista circolare manderebbe il programma in loop.

xbubbax
13-08-2007, 09:15
Comq il programma deve sommare tutte le cifre che compaiono nella stringa, non incrementare un contatore.

comq come l'avevo scritta io, tranne per quell'errore L!=NULL avrebbe funzionato?

Mixmar
13-08-2007, 10:31
Comq il programma deve sommare tutte le cifre che compaiono nella stringa, non incrementare un contatore.

Però anche l'esempio che avevi riportato all'inizio funzionava come avevo immaginato io: trova due cifre ('3' e '4') e restituisce 2. :wtf:

comq come l'avevo scritta io, tranne per quell'errore L!=NULL avrebbe funzionato?

Non funzionerebbe perchè tu scrivi:


return L + conto_cifre(L->next);


Ma L->data (non L, quello è il puntatore alla struttura, prima l'avevi scritto giusto), che sia un int od un char, contiene il codice ASCII del carattere che c'è dentro, anche se è una cifra, e non il valore della cifra che quel carattere rappresenta; ti conviene scrivere:


return (L->data - '0') + conto_cifre(L->next);


Così sottrai al codice della cifra il codice di '0', e siccome nel codice ASCII le cifre sono ordinate in modo crescente e sono in successione, ottiene proprio il risultato che ti interessa.

xbubbax
13-08-2007, 10:34
si hai ragione, deve solo contare quante cifre ci sono

xbubbax
13-08-2007, 10:49
Ne approfitto del topic per chiedervi perchè non funziona questo esercizio che verifica se due vettori hanno esattamente gli stessi elementi. Restituiste 0 se sono diversi e 1 se hanno gli stessi elementi ma anche in posizioni diverse

#include <stdio.h>
int main(){
int n;
int m;
int a[n];
int b[m];
int risultato=0;
int x;
int y;
int i;
int j;
printf("Inserisci la lunghezza del vettore a:\n");
scanf("%d", &n);

for(i=0;i<n;i++){
printf("Inserisci un elemento:\n");
scanf("%d", &x);

a[i]=x;}

printf("Inserisci la lunghezza del vettore b:\n");
scanf("%d", &m);

for(i=0;i<m;i++){
printf("Inserisci un elemento:\n");
scanf("%d", &y);

b[i]=y;}

for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(a[i]==b[j]){
risultato=1;
break;}}

if(risultato=0){break;}
risultato=0;}
for(j=0;j<m;j++){
for(i=0;i<n;i++){
if(b[j]==a[i]){
risultato=1;
break;}}

if(risultato=0){break;}
risultato=0;}

printf("%d\n", risultato);

while(getchar() != '\n');
printf("Premere INVIO per continuare...");
getchar();}

andbin
13-08-2007, 10:50
La "mia" soluzione:
int conta_cifre (L_PTR ptr)
{
if (ptr != NULL)
return conta_cifre (ptr->next) + (ptr->data >= '0' && ptr->data <= '9');

return 0;
}

cionci
13-08-2007, 10:57
xbubbax: mi nasce qualche dubbio sul tuo modo di indentare il codice...attento che in questo modo superi molto spesso il limite dei caratteri nella linea. Se in un esercizio il limite non si mette mai, nei progetti seri il limite è sempre imposto fra gli 80 e 100 caratteri.

andbin
13-08-2007, 10:59
int n;
int m;
int a[n];
int b[m];Non va affatto bene. La dimensione del vettore è stabilita al momento stesso della dichiarazione. A parte il fatto che la definizione di un array a lunghezza variabile è possibile solo in C++ o nel C99 ma non nel "ANSI C". Comunque quanto valgono n e m?? Non lo sai (non sono inizializzate), quindi la lunghezza degli array è ... boh??

Quindi non serve a nulla fare in seguito: scanf("%d", &n), la allocazione dell'array non è "retroattiva".....

xbubbax
13-08-2007, 11:15
andbin sarà sbagliato ma ti assicuro che funziona.

come dovrei scrivere?

comq mi interessa soprattutto sapere cosa sbaglio nel resto del programma, cioè nel programma vero e proprio, questi sono dettagli:D


per il numero di righe posso sempre andare a capo, mica devo scrivere tutto su un'unica riga, o no

Mixmar
13-08-2007, 11:19
La "mia" soluzione:
int conta_cifre (L_PTR ptr)
{
if (ptr != NULL)
return conta_cifre (ptr->next) + (ptr->data >= '0' && ptr->data <= '9');

return 0;
}

Molto più concisa ed elegante della mia! :D

Io non avrei mai fatto l'operazione del passo ricorsivo, perchè non avrei mai pensato che, in fondo, un valore "booleano" per il C è pur sempre un byte posto ad 1, cioè appunto un int che vale 1 o 0 a seconda del valore del test, e che quindi puoi sommarlo al risultato della ricorsione tranquillamente: è troppo tempo che lavoro in Java e sono diventato "strongly-typed"... :D

andbin
13-08-2007, 11:25
questi sono dettagli:D Hai voglia a chiamarlo "dettaglio" non sapere quanti elementi sono stati allocati per gli array......

EDIT: avevo risposto qui (http://www.hwupgrade.it/forum/showthread.php?t=1322787) in passato ad una questione del genere.

cionci
13-08-2007, 11:26
per il numero di righe posso sempre andare a capo, mica devo scrivere tutto su un'unica riga, o no
Certo che no...ma il problema è che solitamente si ritorna a scrivere allineati con l'inizio dell'indentazione (anzi molti ci mettono anche un tab) e quindi se sei già in fondo con l'ultima indentazione ti rimarranno pochissimi caratteri.
Inoltre con il tuo metodo con pochissimi blocchi annidati raggiungi il termine della riga.
Se ad esempio avessi una funzione:
unsigned double funzioneCheFaQualcosa(unsigned int primo, unsigned int secondo, unsigned int terzo)

Quanto spazio ti resta ? Molto poco ;) E una funzione con un dichiarazione di queste dimensioni non è per niente rara !!!

sottovento
13-08-2007, 11:39
La "mia" soluzione:
int conta_cifre (L_PTR ptr)
{
if (ptr != NULL)
return conta_cifre (ptr->next) + (ptr->data >= '0' && ptr->data <= '9');

return 0;
}

Bene! C'e' pero' da dire che "ufficialmente":
- il valore boolean FALSE e' associato all'intero di valore 0;
- il valore boolean TRUE e' associato a qualsiasi numero diverso da zero;

Pertanto un compilatore che decida di ritornare 3, 5 o -1 come esito di una espressione booleana, sarebbe perfettamente accettabile, e magari e' anche probabile che succeda quando si attivano le opzioni di ottimizzazione... ;)

In tal caso sarebbe meglio usare un operatore ternario e scongiurare il pericolo.

xbubbax
13-08-2007, 11:53
Qualcuno mi aiuta a capire l'altro esercizio?

Mixmar
13-08-2007, 13:33
Qualcuno mi aiuta a capire l'altro esercizio?

:) tenchiù

Edit

andbin
13-08-2007, 15:25
Bene! C'e' pero' da dire che "ufficialmente":
- il valore boolean FALSE e' associato all'intero di valore 0;
- il valore boolean TRUE e' associato a qualsiasi numero diverso da zero;

Pertanto un compilatore che decida di ritornare 3, 5 o -1 come esito di una espressione booleana, sarebbe perfettamente accettabile, e magari e' anche probabile che succeda quando si attivano le opzioni di ottimizzazione... ;) A dire il vero il libro "Il linguaggio C, 2° ed." di Kernighan/Ritchie dice, riporto testuali parole:
Gli operatori < (minore), > (maggiore), <= (minore di o uguale a) e >= (maggiore di o uguale a) generano tutti 0 se la relazione specificata è falsa e 1 se è vera. Il tipo del risultato è int.
Nella espressione che ho scritto io c'è solo di mezzo un AND logico, il che non cambia nulla sui valori forniti dagli operatori relazionali.

In tal caso sarebbe meglio usare un operatore ternario e scongiurare il pericolo.Certo, sarebbe altrettanto corretto.

71104
13-08-2007, 16:45
andbin sarà sbagliato ma ti assicuro che funziona. ci vuole poco a mandarlo a puttane:

#include <stdio.h>

int main() {
return work();
}

int work(){
int n;
int m;
int a[n];
int b[m];
int risultato=0;
int x;
int y;
int i;
int j;
printf("Inserisci la lunghezza del vettore a:\n");
scanf("%d", &n);

for(i=0;i<n;i++){
printf("Inserisci un elemento:\n");
scanf("%d", &x);

a[i]=x;}

printf("Inserisci la lunghezza del vettore b:\n");
scanf("%d", &m);

for(i=0;i<m;i++){
printf("Inserisci un elemento:\n");
scanf("%d", &y);

b[i]=y;}

for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(a[i]==b[j]){
risultato=1;
break;}}

if(risultato=0){break;}
risultato=0;}
for(j=0;j<m;j++){
for(i=0;i<n;i++){
if(b[j]==a[i]){
risultato=1;
break;}}

if(risultato=0){break;}
risultato=0;}

printf("%d\n", risultato);

while(getchar() != '\n');
printf("Premere INVIO per continuare...");
getchar();}


come dovrei scrivere? prima preleva n ed m, poi dichiara i vettori.

comq mi interessa soprattutto sapere cosa sbaglio nel resto del programma, cioè nel programma vero e proprio, questi sono dettagli:D bon Dieu -_-'

cionci
13-08-2007, 17:00
prima preleva n ed m, poi dichiara i vettori.

Mi sa che gli serve l'allocazione dinamica...

xbubbax
14-08-2007, 10:08
e come avrei dovuto scrivere per inizializzare i vettori?



i resto del programma è giusto?

grazie

Mixmar
14-08-2007, 10:14
Ma poi, scusate, perchè "n" ed "m"? Non dovrebbe essere comunque almeno "n == m" per poter procedere? :mbe:

xbubbax
14-08-2007, 10:23
no, le lunghezze possono essere diverse

per esempio gli array A={1,3,3,3,5,6} e B={1,3,5,6}
sono uguali