PDA

View Full Version : [C] Lunghetto...prime armi


RaouL_BennetH
13-09-2004, 16:34
Salve a tutti. Mi chiamo Raoul e questo è il mio primo messaggio.

Vengo subito al sodo :)

Ho scritto questo piccolo e stupido programmino perchè sto imparando a programmare in C, ma ci sono delle cose che non riesco a fare :(


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ELENCO 100 /* mi serve per vedere l'elenco con la scelta 2*/

/*prototipo della main*/
int main(int argc, char *argv[]); /*non ho ben chiaro perchè dev'essere così*/

/* struttura di esempio */
struct dati
{
int codice;
char cognome[40];
char nome[40];
char cfs[17]; /*per il codice fiscale*/
char ddn[11]; /*per la data di nascita*/
} anagraf;

int main(int argc, char *argv[])
{
char opfilename[] = "/home/raoul/esempio.txt"; /*per aprire il file*/

FILE *opfp;

char rfilename[] = "/home/raoul/esempio.txt"; /*per leggerlo*/
FILE *rfp;

struct tm *newtime; /*per scrivermi il tempo di memoriz. del record/*
time_t aclock;

int selection; /*variabile per il menù*/

for( ; ; ) /*mi apro un ciclo infinito*/
{
printf("\n1 - aggiunge un record");
printf("\n2 - visualizza elenco");
printf("\n3 - esci dal programma");
scanf("%d", &selection);

if (selection < 1 || selection > 3) /*limito la scelta al menu*/
{
printf("\nInserire solo da 1 a 3!!");
}
else if(selection == 3)
{
printf("\nArrivederci!!\n");
break;
}
else if(selection == 1)
{
printf("\nInserire codice per record: ");
scanf("%d", &anagraf.codice);
printf("\nInserire Cognome: ");
scanf("%s", anagraf.cognome);
printf("\nInserire Nome: ");
scanf("%s", anagraf.nome);
printf("\nInserire Codice Fiscale: ");
scanf("%s", anagraf.cfs);
printf("\nInserire data di nascita(gg-mm-aaa): ");
scanf("%s", anagraf.ddn);
/*mi apro il file per scriverci i dati*/
opfp = fopen(opfilename, "a+");
/*metto anche il "tempo" di registrazione del record*/
time (&aclock);
newtime = localtime(&aclock);

/*scrivo sul file che ho aperto*/
fprintf(opfp, "%d\t %s\t %s\t\t %s\t %s\t\n", anagraf.codice, anagraf.cognome, anagraf.nome, anagraf.cfs, anagraf.ddn, asctime(newtime));

/*dopo aver scritto chiudo il file*/
fclose (opfp);
}/*termine dell'if per la scelta 1*/

else if( selection == 2 )
{
char ind[ELENCO];
rfp = fopen(rfilename, "r"); /*apro il file per leggere i record*/
while( !feof(rfp) )/*fin quando no arrivo alla fine del file*/
{
fgets(ind, ELENCO, rfp);
printf("%s", ind);
}

fclose(rfp);
}
}/*chiusura del ciclo for*/
}/*fine main*/



Ecco, questo è quello che sono riuscito a fare fino ad ora, ma, sonjo arrivato ad un punto morto. Il libro dal quale sto tentando di imparare qualcosa, è una guida al linguaggio C di Apogeo ma, ho letto spesso che ad esempio la funzione gets() andrebbe evitata e preferire la funzione fgets(); Beh, su quel libro ci sono solo e sempre esempi con gets()!!! fgets() la definisce e fa solo un esempio!!!

Io ho cercato di farla come vedete, quindi, non sono nemmeno sicuro di averla "messa bene".... comunque, quello che non riesco a fare è:

1) Come posso fare per evitare che quando si inseriscono i dati, se vengono messi errati (ad esempio anzichè mettere il codice numerico scrivono una lettera) il programma non si blocchi?

2) Come posso fare per ricercare e visualizzare un record singolo alla volta?

3) Mi servirebbe comunque una buona critica al codice, considerando però che ho cominciato da qualche settimana, quindi, non mi spellate vivo e non ridete per piacere :)

Grazie a tutti e complimenti a questo forum!!

P.S.: io uso linux, magari se qualcuno potrebbe anche darmi qualche suggerimento su come si utilizza bene gcc e gdb, che anche linux l'ho messo da poco e mi sento un pò disorientato :(

THX!!

RaouL

Dun
13-09-2004, 19:24
Son di fretta quindi saro' telegrafico: :D :D

Il prototipo delle funzioni serve se le aggiungi dopo il main; il prototipo del main non serve.

Organizza il flusso di esecuzione in uno switch, piu elegante e comprensibile.

Cerca di porganizzare il codice in microfunzioni, ne guadagni di leggibilita'.

Al posto di fget ce' sempre scanf che specifica il tipo di dato inserito.

Cya!! :) :) :)

RaouL_BennetH
13-09-2004, 19:45
Originariamente inviato da Dun
Son di fretta quindi saro' telegrafico: :D :D

Il prototipo delle funzioni serve se le aggiungi dopo il main; il prototipo del main non serve.

Ok, grazie :)

Organizza il flusso di esecuzione in uno switch, piu elegante e comprensibile.

Ci volevo provare, ma ancora non ho capito come fare :(

Cerca di porganizzare il codice in microfunzioni, ne guadagni di leggibilita'.

Ho letto qualcosa a riguardo, ma credo che al momento sia ancora fuori dalla mia portata ma grazie tanto per la dritta :)

Al posto di fget ce' sempre scanf che specifica il tipo di dato inserito.

mmmmm.... nel codice che ho scritto, dove ho messo la fgets(), in che modo avrei potuto usare la scanf() ? sinceramente non ho capito :cry:

Cya!! :) :) :) [/QUOTE]

Dun
13-09-2004, 19:57
Scusa non avevo visto :) Errore mio per la scanf :)

Per i file si preferisce fwrite e fread :)

Dun
13-09-2004, 20:04
Forse questo pezzettino di codice ti puo' aiutare:


#include <stdio.h>

int main(int argc, char *argv[]) {

int scelta;

do {
printf("Menu - Digita scelta:\n");
scanf("%d", &scelta);
switch(scelta) {
case 1:
printf("Azione 1\n");
break;
case 2:
printf("Azione 2\n");
break;
case 0:
printf("Exiting...\n");
break;
default:
printf("Nessuna azione eseguita...\n");
}
} while (scelta != 0);

return 0;
}

RaouL_BennetH
14-09-2004, 09:26
Grazie per il suggerimento Dun, ma vorrei capire una cosa:

Hai fatto un esempio con il ciclo do - while e con lo switch, mi chiedevo, oltre che ad essere più leggibile, è anche più efficiente? e se è più efficiente, lo è in questo caso o sempre? Scusa se faccio tutte queste domande magari stupide per te e per molti di voi, ma vorrei capire bene :)

E per la ricerca di un singolo record, mi sai suggerire qualcosa? Io sto provando a leggere il capitolo che riguarda le stringhe e i confronti fra stringhe, ma non fa accenno a come posso fare il confronto su di un file :(

Mi spiego meglio:

Allora, se per esempio io volessi ricercare un operatore che ho inserito?

Oppure, come potrei fare per ottenere che, se un nuovo operatore che inserisco già esiste il programma me lo segnali?

grazie infinite.

RaouL_BennetH
14-09-2004, 15:10
Per il codice del programmino, mi sono anche accorto che è inutile utilizzare due cose diverse per aprire e leggere il file :(

Praticamente ne utilizzo solo una e per l'inserimento apro il file con l'opzione append e per visualizzare apro il file in modo read. Beh, è già qualche riga in meno :D

RaouL_BennetH
15-09-2004, 11:37
un piccolo up :(

RaouL_BennetH
16-09-2004, 00:46
Un piccolo aiutino per fare un controllo se uno dei campi già esiste?

RaouL_BennetH
17-09-2004, 17:11
up! :)

RaouL_BennetH
18-09-2004, 16:28
up :(

RaouL_BennetH
19-09-2004, 14:06
ciao :)

come suggeritomi da AnonimoVeneziano, sto provando ad utilizzare la fwrite() al posto di fprintf(), ma, non riesco nemmeno a compilare il sorgente perchè mi da alcuni errori.

In particolare, mi succede questo:



struct dati {

int codice;
char cognome[40];
char nome[40];
char cfs[17];
char ddn[11];
} anagraf;

/*apro il file e dichiaro quello che mi serve per farlo */

FILE *fp;
char filename[] = "/home/raoul/prova.txt"

/*qui c'è il codice che mi fa inserire i dati */

......

/*qui cerco di scriverli sul file*/

fp = fopen(filename, "a+");

fwrite(anagraf, sizeof(anagraf), 1, fp);

/*......etcetera....*/



Ma succede che quando vado a compilare, mi da:

gcc -Wall fileprova.c -o prova

error: incompatible type for argument 1 of 'write'

Dun
19-09-2004, 16:11
Originariamente inviato da RaouL_BennetH


fwrite(&anagraf, sizeof(anagraf), 1, fp);



Prova cosi' :)

RaouL_BennetH
20-09-2004, 11:40
Originariamente inviato da Dun
Prova cosi' :)

Ciao Dun :)

Grazie per il suggerimento, infatti così funziona!!

Però.... mi sono accorto che questa funzione, rispetto invece alla fprintf(), non mi scrive nel file ciò che mi serve con la giusta tabulazione :(

Ad esempio, mi viene tutto collegato su una riga, e non mi memorizza la data di inserimento. Ora, volendo insistere su fprintf, c'è modo di fare ricerche di stringhe all'interno del file? perchè son giorni che sto leggendo una marea di roba, ma non sono ancora riuscito a trovare nulla che mi permetta di fare queste due cose:

1) ricercare un nome o un cognome o altro dato

2) al momento dell'inserimento, se inserisco un nominativo che già esiste, che il programma mi avvisi.

Grazie mille :)

Raoul.

AnonimoVeneziano
20-09-2004, 19:51
Originariamente inviato da RaouL_BennetH
Ciao Dun :)

Grazie per il suggerimento, infatti così funziona!!

Però.... mi sono accorto che questa funzione, rispetto invece alla fprintf(), non mi scrive nel file ciò che mi serve con la giusta tabulazione :(

Ad esempio, mi viene tutto collegato su una riga, e non mi memorizza la data di inserimento. Ora, volendo insistere su fprintf, c'è modo di fare ricerche di stringhe all'interno del file? perchè son giorni che sto leggendo una marea di roba, ma non sono ancora riuscito a trovare nulla che mi permetta di fare queste due cose:

1) ricercare un nome o un cognome o altro dato

2) al momento dell'inserimento, se inserisco un nominativo che già esiste, che il programma mi avvisi.

Grazie mille :)

Raoul.

Ciao Raoul :D

fwrite non formatta l'output , ma purtroppo "fprintf" non è adatta a cercare ...

Potresti implementare le 2 cose separatamente , fare una funzione per la memorizzazione dei dati (quella che già hai) e una che crea un file di testo formattato per la lettura separata .

Ciao

RaouL_BennetH
20-09-2004, 20:34
Originariamente inviato da AnonimoVeneziano
Ciao Raoul :D

fwrite non formatta l'output , ma purtroppo "fprintf" non è adatta a cercare ...

Potresti implementare le 2 cose separatamente , fare una funzione per la memorizzazione dei dati (quella che già hai) e una che crea un file di testo formattato per la lettura separata .

Ciao

Ciao a te AnonimoVeneziano :)

ieri ero in chan, poi "alice" mi ha abbandonato :(

comunque, se prima avevo le idee confuse, ora ho il buio davanti a me (e non certo per colpa vostra !! ) Sarà forse che non è cosa mia? :what:

Comunque, ora ci provo e ci riprovo :D

Grazie mille!!

Raoul.

RaouL_BennetH
23-09-2004, 10:37
up :(

RaouL_BennetH
24-09-2004, 10:14
Allora, adesso con fwrite() riesco a scrivere il file ed ho provato diverse volte di capire il funzionamento di fseek() ma, probabilmente, anzi, sicuramente, non so bene nemmeno cosa ricercare con google, dato che non riesco a trovare nemmeno un esempio su come ricercare una stringa all'interno di un file. Magari avreste voi da suggerirmi qualche link?

Thx!

RaouL.

RaouL_BennetH
26-09-2004, 13:06
ho un piccolo grande dubbio:


struct dati
{
int codice;
char cognome[40];
char nome[40];
char cfs[17]; /*per il codice fiscale*/
char ddn[11]; /*per la data di nascita*/
} anagraf;


se all'istanza della struttura 'anagraf', la dichiaro come array, cioè:


struct dati
{
int codice;
char cognome[40];
char nome[40];
char cfs[17]; /*per il codice fiscale*/
char ddn[11]; /*per la data di nascita*/
} anagraf[100];


ottengo che ogni 'anagraf' può contenere 100 elementi, oppure che ogni anagraf possa contenere 100 elementi ciascuno composto dal valore di array di ogni singolo elemento della struttura?

Black imp
26-09-2004, 15:00
rispondo ad una domanda che hai fatto sopra:

più è strutturato e gerarchizzato il codice più è leggibile correggibile e manipolabile ma meno è veloce.
il fatto è che di solito il beneficio che hai a strutturare è di gran lunga maggiore della perdita di velocità che per esempi come questo è irrisoria. la strutturazione è inevitabile. però in certi casi si possono sostituire le istruzioni con macro che visivamente permettono di impostare il programma come strutturato ma poi di fatto verranno prima della compilazione espanse, cioè ad ogni occorrenza della macro verrà sostituito il codice relativo e POI il programma verrà compilato

lattone
27-09-2004, 00:47
Ultima domanda:


struct dati
{
int codice;
char cognome[40];
char nome[40];
char cfs[17]; /*per il codice fiscale*/
char ddn[11]; /*per la data di nascita*/
} anagraf[100];

In pratica si dichiarano 100 anagraf.....
Si accede alla struttura così:

anagraf[1].codice;
anagraf[1].cognome[1];
ecc.

domanda precedente:
Questo algoritmo cerca una stringa (pattern) all'interno di un altra stringa (buffer):

for (i=0,j=0; j<strlen(pattern) && i<strlen(buffer); i++,j++)
while (buffer[i] != pattern[j]){
i -= j-1;
j = 0;}

if (j == strlen(pattern)) return (i-strlen(pattern))+1;
else return -1;

La funzione ritorna la posizione in cui inizia il pattern, oppure -1 se non lo trova.

domanda precedente:
int main(int argc, char *argv[]) /*non ho ben chiaro perchè dev'essere così*/

argc e argv[] servono per inserire argomenti dalla riga di comando
Se il programma si chiama raoul.....
ed esegui : raoul.exe ara arb arc
argc contiene il numero di argomenti: 4 [raoul.exe, ara, arb, arc]
argv contiene gli argomenti:
argv[1] è la stringa "raoul.exe"
argv[2] è la stringa "ara"
argv[argc-1] è la stringa "arc"
ecc...

in effetti non mi pare che nel programma utilizzi argomenti da riga di comando quindi potresti utilizzare:

int main(){
.........

RaouL_BennetH
27-09-2004, 21:22
Ragazzi, davvero un enorme grazie a tutti :)

So che non serve a niente, ma davvero vi sono grato :ave:

RaouL_BennetH
28-09-2004, 17:53
Originariamente inviato da lattone

Questo algoritmo cerca una stringa (pattern) all'interno di un altra stringa (buffer):


for (i=0,j=0; j<strlen(pattern) && i<strlen(buffer); i++,j++)
while (buffer[i] != pattern[j]){
i -= j-1;
j = 0;}

if (j == strlen(pattern)) return (i-strlen(pattern))+1;
else return -1;




Mi dispiace ammetterlo, ma davvero non l'ho capito :(

Ho provato ad integrarlo nel codice, ma senza risultato. In che modo potrei adattarlo per la ricerca su di un file?

Thx.

RaouL.

lattone
28-09-2004, 23:16
int sottostringa(char pattern[],char filename[]){
/* EFFECTS: Ricerca pattern all'interno del file filename

int fd, i, j;
struct stat info; //struttura per le informazione sui file

open(filename,O_RDONLY); // apre il file
stat(filename, &info) // legge le info sul file

int size = info.st_size; // size prende la dimensione del file
char buffer[size];

// metti in buffer tutto il contenuto del file
read(fd,buffer,size);

for (i=0,j=0; j<strlen(pattern) && i<strlen(buffer); i++,j++)
while (buffer[i] != pattern[j]){
i -= j-1;
j = 0;}

if (j == strlen(pattern)) return (i-strlen(pattern))+1;
else return -1;
}


Chiamando sottostringa("ciao",nomefile)
se la stringa "ciao" è nel file restituisce la posizione altrimenti -1

Attenzione al fatto che non si controlla l'esito delle chiamate
open(filename,O_RDONLY);
stat(filename, &info);
Le quali restituiscono -1 in caso di insuccesso

in oltre read(fd,buffer,size); riempie il contenuto di una variabile con quello di un intero file. Per un esempio va bene ma attenzione alla dimensione del file.

Ci sono tanti altri modi per realizzare funzioni simili

:)

RaouL_BennetH
28-09-2004, 23:44
Originariamente inviato da lattone

int sottostringa(char pattern[],char filename[]){
/* EFFECTS: Ricerca pattern all'interno del file filename

int fd, i, j;
struct stat info; //struttura per le informazione sui file

open(filename,O_RDONLY); // apre il file
stat(filename, &info) // legge le info sul file

int size = info.st_size; // size prende la dimensione del file
char buffer[size];

// metti in buffer tutto il contenuto del file
read(fd,buffer,size);

for (i=0,j=0; j<strlen(pattern) && i<strlen(buffer); i++,j++)
while (buffer[i] != pattern[j]){
i -= j-1;
j = 0;}

if (j == strlen(pattern)) return (i-strlen(pattern))+1;
else return -1;
}


Chiamando sottostringa("ciao",nomefile)
se la stringa "ciao" è nel file restituisce la posizione altrimenti -1

Attenzione al fatto che non si controlla l'esito delle chiamate
open(filename,O_RDONLY);
stat(filename, &info);
Le quali restituiscono -1 in caso di insuccesso

in oltre read(fd,buffer,size); riempie il contenuto di una variabile con quello di un intero file. Per un esempio va bene ma attenzione alla dimensione del file.

Ci sono tanti altri modi per realizzare funzioni simili

:)


:ave: :ave:

RaouL_BennetH
01-10-2004, 22:57
Rieccomi :) con il vostro preziosissimo aiuto sono ormai quasi alla fine del primo programmino in C (per voi sarà na stupidaggine, ma io mi sento come se avessi scoperto l'elisir di lunga vita :D ).

Mi era venuta solo un'altra malsana idea :mbe:

Se il file di prova sul quale scrivo i dati, si trovasse su una periferica esterna, tipo su un dispositivo seriale, cosa dovrei studiarmi per farlo lavorare da li?

Thx.

RaouL.