miei programmi in c su knoppix e relativi problemi

anche_per_il_direttore

Nuovo Utente
63
2
salve, ho un problema con un programma che calcola il fattoriale, mi spiego, il programma che posto di seguito funziona ma quando decido di separare le funzioni non mi calcola piu il fattoriale.
il programma "non spezzato" si chiama pr27.c e funziona
il programma "spezzato" e suddiviso in tre codici
pr25.h che contiene la dichiarazione della funzione
pr25.c che contiene la definizione della funzione
pr25_main.c che contiene la main
ora quando compilo i tre codici non ottengo il fattoriale, come se la funzione non si attivasse.

qualcuno ha qualche idea?
grazie

PS seguono i listati dei 4 codici

C:
/* File: fattoriale.c */
/* Funzione ricorsiva che calcola il fattoriale di un numero >= 0
   Si ricorda che il fattoriale n! e' definito come:
 
      n! = 1         se n = 0
         n! = n*(n-1)!  se n > 0
    
         */
         /* Esempio di funzione ricorsiva */
    
         #include <stdio.h>
         int fattoriale(int);
    
         int fattoriale(int n)
         {
           if (n < 0) return -1; /* Fattoriale non e' definito per interi negativi! */
      
             if (n == 0) return 1;
               else return n*fattoriale(n-1);
               }
          
               int main(void)
               {
                 int n;
                   printf("Inserire un intero >= 0 : ");
                     scanf("%d", &n);
                       printf("Il fattoriale di %d e' %d\n", n, fattoriale(n));
                         return 0;
                         }
                    
                         /*
                           Nota: il fattoriale di un numero cresce molto velocemente. Per calcolare il
                             fattoriale di numeri grandi, modificare la funzione sostituendo int con long
                             */

questo e il pr25.h
C:
int fat(int);        //dichiarazione della funzione fattoriale

questo e il pr25.c
C:
#include"pr25.h"

int fat (int n)   //definizione della funzione fattoriale procedura ricorsiva

{


if (n==0)
return 1;
else
return n*fat(n-1);

}

questo e il pr25_main.c
C:
#include<stdio.h>
#include<stdlib.h>
#include"pr25.h"


int main() {

int n;

printf("inserisci il numero di cui vuoi calcolare il fattoriale\n",n);
scanf("%d",&n);

printf("il fattoriale di %d  e':\n",n,fat(n));

return 0;

}
 
Ultima modifica da un moderatore:

filoippo97

Utente Èlite
14,067
7,617
CPU
Intel Core I7 4930K @4.5GHz
Dissipatore
EKWB supremacy nickel
Scheda Madre
ASUS Rampage IV Black Edition
HDD
OCZ vertex 4 512GB | WD RE4 Enterprise Storage 2TB
RAM
16GB Corsair Dominator Platinum 2133MHz cas9 OC @2400MHz 9-11-11-31-2 1.65V
GPU
2-way SLI GTX 780Ti DirectCUII OC
Audio
TEAC UD-503 MUSES + HiFiMan HE-560 V2 + Anaview AMS1000 + Tannoy Revolution XT8F
Monitor
ASUS VG278HR 144Hz 3D 1920x1080p
PSU
Corsair AX1200i Fully sleeved red
Case
Corsair Graphite 760T Arctic White
Periferiche
Corsair K95 | Steelseries Rival
OS
windows 10 Pro
non fare messaggi multipli e nel tag di apertura usa [code=C] per visualizzare correttamente il codice.
Seconda cosa... non manca un "#include "pr25.c" " nel file del main? Dovrebbe essere proprio questo il motivo per cui non vede la funzione, gli fai vedere solo la dichiarazione ma non il codice implementativo.
 

anche_per_il_direttore

Nuovo Utente
63
2
[*]Grazie della risposta
[*]Come Si fa a fare
C:
, io Di solito clicco sul + e incollo nella finestra che Si apre
[*]Riguardo il codice quando compilo uso il seguente comando
[*]

[*]gcc pr25.c pr25_main.c -o a25
[*]

[*]Dovrebbe fare il link come ho fatto per tutti gli altri codici, provero' a vedere Se inserendo nel main l altro riferimento funziona, Ma a quel punto la questione sarebbe: perche questo no e tutti gli altri Si
[*]Vi faro' sapere.
[*]

[*]aggiornamento: ho provato a inserire nel main il riferimento all altro file ma come sospettavo non funziona, comincio a pensare che il problema sia dovuto alla ricorsivita della funzione che viene richiamata nell istruzione di return al termine della definizione nel file pr25.c, comunque non perdiamoci il sonno. se qualcuno ha qualche idea ben venga.
[*]PS forse ho anche capito la questione del [code=C] per aumentare la leggibilita del programma. nel prossimo messaggio postero' una questione su un programma che vorrei realizzare che riguarda gli ingressi ad un percettrone "annegati" in uno spazio vettoriale e successivamente passati al programma gnuplot. tempo permettendo
[*]grazie per gli aiuti
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
Devi aggiungere #include <stdio.h> nel file c.
 

anche_per_il_direttore

Nuovo Utente
63
2
grazie della risposta fabio93 ma anche cosi non funziona e mi stupirebbe del fatto che funzionasse dal momento che gli altri codici funzionano senza includere l i/o standard, e come dicevo prima se compongo il codice sotto un unico file.c tutto funziona a meraviglia.
sinceramente non capisco

aggiornamento: l ho risolto, c era uno stupido errore nella main, non ho messo %d nella funzione printf relativa alla funzione fattoriale, ora tutto quadra.
semplicemente laprintf non vedeva la funzione
 
Ultima modifica:

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
A me funziona compilando con "gcc -o pr25 (o nome a scelta) pr25.c pr25_main.c".
 

anche_per_il_direttore

Nuovo Utente
63
2
si anche a me la compilazione andava a buon fine solo che non vedevo il risultato che mi aspettavo, in pratica non vedevo il risultato del fattoriale, se fai la modifica aggiungendo nella funzione printf %d appena prima di \n visualizzi il risultato corretto.
per compilare il tutto i tre file contemporaneamente e linkarli usi

gcc pr25.c pr25_main.c -o a25

-o a25 e dove voglio salvare il mio eseguibile

poi col comando ./a25 il gioco e fatto
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
Non avevo notato che ti eri dimenticato di scrivere lo specificatore di conversione %d, se non lo metti è ovvio che il programma non stampa il valore restituito dalla funzione.
 

anche_per_il_direttore

Nuovo Utente
63
2
salve, oggi voglio postare un programma che ho modificato e che naturalmente dopo la modifica non funziona piu.
la parte modificata e' relativa a un ciclo for che inizializza un vettore su cui poi calcolo i valori di una funzione, ora se il ciclo for parte da zero tutto ok, ma io vorrei che il range dei valori del vettore partisse da -n e andasse a n invece che da 0 a n, posto ora il codice modificato nel for e se qualcuno avesse idee in merito su come risolvere il problema col ciclo sarebbe di grosso aiuto. per fare questa cosa ci sarebbe un modo piu lungo ma la domanda e se posso usare il ciclo for senza troppi giri per risolvere il problema.
C:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include"pr14.h"
//#define NMAX 100


int main()   {

//int i,x[NMAX];




FILE *pf;              //pf e il puntatore o lo stream

int i,n,*v;
v = malloc (n* sizeof(int));
printf ("inserisci la dimensione del vettore dati\n");
scanf ("%d",&n);

pf = fopen ("dati15.txt", "w+");  //creo un file in lettura/scrittura
if (pf == NULL) {                //la funzione fopen ritona un puntatore se c'e un errore ritorna NULL
printf ("impossibile aprire il file dati15.txt");
exit(1); }


for (i=-n; i<n; i++) {

v[i]=i;
fprintf(pf,"%d\t%d\n",v[i],retta(v[i])); }



fclose(pf);            //chiudo il file dati15.txt


FILE *pc;                        //pc e il puntatore o lo stream
pc = fopen ("com15.txt", "w+");  //creo un file per memorizzare i comandi di gnuplot
if (pc == NULL) {
printf ("impossibile aprire il file com15.txt");
exit(1); }                       

fprintf(pc,"plot\"dati15.txt\" with lines\n");//scrivo sul file com15.txt il comando da eseguire
fprintf(pc,"pause -1\"\n");
fclose(pc);   //chiudo il file com15.txt

system("gnuplot com15.txt");//eseguo il programma gnuplot passandogli il nome del file che contiene i comandi
                      
free (v);  //libero la memoria allocata da v                    
                      
 
return 0;
}
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
Non posso testare il programma perché mancano le funzioni contenute nell'header ma, guardando il codice, noto che, prima di tutto, l'allocazione della memoria per il vettore v dovresti farla dopo aver ottenuto la dimensione n dall'utente, altrimenti viene creato un array di dimensione casuale. Quindi la malloc va dopo la scanf.
In secondo luogo, avendo creato un array di dimensione n, non puoi scandirlo da -n a n - 1, perché andresti ben oltre i suoi "confini" (es: se n = 5, vai da -5 a 4, cioè scandisci 10 locazioni, quando ce ne sono solo 5!). Potresti fare che, se n è pari, vai da -n/2 a n/2 - 1 (es: se n = 4, vai da -2 a 1) e, se è dispari, da -n/2 a n/2 (es: se n = 5, vai da -2 a 2), ma mi sembra un'inutile macchinazione. È meglio usare indici positivi (da 0 a n - 1).
 

anche_per_il_direttore

Nuovo Utente
63
2
grazie per la risposta fabio,
allora io l avrei risolta in questo modo; metto i tre codici relativi (ossia anche gli headers); il codice risulta spezzato ancora in tre parti (fatto nei ritagli di tempo, quindi non c e una logica nei nomi dei file)
come puoi vedere all interno del codice principale, in questo caso non ha nessuna importanza la posizione della malloc rispetto alla scanf (provare per credere);
premesso che questa serie di piccoli programmi sono i passi (per me) da compiere per arrivare a definire uno spazio vettoriale in m dimensione ( in questo caso ad esempio riesco a creare un vettore che rappresenta l 'insieme Z tra -n ed n) e qui (m=1) come puoi verificare andando a vedere il file dati15.txt (naturalmente su tale insieme puoi passare una qualunque funzione lineare ad esempio, ottenendo quindi una restrizione su tale insieme) ecco i codici.
PS il file pr14.h altro non e che la dichiarazione della funzione che scrivo qui---int retta(int x);---(quindi basta che nella directory dove conservi i tuoi file ne crei uno che sichiama pr14.h con quella riga che ho appena scritto.

C:
#include "pr14.h"

int retta (int x)

{

return (2*x+1);

}

C:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include"pr14.h"


int main()   {



FILE *pf;              //pf e il puntatore o lo stream

int i,*g,n;
g = malloc (n* sizeof(int));


printf ("inserisci la dimensione del vettore dati\n");
scanf ("%d",&n);



pf = fopen ("dati15.txt", "w+");  //creo un file in lettura/scrittura
if (pf == NULL) {                //la funzione fopen ritona un puntatore se c'e un errore ritorna NULL
printf ("impossibile aprire il file dati15.txt");
exit(1); }



for (i=0; i<2*n; i++) {


g[i]=i-n;


fprintf(pf,"%d\t%d\n",g[i],retta(g[i])); }

         




fclose(pf);            //chiudo il file dati15.txt


FILE *pc;                        //pc e il puntatore o lo stream
pc = fopen ("com15.txt", "w+");  //creo un file per memorizzare i comandi di gnuplot
if (pc == NULL) {
printf ("impossibile aprire il file com15.txt");
exit(1); }                       

fprintf(pc,"plot\"dati15.txt\" with lines\n");//scrivo sul file com15.txt il comando da eseguire
fprintf(pc,"pause -1\"\n");
fclose(pc);   //chiudo il file com15.txt

system("gnuplot com15.txt");//eseguo il programma gnuplot passandogli il nome del file che contiene i comandi
                      
free (g);  //libero la memoria allocata da v                    
                      
 
return 0;
}
 

fabio93

Utente Attivo
609
173
CPU
AMD Ryzen 5 2400G
Dissipatore
Arctic Alpine64 Plus
Scheda Madre
Gigabyte GA-AX370-Gaming 3
HDD
Crucial MX500 250 GB, Crucial BX500 240 GB
RAM
G.Skill F4-3200C14D-16GFX FlareX 16 GB
Monitor
HP 2010i
PSU
Corsair TX550M
Case
Sharkoon M25-W
Periferiche
Magicforce 68, Logitech G203
OS
Windows 10 Pro, Fedora 31
come puoi vedere all interno del codice principale, in questo caso non ha nessuna importanza la posizione della malloc rispetto alla scanf (provare per credere);
Mi permeto di dissentire: l'importanza ce l'ha eccome! Lo scopo dell'istruzione malloc nel programma è di allocare memoria per n interi (tenendo presente che solitamente la memoria occupata da una variabile di tipo intero è 4 byte), dato un certo valore n ottenuto da tastiera. Se tu allochi la memoria prima di ottenere questo valore, semplicemente stai utilizzando un valore casuale di n, quello contenuto dalla variabile n non inizializzata (un dato grezzo). Ciò vanifica la successiva richiesta di inserire un valore da tastiera, rendendola perfettamente inutile (ormai l'allocazione è stata fatta). Il fatto che l'allocazione vada a buon fine non vuol dire niente, si tratta di un caso, dipendente unicamente dal valore contenuto nella variabile n (e se fosse troppo grande, o peggio negativo?). Il funzionamento non è garantito (dicesi "undefined behaviour") e soprattutto la quantità di memoria allocata è del tutto casuale. Ed è comunque sbagliato da un punto di vista logico (è come se vai dal salumiere e lui prima ti affetta una quantità casuale di prosciutto, e dopo ti chiede quanto ne vuoi). Te lo dimostro con un esempio:
Ecco qua un piccolo programma che alloca correttamente memoria per n interi, dato un certo n da tastiera.
C:
#include<stdio.h>
#include<stdlib.h>

int main()
{
   int n, exit;
   int *v;
 
   printf("Inserisci dimensione array: ");
   scanf("%d", &n);
 
   v = malloc(n * sizeof(int));
   if (v == NULL) { // controllo che l'allocazione e' andata a buon fine
       fputs("Impossibile allocare la memoria!\n", stderr);
       return EXIT_FAILURE;
   }
 
   printf("premere un tasto...");
   scanf("%d", &exit); // per tenere aperta la shell

   free(v);
   return 0;
}

Monitorando l'occupazione di memoria del processo con un programma adatto (io ho usato process explorer su windows, su linux dovrebbe andare bene un qualsiasi task manager), si vede che essa dipende dal valore n inserito dall'utente.
Cattura1.PNG
In questa immagine, si vede l'occupazione di memoria del programma appena avviato, prima che l'utente abbia indicato la dimensione della memoria da allocare (quindi l'allocazione non è ancora avvenuta). Come si vede, il programma occupa 512 KB.
Cattura2.PNG
Qui si vede la memoria occupata dopo una richiesta di 10 milioni di elementi: è circa 40 MB (10 milioni di elementi da 4 byte l'uno).
Cattura3.PNG
Infine, l'ultima immagine mostra l'occupazione di memoria dopo una richiesta di 400 milioni di elementi: circa 1.6 GB (400 milioni di elementi da 4 byte l'uno).

Qui sotto invece c'è un programma con la malloc e la scanf invertite.
C:
#include<stdio.h>
#include<stdlib.h>

int main()
{
   int n, exit;
   int *v;

   v = malloc(n * sizeof(int));
   printf("Dimensione n: %d\n", n);
   printf("Inserisci dimensione array: ");
   scanf("%d", &n);
 

   if (v == NULL) { // controllo che l'allocazione e' andata a buon fine
       fputs("Impossibile allocare la memoria!\n", stderr);
       return EXIT_FAILURE;
   }
 
   printf("premere un tasto...");
   scanf("%d", &exit);

   free(v);
   return 0;
}
Guarda cosa succede:
Cattura_E1.PNG Cattura_E2.PNG Cattura_E3.PNG
come mostrano le immagini, ora l'occupazione di memoria non dipende dal valore inserito dall'utente (ho provato gli stessi valori di prima) e inoltre il programma appena avviato occupa già una certa quantità di memoria (casuale), che dipende dal valore grezzo della variabile non inizializzata n. A riprova di ciò ho fatto stampare il valore di n, così puoi verificare che la memoria occupata corrisponde circa a quel valore moltiplicato per 4 (i byte di un intero). Ho anche provato a inserire un valore negativo, che normalmente dovrebbe generare un errore nella malloc, ma non è successo nulla perché l'allocazione era già avvenuta prima.
Senza alcun intento polemico, spero di aver chiarito questo aspetto.

Ciò detto, nel ciclo for (for (i=0; i<2*n; i++)) non puoi scandire 2n elementi, perché l'array ne ha esattamente n, quindi andresti fuori dai limiti.
 
Ultima modifica:

anche_per_il_direttore

Nuovo Utente
63
2
grazie per la risposta fabio
si effettivamente ha senso quello che dici, infatti seguendo il metodo logico nel mio programma, scandendo i valori fino a 2n non avviene la compilazione, che si verifica imponendo la scansione fino a n.
per la verita speravo di poter ottenere un vettore che contiene gli Z compresi tra -n ed n senza appesantire troppo il codice ma probabilmente devo inserire una if (non ci ho ancora pensato a dovere)
come dicevo questi programmi mi servono per capire come costruire un "reticolo" a m dimensioni, che corrisponderebbe a un vettore m dimensionale.
insomma per farla breve sto cercando di costruire i domini di funzioni in Z (come nel programma che ho postato), quindi ottenendo immagini discrete di tali funzioni.
il passo successivo e quello di creare un codice che mi permetta non solo di creare tale vettore a m dimensioni (il che non sarebbe veramente un problema) ma quello di creare altresi' una funzione da permettermi di inizializzare l intero spazio vettoriale in un certo modo "ordinato"
se consideriamo ad esempio lo spazio m=2 ossia il piano, il reticolo in questo caso dovrebbe riportare il punto di coordinate 0,0 nel centro della matrice, il punto di coordinate -n,n nell angolo in alto a sinistra, il punto di coordinate -n,-n nell angolo in basso a sinistra, il punto di coordinate n,n nell angolo in alto a destra e il punto di coordinate n,-n nell angolo in basso a destra.
nel caso m=3 ho un cubo con le stesse regole di "ordinamento" etc etc.
la funzione malloc (o equivalenti) combinata con la scelta della dimensione dello spazio m mi permetterebbe di fare reticoli grandi (o piccoli) a piacere.
adesso tu ti chiederai ma che te ne fai di questi spazi?
ok, il primo scopo e' quello di avere un maggior controllo dei domini di funzioni da passare a gnuplot (senza dover modificare ogni volta l elenco dei comandi da passare)
il secondo scopo che per me e il piu importante e' quello di controllare visivamente lo spazio degli ingressi ad una generica rete neurale e sovrapporre nello stesso spazio le uscite dalla rete neurale
naturalmente stesso discorso si puo fare nella visualizzazione della distribuzione dei pesi (eventualmente assegnabili tramite altre funzioni) etc etc
forse sono stato un po confuso ma spero sia chiaro qual e' il mio obbiettivo.
comunque grazie per l interessamento, ciao
 

anche_per_il_direttore

Nuovo Utente
63
2
ok, ho inserito una if e spostato la malloc, sembra che il codice venga compilato e i risultati mi sembrano corretti, posto il codice, la if sembra assolutamente ridondante
C:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include"pr14.h"


int main()   {



FILE *pf;              //pf e il puntatore o lo stream

int i,*g,n;






printf ("inserisci la dimensione del vettore dati\n");
scanf ("%d",&n);

g = malloc (n* sizeof(int));


pf = fopen ("dati15.txt", "w+");  //creo un file in lettura/scrittura
if (pf == NULL) {                //la funzione fopen ritona un puntatore se c'e un errore ritorna NULL
printf ("impossibile aprire il file dati15.txt");
exit(1); }



for (i=0; i<n; i++) {


if (i<n/2)

g[i]=i-n/2;

else

g[i]=i-n/2;


fprintf(pf,"%d\t%d\n",g[i],retta(g[i])); }

        




fclose(pf);            //chiudo il file dati15.txt


FILE *pc;                        //pc e il puntatore o lo stream
pc = fopen ("com15.txt", "w+");  //creo un file per memorizzare i comandi di gnuplot
if (pc == NULL) {
printf ("impossibile aprire il file com15.txt");
exit(1); }                      

fprintf(pc,"plot\"dati15.txt\" with lines\n");//scrivo sul file com15.txt il comando da eseguire
fprintf(pc,"pause -1\"\n");
fclose(pc);   //chiudo il file com15.txt

system("gnuplot com15.txt");//eseguo il programma gnuplot passandogli il nome del file che contiene i comandi
                     
free (g);  //libero la memoria allocata da g                   
                     
 
return 0;
}
 
Ultima modifica:

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili