Newsgroup: it.comp.lang.c
Titolo: bo?

ciao, non riesco a capire una cosa:
ho compilato con successo un mio programmino, e gcc non mi da errori
di compilazione, neanche warning, ma, quando lancio l'eseguibile mi fa
inserire l'input (perciň il main funziona) poi quando,
presumibillmente, viene chiamata l'unica funzione mi scrive:
segmentation fault (core dumped)
che significa?
grazie
		gabo


Qualsiasi cosa :)  Il segmentation fault significa in parole povere
che hai cercato di accedere alla memoria dove non ti era permesso
(cari e vecchio puntatori :) ). Il core dump significa che lo stato
della memoria e' stato messo su file (per eventuali debug futuri).
Una cosa che in genere provoca core dump (legge di Murphy permettendo)
e' questa:
<CODE>
char * stringa= "stringa\0";
printf("Stringa = %s", stringa);
getchar();
printf("Stringa = %s, *stringa);
/*BOOM*/
</CODE>
Prova a lanciare questo codice... nella prima printf tutto bene, nella
seconda fai un deferenziamento di troppo e BOOM.
Mox :)


Che c'č un bug nella funzione. Posta il codice, cosě qualcuno ci puň
dare un'occhiata.

 printf("Stringa = %s, *stringa);
		   ^^^^^
Piccolo errore: manca un " per chiudere la stringa:
printf("Stringa = %s", *stringa);
Cecco

printf("Stringa = %s", *stringa);
Ops, non riesco a far crashare quando voglio, ma ci riesco benissimo
quando non voglio :P
Scusate e grazie Cecco :)
Mox

che significa?
Sicuramente non hai allocato abbastanza memoria per qualche
puntatore.  Posta il codice e sapro' risponderti.
-- 
The Follet

On Mon, 15 Oct 2001 20:37:42 GMT, thef...@thefollet.bye (The Follet)
wrote:

http://www.di.unito.it/~deligu/didattica/algo/EsLabAlg.html
 
Questo è l'indirizzo al quale potete trovare gli esercizi  che il mio
docente di algoritmi ci assegna, con relative soluzioni (a volte).
Io trovo che il testo sia scritto in modo molto artificioso, ma ciò
che non capisco sono le soluzioni!!! le funzioni per la gestione delle
liste (WriteList, ecc) io ho provato a compilarle, gcc me le compila,
ma poi non funzionano...
Per quanto riguarda  le pile non sono riuscito a capire il suo uso
dello stack, per cui ho provato ad implementare una mia versione, che
è appunto il codice incriminato, miostack.c:
________MIOSTACK.C_________
/*       GESTIONE DELLE PILE (STACK). LIFO       */
/*       implementazione tramite le liste                      */
#include <stdio.h>
#include "stack.h"
stack s;
int fact(int x);             /* calcola il fattoriale simulando la  
                                    ricorsione mediante l'uso di uno
                                    stack */
int fact(int x)
{  stack s = EmptyStack;
   int arg, val, control;
   while (top(s) != 1)
   {  s = push(x, s);
      arg = top(s);
      if (arg != 1)
        {  s = push(-1, s);
           val = top(s);
           --x;
        }
      else
       {  s = push(1, s);
          val = top(s);
       }
   }
   control = top(s);
   while (control != x)
   {  s = pop(s);
      s = pop(s);
      s = pop(s);
      control = top(s);
      s = push((val * top(s)), s);
      val = top(s);
   }
   return val;
}
main()
{  int x;
 scanf("%d", &x);
 printf("%d%",fact(x));
}
_________STACK.H___________
/*       GESTIONE DELLE PILE (STACK). LIFO       */
/*       implementazione tramite le liste                       */
/*                 header file                                      */
#include <stdio.h>
#include "liste.h"  /* mi serve per le definizioni dei tipi, per le */
                             /* funzioni Cons, Tail, ecc.... */
typedef ListT stack; /* come ListT per le liste */
const EmptyStack = NULL;
Boolean isEmptyStack(stack s);
stack push(T x, stack s);
stack pop(stack s);
T top(stack s);
/* implementazione */
Boolean isEmptyStack (stack s)
{
  return (isEmptyList(s));
}
stack push(T x, stack s)
{
  return Cons(x, s);
}
stack pop(stack s)
{
  stack t = Tail(s);
  free(s);
  return t;
}
T top(stack s)
{
  return Head(s);
}  
_______LISTE.H________
/*	PROGRAMMA PER LA GESTIONE DI LISTE           */
/*                header file                                 */
#include <stdio.h>
/* definisco il tipo Lnode,costituito da un intero info
e da un puntetore all'Lnode successivo (next) */
typedef enum {false, true} Boolean;
typedef int T;
/* ListT è un puntatore a INode */
typedef struct lnode* ListT;
typedef struct lnode
{
	T info;
        ListT next;
} Lnode;
/*
Prototipi
costruttori dell'ADT Liste
*/
const ListT emptylist = NULL;
ListT Cons (T x, ListT l);
Boolean IsEmptyList (ListT l);
T Head (ListT l);
/* pre: l != EmptyList */
ListT Tail (ListT l);
/* pre: l != EmptyList */
/* implementazione */
ListT Cons (T x, ListT l)
/* funzione per l'inserimento sequenziale di
elementi nella lista */
{
	ListT p;
	p = (ListT) malloc (sizeof(Lnode));
		p->info = x;
		p->next = l;
		return p;
    /* else
		printf("memoria insufficiente");
	  return p; */
}
Boolean isEmptyList (ListT l)
/* restituisce true se la lista è vuota */
{
	return (l == emptylist);
}
T Head (ListT l)
{
	return l->info;
}
ListT Tail (ListT l)
{
	return l->next;
}
Mi piacerebbe sapere cosa ne pensate del mio docente, è molto bravo a
spiegare il C in teoria, ma quando si parla di mettersi a
programmare... sigh :((

programmare... sigh :((
Su su, ho trovato di peggio :)
Il C non l'ho studiato dai docenti, se non la base teorica, ma sul
K&R, sui libri di Koenig e prendendo bastonate sul NG :P
Ma le ADT le hai fatte tu o il prof? Se le hai fatte tu e' ora che
impari a mettere i controlli... se le ha fatte il prof... beh, fagli
notare che hanno la robustezza dei server Microzozz... ehm, scusate...
dicevo, fagli notare che mancano dei controlli (tutti praticamente) e
dovrebbe implementarli :)
Mox (dopo il lavoro che ho fatto sulle ADT conosco ogni possibile
errore fattibile deferenziando puntatori... e ogni possibile
imprecazione da lanciare in casi simili) :P

programmare... sigh :((
Ti faccio una domanda: secondo te ha senso che un ingegnere
disegni un palazzo e poi non lo sappia costruire ?
-- 
The Follet

 accademiche rovinano il cervello degli studenti ;)
il programmatore dovrebbe scrivere codice il piu' chiaro possibile. Nel 
caso del fattoriale entrambe le forme sono chiare ma, personalmente, 
preferisco la piu' elegante ricorsiva. Se sono le prestazioni a 
preoccuaparti puoi anche stare tranquillo: un compilatore decente produrra' 
lo stesso identico codice (gcc 3 fa proprio questo).
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

preferisco la piu' elegante ricorsiva. 
Secondo me non e' affatto la via piu' elegante.
La via piu' elegante, sempre secondo me, e' la piu' semplice
:
int fatt(int x)
{
    int r; 
    for (r = 1; x > 0; x--)
    {
        r = r * x;
    } 
    return r;
}
Molto piu' leggibile e semplice da capire.
Mai complicare le cose oltre il necessario.
In quanto alle prestazioni, temo proprio che tu ti stia
sbagliando.  
Non ti fare ingannare dalle ottimizzazioni del compilatore.
E' preferibile un codice che consiste di sole
moltiplicazioni, rispetto ad uno che consuma parecchia
memoria (al crescere del numero per il quale effettuare il
calcolo) e rallenta le operazioni.
-- 
The Follet

}
...ops...
int fatt(int x)
{
    int r = 1; 
    for ( ; x > 0; x--)
    {
        r = r * x;
    } 
    return r;
}
-- 
The Follet

 ....ops...
Cambiava nulla...
-- 
"Windows 95 is a 32-bit shell for a 16-bit extension to an 8-bit
operating system designed for a 4-bit microprocessor by a 2-bit
company that can't stand one bit of competition."
La mia (penosa, per ora) homepage: 
http://digilander.iol.it/burton666

Cambiava nulla...
Cambiava, cambiava, il fattoriale di 0 nel primo caso non
veniva calcolato.
-- 
The Follet

 veniva calcolato.
Uhm... ma scusa, hai semplicemente spostato il punto in cui inizializzi
r.... da dentro l'istruzione for a fuori.... cosa cambia?


 r.... da dentro l'istruzione for a fuori.... cosa cambia?
Se x = 0, non si entra nemmeno nel ciclo for, e l'r nella versione
precedente era inizializzato dentro di esso.
Cecco

 precedente era inizializzato dentro di esso.
sbagliato.
il primo termine del for viene SEMPRE eseguito, e' indipendente dalla
condizione di mantenimento del ciclo
altrimenti come mi spieghi il funzionamento di questo strausatissimo
ciclo for
int n;
for( n=0 ; n<100 ; n++ ) ...
ciao
donCiccio


Beh, in effetti la strauso anche io questa forma. Non so per quale
motivo mi sia venuta in mente questa ca**ata.
Cecco

imprecazione da lanciare in casi simili) :P
grazie mille!!!!

The Follet
thanks
		gabo

 calcolo) e rallenta le operazioni.
 
Non hai capito. Il gcc genera lo *stesso* codice. Essendo i computer 
moderni macchine deterministiche, due codici identici con lo stesso input 
produrranno la stessa sequenza di operazioni.
La rimozione della ricorsione di coda (quella del fattoriale) e' una 
tecnica di ottimizzazione piuttosto diffusa e i buoni compilatori 
trasformano automaticamente il codice ricorsivo in iterativo (dato che le 
funzioni ricorsive in coda non utilizzano alcuno stack).


 trasformano automaticamente il codice ricorsivo in iterativo (dato che
Certo. Ma il tuo codice potrebbe venire compilato da un compilatore un
po' meno buono, che magari NON trasforma le funzioni ricorsive in
iterative, e secondo me e' importante fare le cose in modo che su
qualunque piattaforma funzioni piu' o meno allo stesso modo.


 tecnica di ottimizzazione piuttosto diffusa e i buoni compilatori 
Ribadisco: qui si parla di algoritmi, non di cio' che si ottiene
con l'ottimizzazione di un particolare compilatore.
-- 
Posted from  [80.105.34.80] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 con l'ottimizzazione di un particolare compilatore.
veramente non abbiamo mai detto che parlavamo dell' "algorimo di 
calcolo del fattoriale". La discussione e' nata riferendoci ad una 
particolare implementazione dell'algoritmo.


 qualunque piattaforma funzioni piu' o meno allo stesso modo.
 
qui si potrebbe aprire un dibattito sul se e quando ottimizzare il 
codice. Io sono di questa opinione: prima di tutto scrivi il tuo 
programma nel modo piu' semplice, chiaro ed elegante possibile. Poi 
misuri le prestazioni (con uno strumento di profiling) e, *se e solo 
se* esse non sono soddisfacenti vai a vedere quali sono i "colli di 
bottiglia" del tuo programma, ottimizzandoli; sono contrario 
all'"ottimizzazione precoce", quindi trasformerei la mia funzione 
fattoriale solo nei casi di effettivo bisogno. Ovvio, se tu reputi la 
versione iterativa piu' elegante il problema non si pone neppure.


particolare implementazione dell'algoritmo.
Vedi sopra.
L'implementazione dell'algoritmo prescinde dal compilatore
utilizzato per compilare il sorgente (perche' il sorgente e'
espresso in C che e' un linguaggio standard).
-- 
The Follet

fattoriale solo nei casi di effettivo bisogno. 
Tu continua pure a scriverla in modo ricorsivo :) pero'
quello che vorrei farti capire e' che non puoi affermare che
i due algoritmi hanno la stessa efficienza (considerando la
loro espressione in un linguaggio di programmazione
particolare) solo perche' il tuo compilatore particolare da'
lo stesso risultato (per via delle ottimizzazioni).
Anch'io sono contrario delle ottimizzazioni precoci (Knuth
ci insegna che sono sbagliate ed e' intuitivo capirne il
perche'), ma scrivere un algoritmo come quello del
fattoriale per via iterativa, anziche' ricorsiva, non e'
affatto un'ottimizzazione precoce, e' un modo realmente piu'
intelligente di esprimere quel calcolo (IMHO).
Per esempio, anche scrivere i valori di una lista possono
essere scritti per via ricorsiva:
void scrivi_lista(item *p)
{
    if (p) 
    {
       printf("%d", p->valore);
       scrivi_lista(p->next);
    }
}
Ma a me sembra un modo poco intelligente di scrivere la
stessa cosa:
void scrivi_lista(item *p)
{
     while (p)
     {
           printf("%d", p->valore);
           p = p->next;
     }
}
-- 
The Follet

 Non si sta parlando dei punti 1 e 3, ma del 2.
Con queste precisazioni posso essere anche d'accordo. Considerato dal 
punto di vista (2) effettivamente la versione ricorsiva e' piu' lenta 
di quella iterativa.
Anche se, IMHO, non vedo l'utilita' di ragionare secondo il punto di 
vista (2), dato che non e' di utilita' ne' teorica (per la teoria c'e' 
il punto (1) ) ne' pratica (per la quale occorre considerare il punto 
(3) ).


 intelligente di esprimere quel calcolo (IMHO).
Scusa, cerca di quotare un po' meglio. Ho scritto:
"Ovvio, se tu reputi la versione iterativa piu' elegante il problema 
non si pone neppure."
Quindi, dato il tuo punto di vista, il problema non si pone.
Personalmente credo che la versione ricorsiva sia piu' aderente alla 
definizione matematica di fattoriale. Ma, cmq, ormai siamo nel campo 
delle opinioni e quindi c'e' ben poco su cui discutere.


vista (2)
Invece ti sbagli, IMHO, non tutti i compilatori utilizzano
le stesse ottimizzazioni e bisogna ragionare come se le
ottimizzazioni non ci fossero.
-- 
The Follet

definizione matematica di fattoriale. 
Veramente il fattoriale e' matematicamente inteso come un
prodotto di termini, quindi e' piu' intuitivo pensarlo per
via iterativa.  Comunque ognuno la pensi come vuole :)
-- 
The Follet

bravo
"The Follet" <thef...@thefollet.bye> ha scritto nel messaggio
news:3bdc67c5...@news.tin.it...
