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 sempre la versione di Slackware usata e la versione del Kernel. Questi dati aiutano le persone che possono rispondere.
2) Specificare sempre il tipo di shell (bash, sh, csh, etc...)
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 dell'ultima regola 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 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
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 911
Iscritto il: mer apr 25, 2007 14:07
Località: Bari (Provincia)
Distribuzione: ArchLinux

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
d4z_c0nf
Packager
Packager
 
Messaggi: 1266
Iscritto il: mar mar 14, 2006 19:07
Località: Salerno
Nome Cognome: Rocco Aliberti
Slackware: current64
Kernel: 3.2.13
Desktop: awesome 3.4.11

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
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 911
Iscritto il: mer apr 25, 2007 14:07
Località: Bari (Provincia)
Distribuzione: ArchLinux

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
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 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
FireEater
Linux 2.6
Linux 2.6
 
Messaggi: 508
Iscritto il: sab feb 05, 2005 1: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 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
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 911
Iscritto il: mer apr 25, 2007 14:07
Località: Bari (Provincia)
Distribuzione: ArchLinux

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
FireEater
Linux 2.6
Linux 2.6
 
Messaggi: 508
Iscritto il: sab feb 05, 2005 1: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 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:
Avatar utente
SIV
Linux 2.6
Linux 2.6
 
Messaggi: 911
Iscritto il: mer apr 25, 2007 14:07
Località: Bari (Provincia)
Distribuzione: ArchLinux


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite