Pagina 1 di 1

Numeri casuali e Segmentation fault in C - [Risolto]

Inviato: gio 2 lug 2009, 20:00
da SIV
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

Re: Numeri casuali e Segmentation fault - C

Inviato: gio 2 lug 2009, 20:26
da d4z_c0nf
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

Re: Numeri casuali e Segmentation fault - C

Inviato: gio 2 lug 2009, 20:43
da SIV
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?

Re: Numeri casuali e Segmentation fault - C

Inviato: gio 2 lug 2009, 21:01
da GioPower
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.

Re: Numeri casuali e Segmentation fault - C

Inviato: gio 2 lug 2009, 21:15
da FireEater
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

Re: Numeri casuali e Segmentation fault - C

Inviato: gio 2 lug 2009, 21:27
da SIV
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:

Re: Numeri casuali e Segmentation fault - C

Inviato: gio 2 lug 2009, 22:15
da FireEater
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? :)

Re: Numeri casuali e Segmentation fault - C

Inviato: ven 3 lug 2009, 12:17
da SIV
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: