Repository 32bit  Forum
Repository 64bit  Wiki

Numeri casuali e Segmentation fault in C - [Risolto]

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

Numeri casuali e Segmentation fault in C - [Risolto]

Messaggioda SIV » gio lug 02, 2009 19:00

Ragazzi stavo facendo qualche esercizio in C.

Devo estrarre un numero casuale tratto dal gruppo -> 6,10,14,18,22 senza usare particolari funzioni e neanche degli array, solo la funzione (s)rand e dei controlli.

Ho scritto questo:
Codice: Seleziona tutto
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int check();
int i;

int main(){

int number=0;
number=check();
printf("Numero estratto: %d\n", number);

return 0;

}

int check(){

srand(time(NULL));
i = 6+rand()%22;

if (i==6 || i==10 || i==14 || i==18 || i==22){return i;}

else {return check();}

}


Però a volte va in seg fault. Ecco l'output:
Codice: Seleziona tutto
muller:~/temp# gcc 5.14-c.c
muller:~/temp# ./a.out     
Numero estratto: 22
muller:~/temp# ./a.out
Numero estratto: 18
muller:~/temp# ./a.out
Numero estratto: 18
muller:~/temp# ./a.out
Numero estratto: 22
muller:~/temp# ./a.out
Segmentation fault
muller:~/temp# ./a.out
Numero estratto: 14
..
muller:~/temp# ./a.out
Segmentation fault
muller:~/temp# ./a.out
Segmentation fault
...


Ho come l'impressione che se il numero estratto non sia tra quelli elencati e quindi vada all'else nella funzione check, vada in seg fault.

:-k :-k
Ultima modifica di SIV il ven lug 03, 2009 11:17, modificato 1 volta in totale.
Avatar utente
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 918
Iscritto il: mer apr 25, 2007 13:07
Località: Bari (Provincia)

Re: Numeri casuali e Segmentation fault - C

Messaggioda d4z_c0nf » gio lug 02, 2009 19:26

Perchè non puoi usare gli array?
In ogni caso anche non usando gli array come "struttura" puoi simularli, chi te lo vieta?

Codice: Seleziona tutto
 switch( i )
     {
        case 0:   return 6;
        case 1:   return 10;
        // ecc ecc
     }


Il problema del segfault può essere che "ricorre" troppo, visto che tra 0 e 22 ci sono 23 numeri e beccare giusto uno di quei sei non è facilissimo. Elimina la ricorsione insomma, anche perchè mi pare eccessivo usarla in un caso come questo...
rock
Avatar utente
d4z_c0nf
Packager
Packager
 
Messaggi: 1293
Iscritto il: mar mar 14, 2006 18:07
Località: Salerno
Nome Cognome: Rocco Aliberti
Slackware: 14.1-64bit
Kernel: 3.10.17
Desktop: xfce

Re: Numeri casuali e Segmentation fault - C

Messaggioda SIV » gio lug 02, 2009 19:43

Per gli array è proprio l'esercizio che lo richiede.

Comunque sia, se elimino la ricorsione, come faccio a scrivere una funzione che estrae un numero a caso e se non è nel "gruppo" di rifare la selezione?
Avatar utente
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 918
Iscritto il: mer apr 25, 2007 13:07
Località: Bari (Provincia)

Re: Numeri casuali e Segmentation fault - C

Messaggioda GioPower » gio lug 02, 2009 20:01

Guardando i numeri che devi ritornare, ho notato che rispettano la regola che:
Codice: Seleziona tutto
num =  6 + ( x * 4 )

dove num e' il numero di ritorno e x e' un numero casuale compreso tra [0,4].

Quindi io farei una cosa cosi:
Codice: Seleziona tutto
int main(...)
{
  //cose varie
  //...

  int num = rand(...) % 5;
  num *= 4;
  num += 6;
  printf("Numero estratto: %d\n", num);

  //altre cose varie
  //...
}


Non so se una soluzione del genere possa valere per l'esercizio in questione.
Avatar utente
GioPower
Packager
Packager
 
Messaggi: 46
Iscritto il: lun ott 13, 2008 13:26
Nome Cognome: Luca Giona
Slackware: 13 x86_64
Kernel: 2.6.29
Desktop: xfce

Re: Numeri casuali e Segmentation fault - C

Messaggioda FireEater » gio lug 02, 2009 20:15

Il segmentation fault è probabilmente dovuto ad uno stack overflow. Al contrario di come si potrebbe immaginare la programmazione ricorsiva è computazionalmente molto più pesante rispetto a quella iterativa. Questo succede perchè il contesto della funzione ricorsiva viene caricato sullo stack ad ogni chiamata.

La soluzione riportata da GioPower è senza dubbio la migliore e probabilmente è quella che ha pensato chi ha scritto l'esercizio.

Ad ogni modo una possibile riscrittura di quella funzione ricorsiva è:
sorvolando sul i = 6+rand()%22; che non è proprio l'ideale dato che estrae da 6 a 27...


Codice: Seleziona tutto
int check(){
for (int i = 6+rand()%22; (i!=6 && i!=10 && i!=14 && i!=18 && i!=22); i =  6+rand()%22;)
__noop; // o {}

return i;
}


Il random seed va inizializzato nel main, farlo all'interno della funzione in questo caso non serve.

FireEeater
Avatar utente
FireEater
Linux 2.6
Linux 2.6
 
Messaggi: 508
Iscritto il: sab feb 05, 2005 0:00
Località: Cagliari <---> Torino
Nome Cognome: Giuseppe M.
Slackware: Current
Kernel: 2.6.32.7-smp
Desktop: kde 4.3.4

Re: Numeri casuali e Segmentation fault - C

Messaggioda SIV » gio lug 02, 2009 20:27

Ok ragazzi grazie a tutti.

- Sì sicuramente la soluzione scritta GioPower è quella pensata dallo scrittore.
- FireEater, potresti spiegarmi meglio la funzione check che hai scritto? :thumbright:
Avatar utente
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 918
Iscritto il: mer apr 25, 2007 13:07
Località: Bari (Provincia)

Re: Numeri casuali e Segmentation fault - C

Messaggioda FireEater » gio lug 02, 2009 21:15

Questo codice è equivalente, in italiano si potrebbe dire: Fintantoché i è diverso da uno di quei numeri(6,10,14,18,22) estrai un altro numero. Quando è i uguale esce dal ciclo e ritorna il numero presente in i.

Codice: Seleziona tutto
int check(){

int i = 6+rand()%22;
while (i!=6 && i!=10 && i!=14 && i!=18 && i!=22)
{
 i =  6+rand()%22;
}
return i;
}


__noop; significa no operation e serve a non fare nulla durante il ciclo for, le parentesi graffe aperte e chiuse sono la stessa cosa.

OK? :)
Avatar utente
FireEater
Linux 2.6
Linux 2.6
 
Messaggi: 508
Iscritto il: sab feb 05, 2005 0:00
Località: Cagliari <---> Torino
Nome Cognome: Giuseppe M.
Slackware: Current
Kernel: 2.6.32.7-smp
Desktop: kde 4.3.4

Re: Numeri casuali e Segmentation fault - C

Messaggioda SIV » ven lug 03, 2009 11:17

OK grazie FireEater, con il ciclo while ho capito il senso ed ho capito anche il ciclo for di prima. :D

Grazie a tutti :thumbright: :thumbright:
Avatar utente
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 918
Iscritto il: mer apr 25, 2007 13:07
Località: Bari (Provincia)


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite