PDA

Visualizza la versione completa : [C] Problema nella scrittura di un file di testo


skyboy85
27-11-2007, 12:08
salve a tutti,vi posto questo pezzo di codice:
1)la compilazione nn mi riporta errore
2)a mio avviso sembra correto,ma l'esecuzione va in errore in particolare va in errore dopo la fopen:
3)sto usando fedora core 6 ed lo standard ansi c x gestire gli stream
4) il file itoa.c serve per convertire da intero a stringa


#include <sys/types.h> /* predefined types */
#include <unistd.h> /* include unix standard library */
#include <arpa/inet.h> /* IP addresses conversion utiliites */
#include <sys/socket.h> /* socket library */
#include <stdio.h> /* include standard I/O library */
#include <time.h>
#include <syslog.h> /* syslog system functions */
#include <signal.h> /* signal functions */
#include <errno.h> /* error code */
#include <string.h> /* error strings */
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <malloc.h>

#include "itoa.c"

struct rich{

FILE *richfd; // file descriptors
//la struttura è importante xchè questo codice fa parte di un progetto dove è necessario allocare una struttura
};

typedef struct rich* richiesta;

int main(){
char nome3[]="./cache/richiesta";
char nome4[]=".txt";
char *n1;
int nwrite;
int i=1;
richiesta q;
char* buff="Granatello";



n1=itostring(i);

q =(richiesta)malloc(sizeof(struct rich));


strcat(nome3,n1);
strcat(nome3,nome4);
printf("nome file= %s\n",nome3);

if(q->richfd=fopen(nome3,"a+")==NULL){
printf("errore nella creazione del file: %s\n",strerror(errno));
}
printf("q->richfd: %d\n",q->richfd);
// l'esecuzione si blocca qui
if(fputs(buff,q->richfd)==EOF){
printf("errore nella scittura del file: %s\n",strerror(errno));
}


fclose(q->richfd);
free(q);



}


questo è lo stesso codice,ma ho utilizzato lo stansard unix x gestire i file,ma in questo caso nel file di testo nn viene scritto niente


#include <sys/types.h> /* predefined types */
#include <unistd.h> /* include unix standard library */
#include <arpa/inet.h> /* IP addresses conversion utiliites */
#include <sys/socket.h> /* socket library */
#include <stdio.h> /* include standard I/O library */
#include <time.h>
#include <syslog.h> /* syslog system functions */
#include <signal.h> /* signal functions */
#include <errno.h> /* error code */
#include <string.h> /* error strings */
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <malloc.h>

#include "itoa.c"

struct rich{

int richfd; // file descriptors
// int frequenza;

};

typedef struct rich* richiesta;

int main(){
char nome3[]="./cache/richiesta";
char nome4[]=".txt";
char *n1;
int nwrite;
int i=1;
richiesta q;
char* buff="Granatello";
//printf("%s \n",buff);


n1=itostring(i);




q =(richiesta)malloc(sizeof(struct rich));




strcat(nome3,n1);
strcat(nome3,nome4);
printf("nome file= %s\n",nome3);

if(q->richfd=open(nome3,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR)<0){
printf("errore nella creazione del file: %s\n",strerror(errno));
}
printf("q->richfd: %d\n",q->richfd);

if((nwrite=write(q->richfd,buff,strlen(buff)))<0){
printf("errore nella scittura del file: %s\n",strerror(errno));
}
else
printf("nwrite = %d\n",nwrite);

close(q->richfd);
free(q);
}

MacApp
27-11-2007, 12:25
Originariamente inviato da skyboy85
salve a tutti,vi posto questo pezzo di codice:
1)la compilazione nn mi riporta errore

Prova a compilare con l'opzione -Wall, e modifica il tuo codice in modo da eliminare tutti i warning generati.

in:


