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.
Avatar utente
SIV
Linux 2.6
Linux 2.6
Messaggi: 921
Iscritto il: mer apr 25, 2007 14:07

Numeri casuali e Segmentation fault in C - [Risolto]

Messaggioda SIV » gio lug 02, 2009 20: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 12:17, modificato 1 volta in totale.

Avatar utente
d4z_c0nf
Packager
Packager
Messaggi: 1296
Iscritto il: mar mar 14, 2006 18:07
Nome Cognome: Rocco Aliberti
Slackware: 14.1-64bit
Kernel: 3.10.17
Desktop: xfce
Località: Salerno

Re: Numeri casuali e Segmentation fault - C

Messaggioda d4z_c0nf » gio lug 02, 2009 20: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
SIV
Linux 2.6
Linux 2.6
Messaggi: 921
Iscritto il: mer apr 25, 2007 14:07

Re: Numeri casuali e Segmentation fault - C

Messaggioda SIV » gio lug 02, 2009 20: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
GioPower
Packager
Packager
Messaggi: 46
Iscritto il: lun ott 13, 2008 14:26
Nome Cognome: Luca Giona
Slackware: 13 x86_64
Kernel: 2.6.29
Desktop: xfce

Re: Numeri casuali e Segmentation fault - C

Messaggioda GioPower » gio lug 02, 2009 21: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
FireEater
Linux 2.6
Linux 2.6
Messaggi: 508
Iscritto il: sab feb 05, 2005 0:00
Nome Cognome: Giuseppe M.
Slackware: Current
Kernel: 2.6.32.7-smp
Desktop: kde 4.3.4
Località: Cagliari <---> Torino
Contatta:

Re: Numeri casuali e Segmentation fault - C

Messaggioda FireEater » gio lug 02, 2009 21: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
SIV
Linux 2.6
Linux 2.6
Messaggi: 921
Iscritto il: mer apr 25, 2007 14:07

Re: Numeri casuali e Segmentation fault - C

Messaggioda SIV » gio lug 02, 2009 21: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
FireEater
Linux 2.6
Linux 2.6
Messaggi: 508
Iscritto il: sab feb 05, 2005 0:00
Nome Cognome: Giuseppe M.
Slackware: Current
Kernel: 2.6.32.7-smp
Desktop: kde 4.3.4
Località: Cagliari <---> Torino
Contatta:

Re: Numeri casuali e Segmentation fault - C

Messaggioda FireEater » gio lug 02, 2009 22: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
SIV
Linux 2.6
Linux 2.6
Messaggi: 921
Iscritto il: mer apr 25, 2007 14:07

Re: Numeri casuali e Segmentation fault - C

Messaggioda SIV » ven lug 03, 2009 12: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:


Torna a “Programmazione”

Chi c’è in linea

Visitano il forum: Yahoo [Bot] e 1 ospite