if(q->richfd=fopen(nome3,"a+")==NULL){

assegni a "q->richfd" il risultato del confronto "fopen(nome3,"a+")==NULL", anziché assegnargli il risultato della fopen e poi confrontarlo con NULL.

Stesso ragionamento per:


if(q->richfd=open(nome3,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR)<0){

skyboy85
27-11-2007, 14:57
Mitico...ti ringrazio x l'aiuto...
però ora è sorto questo nuovo problema:


#include <sys/types.h> /* predefined types */
#include <unistd.h> /* include unix standard library */
#include <arpa/inet.h> /* IP addresses conversion utiliites */
#include <sys/socket.h> /* socket library */
#include <stdio.h> /* include standard I/O library */
#include <time.h>
#include <syslog.h> /* syslog system functions */
#include <signal.h> /* signal functions */
#include <errno.h> /* error code */
#include <string.h> /* error strings */
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <malloc.h>

#include "itoa.c" //converte da int a stringa


struct rich{

int richfd; // file descriptors
int frequenza;
struct rich* succ;

};


typedef struct rich* richiesta;



void inserimentorichieste(richiesta,char*);
void inizializzazionerichieste(richiesta );

int i=1;



int main(){

char* buff1="Granatello";
printf("%s \n",buff1);
richiesta testa;
inizializzazionerichieste(testa);
printf("sono qui prima del primo inserimento\n");
inserimentorichieste(testa,buff1);
printf("sono qui2 prima del secondo inserimento\n");
char* buff2="Mario";
inserimentorichieste(testa,buff2);
return 0;
}




void inizializzazionerichieste(richiesta testa){

testa=NULL;

}

void inserimentorichieste(richiesta testa,char* buff){


char nome1[]="./cache/richiesta";
char nome2[]=".txt";
char *n1;
richiesta q;
int nwrite;

n1=itostring(i);


q = (richiesta)malloc(sizeof(struct rich)); //con malloc in questa riga inserisce la prima stringa,ma va in errore sulla funz free...



strcat(nome1,n1);
strcat(nome1,nome2);

printf("%s\n", nome1);


//se metto la malloc in questa riga il programma nn va in errore,ma nn viene rispettato il nome dei 2 file di testo

//printf("sono qui4 dopo malloc %s\n",nome1);

if((q->richfd=open(nome1,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR))<0){
printf("errore nella creazione del file: %s\n",strerror(errno));
}
//printf("filefd: %d\n",q->richfd);
//printf("file = %d\n",file);
//printf("buff = %s\n",buff);
if((nwrite=write(q->richfd,buff,strlen(buff)))<0){
printf("errore nella scittura del file: %s\n",strerror(errno));
}
else {
printf("nwrite = %d\n",nwrite);
}

close(q->richfd);

q->succ=testa;
testa=q;
//q->frequenza++;

i++;

free(q);
printf("QUI i=%d e testa= %d\n",i,testa);
}
:dhò:

MacApp
27-11-2007, 15:59
Originariamente inviato da skyboy85

però ora è sorto questo nuovo problema:

Anche se non è in relazione al tuo errore, modifica la "inizializzazionerichieste" in:


void inizializzazionerichieste(richiesta * testa){
*testa=NULL;
}


e quando la chiami nella main:


inizializzazionerichieste(&testa);


Invece relativamente al tuo errore commetti un classico sforamento.
Infatti in "inserimentorichieste":


char nome1[]="./cache/richiesta";
char nome2[]=".txt";

implicitamente nome1 è un array di 18 elementi, e nome2 di 5 elementi.

quindi quando fai:


strcat(nome1,n1);
strcat(nome1,nome2);


vai a scrivere in zona di memoria indefinite, generando pertanto un comportamento indefinito.

skyboy85
27-11-2007, 16:15
ti sono veramente grato e mi scuso per il tempo ke ti faccio perdere...
ho risolto il problema con la funzione iniziallizzazione,ma nn ho capito il problema sulla concatenzione e neanke come risolverlo...
se rivedi il mio primo post(in particolare la seconda citazione),ho effettuato le modifiche da te suggeritemi ed il programma si esegue correttamente,cioè nn mi da il problema sul nome file
rifacendo lo stesso nel codice presente nel secondo post ho i problemi con malloc e nome dei file

grazie mille

MacApp
27-11-2007, 16:32
Leggiti bene la documentazione di strcat.
Il primo argomento DEVE essere sufficientemente grande da poter ricevere ciò che gli stai aggiungendo. Altrimenti hai un comportamento indefinito (crash, hd rotti, esplosioni nucleari, aerei che cadono, la ragazza che ti lascia, la moglie brutta del tuo collega che si innamora di te, vincite al lotto inattese ecc..) ;-)

Se ad esempio ipotizzi che l'array nome1 possa contenere 1024 elementi (quindi una stringa lunga al max 1023 caratteri) allora glielo devi dire, ad esempio:


char nome1 [1024]="./cache/richiesta";

skyboy85
27-11-2007, 19:38
però visto ke a priori non posso calcolare la lunghezza del nome ==> ho dichiarato nome1 come char*.... :bhò:

MItaly
27-11-2007, 20:06
Se non sai a priori le dimensioni di una stringa non la dichiari come char *, ma crei un buffer sufficientemente ampio o lo allochi a runtime usando la malloc.
Quando tu scrivi


char * nome1 = "./cache/richiesta";

stai dicendo al compilatore di mettere "./cache/richiesta" nella tabella delle stringhe (o almeno, così accade sulla maggior parte delle architetture) e di assegnare a nome1 un puntatore alla locazione di memoria (all'interno della tabella delle stringhe) in cui la stringa si trova. Ora, la tabella delle stringhe di solito è "compattata", in modo che tutte le stringhe usate dal programma note a compile-time siano strette nel minor spazio possibile, quindi ad una stringa segue immediatamente l'altra, senza che ci sia spazio aggiuntivo tra l'una e l'altra.
Perciò se effettui una strcat su nome1 con le massime probabilità vai a sovrascrivere altre stringhe del programma.

skyboy85
27-11-2007, 20:58
char nome1[]="./cache/richiesta";

char nome2[]=".txt";

char *n1;
QUOTE]strcat(nome1,n1);[/QUOTE]

strcat(nome1,nome2);


prima ho sbagliato a dire...io ho seguito quanto scritto sopra...ora mi sorgono le seguenti domande:

1) in char nome1[] dove specificare una dim??? ad esempio 20???
2) n1 devova essere dichiarata come char n1[]???

dalla documentazione di strcat ho visto i prototipi:

char *strcat ( char *s1, const char*s2)
oppure
char *strcat(char dest[], char *sorg);

a quale mi devo riferire???

in entrambi i casi la funzione restituisce un puntatore a dest o s1 quindi un' istruzione di questo tipo è lecita:

q->richfd=open(nome1,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR)

MItaly
27-11-2007, 21:38
Originariamente inviato da skyboy85
1) in char nome1[] dove specificare una dim??? ad esempio 20???
Sì, ma nome1 deve essere di dimensioni tali da poter contenere tutto quello che ci accoderai.
Tra parentesi, tra il dichiarare nome1 come char* e come char[] c'è comunque una differenza: nel primo caso accade quello che ti ho detto, nel secondo, invece, viene effettivamente creato un array nello stack (non nella tabella delle stringhe) di dimensioni determinate dal compilatore in base alla stringa con cui lo inizializzi.


2) n1 devova essere dichiarata come char n1[]???

Non saprei, visto che non conosco la itostring (non è standard).


dalla documentazione di strcat ho visto i prototipi:

char *strcat ( char *s1, const char*s2)
oppure
char *strcat(char dest[], char *sorg);

a quale mi devo riferire???

Sono identici (char[] e char * in una chiamata a funzione sono la stessa cosa, ossia un puntatore a char). In ogni caso per evitare buffer overrun ti consiglio di utilizzare la strncat, così da essere sicura di non superare le dimensioni dell'array.


strncat(nome1, n1, sizeof(nome1)-strlen(nome1)-1);
strncat(nome1, nome2, sizeof(nome1)-strlen(nome1)-1);
nome1[sizeof(nome1)-1]=0;



in entrambi i casi la funzione restituisce un puntatore a dest o s1 quindi un' istruzione di questo tipo è lecita:

q->richfd=open(nome1,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR)
Non vedo il collegamento tra le due cose... :master:

Loading