ouverture de fichier en C

HommeCocoa

Membre actif
3 Janvier 2003
173
0
Vevey - Suisse
Bonjour,

J'essaie d'écrire un petit fichier en C qui inscrit des valeurs dans un fichier texte précédemment créé. J'ai un livre sur le C ou il expliquent comment et j'ai aussi trouvé des tutoriaux:
http://membres.lycos.fr/macbuilder/tutoriaux/tut_c/

J'ai alors copié le code du tutoriel

#include <stdio.h>


int main (int argc, const char * argv[])
{
FILE *f;
f=fopen("essai.data", "r");
if (f == NULL)
{
printf("erreur d'ouverture du fichier\n");
}
}

Mais l'écriture du fichier échoue à chaque fois. J'ai essayé un autre code trouvé dans un bouquin mais c'est le meme problème.

Quelqu'un peut-il m'expliquer le problème?
Merci d'avance

David
 
Bloc de code:
#include <stdio.h>

int main() {
  FILE *sourceFile;
  FILE *destinationFile;
  char *buffer;
  int n;

  sourceFile = fopen("file.c", "r");
  destinationFile = fopen("file2.c", "w");

  if(sourceFile==NULL) {
    printf("Error: can't access file.c.\n");
    return 1;
  }
  else if(destinationFile==NULL) {
    printf("Error: can't create file for writing.\n");
    return 1;
  }
  else {
    n = fread(buffer, 1, 1000, sourceFile);
    fwrite(buffer, 1, n, destinationFile);
    fclose(sourceFile);
    fclose(destinationFile);

    destinationFile = fopen("file2.c", "r");
    n = fread(buffer, 1, 1000, destinationFile);
    printf("%s", buffer);
    fclose(destinationFile);
    return 0;
  }
}

..........w==write
..........r==read
;)

et tu peux composer destinationFile = fopen("file2.c", "rw");

j'ai passé quelques étapes après c'est la function fscanf dont tu vas avoir besoin

:zen:
 
Bonjour,

Il y a une petite erreur dans ton exemple Tatouille :
Tu écrit :

sourceFile = fopen("file.c", "r");
destinationFile = fopen("file2.c", "w");

if(sourceFile==NULL)
{
printf("Error: can't access file.c.\n");
return 1;
}
else if(destinationFile==NULL) {
printf("Error: can't create file for writing.\n");
return 1;
}

Or si tu arrive a ouvrir la source et pas la destination, ta source reste ouverte et tu perd un descripteur de fichier. Comme le nombre de descripteur de fichier est limité (par session de la meme application) tu va saturer et au bout d'un moment plus aucun fichier ne pourra etre ouvert.
Ensuite le "else" ne sert a rien puisque le "return" rends la main a l'appelant.

Je prefererait donc :

sourceFile = fopen("file.c", "r");

if(sourceFile==NULL)
{
printf("Error: can't access file.c.\n");
return 1;
}
destinationFile = fopen("file2.c", "w");
if(destinationFile==NULL)
{
fclose(sourceFile); /* Je ferme le fichier source */
printf("Error: can't create file for writing.\n");
return 1;
}

Ensuite, plutot que de retourner (1) dans le cas d'une erreur, et (0) quand tout est bon, il pourrait etre intéressant d'utiliser "errno" qui donne un numéro d'erreur.

Cordialement
 
Maintenant que ça marche, je me suis amusé avec ceci:

#include <stdio.h>

int i;
int res;

int main()
{

FILE *destinationFile;

destinationFile = fopen("file.txt", "w");

if(destinationFile==NULL)
{
printf("Error: can't create file for writing.\n");
return 1;
}
else
{
fprintf(destinationFile, "Liste des carres des nombres de 1 a 1000\n");
for (i=0; i<10; i++)
{
res = i*i;
fprintf(destinationFile, "%d * %d = %d\n", i, i, res);
}
fclose(destinationFile);
return 0;
}
}

ce petit programme ouvre un fichier txt et y inscrit les dix premier carré (1*1=1 2*2=4 ...).
Si je clique sur Build and Run, tout se passe bien, le fichier se crée et les nombres s'inscrivent, mais si je supprime le fichier créé et que je lance mon application dans le terminal, elle ne parvient pas à recréer le fichier mais ne me signial pas d'erreur.

Là encore quelqu'un peut-il m'éclairer?
Merci!
David
 
Bonjour,

La seule irrégularité que je vois pour l'instant est l'utilisation du type "int". A proscrire car la précision de "int" varie selon les systemes (en general 32 bits mais cela peut varier et rends donc ton source non portable)
Utilise donc "short" si tu veut un nombre signé sur 15 bits, "long" signé sur 31 bits (1 bit est reserve au signe.

La sequence %d doit être adaptée : %d si tu utilise un short, %ld si tu utilise un long.


Pour ton probleme de fichier non créé, fait "ls -l" sous le terminal pour visualiser les fichiers de ton dossier. Parfois le Finder souffre de probleme de raffraichissement.

Cordialement
 
Didier Guillion a dit:
Ensuite, plutot que de retourner (1) dans le cas d'une erreur, et (0) quand tout est bon, il pourrait etre intéressant d'utiliser "errno" qui donne un numéro d'erreur.

Il existe aussi les constantes EXIT_FAILURE et EXIT_SUCCESS de la librairie stdlib.h. Elles sont plutôt à utiliser en association avec la fonction exit(int statuts) de cette même librairie.
 
mis à part ce problème, j'ai augmenté le nombre de passage dans la boucle for à quelques millions...

Par conséquent j'ai un joli petit fichier txt rempli de carré... le tout ne pesant pas moins de 500Mo loool...

Si quelqu'un a une bonne connection et est intéressé par des carrés en vrac, qu'il me fasse signe.. :D
 
Didier Guillion a dit:
Bonjour,

La seule irrégularité que je vois pour l'instant est l'utilisation du type "int". A proscrire car la précision de "int" varie selon les systemes (en general 32 bits mais cela peut varier et rends donc ton source non portable)
Utilise donc "short" si tu veut un nombre signé sur 15 bits, "long" signé sur 31 bits (1 bit est reserve au signe.

La sequence %d doit être adaptée : %d si tu utilise un short, %ld si tu utilise un long.


Pour ton probleme de fichier non créé, fait "ls -l" sous le terminal pour visualiser les fichiers de ton dossier. Parfois le Finder souffre de probleme de raffraichissement.

Cordialement

J'ai adopté le type float, est-ce aussi adapté?

#include <stdio.h>

float i;
float res;

int main()
{

FILE *destinationFile;

destinationFile = fopen("file.txt", "w");

if(destinationFile==NULL)
{
printf("Error: can't create file for writing.\n");
return 1;
}
else
{
fprintf(destinationFile, "Liste des carres des nombres de 1 a 1000\n");
for (i=0; i<10000000; i++)
{
res = i*i;
fprintf(destinationFile, "%f * %f = %f\n", i, i, res);
}
fclose(destinationFile);
return 0;
}
}
 
Bonjour,

Oui, le type "float" est parfaitement compatible.
A noter que tu peut parametrer l'affichage du %f en utilisant par exemple %.2f qui va te donner deux chiffres apres la virgule.


Une remarque infime, si tu déclare tes variables en dehors du corps de la fonction "main" elles sont globales, ce n'est pas génant, mais pas vraiment une bonne habitude a prendre.

Ecrit donc plutot :


int main()
{
float i;
float res;
FILE *destinationFile;

...

Et pour ton probleme de génération de fichier ?

Cordialement
 
!!!!! Etrange, après une nouvelle tentative cela semble fonctionner, le fichier texte est effectivement créé... Bizarre

Mis à part ça, j'ai plusieur autres questions, quelle est la différence entre le mode "development" et le mode "deployement" qu'il est possible de spécifier dans Xcode?

Et sinon, je ne comprend toujours pas pourquoi mon premier code ne marchait pas:

int main (int argc, const char * argv[])
{
FILE *f;
f=fopen("essai.data", "r");
if (f == NULL)
{
printf("erreur d'ouverture du fichier\n");
}
}
Chez moi, il me donne toujours le message d'erreur d'ouverture.

Merci encore!
 
Bonjour,

Je pense que la difference entre les deux modes est due au niveau d'optimisation.
En general on developpe un code non optimisé car c'est plus facile a debogger.
Puis, on genere une version diffusable optimisée pleinement.

A noter : toujours refaire les tests sur la version optimisée, certaines options d'optimsation peuvent se "planter".

Pour ta deuxieme question, le fichier "essai.data" est til present au meme niveau que l'executable ? Si non, c'est normal qu'il ne puisse s'ouvrir...

Cordialement
 
Oui il était censé se créer au niveau de l'exécutable. Mais ne se créait pas.
J'ai changé son extention pour du .txt et le type, je l'ai mis en "w" et là du coup le fichier s'ouvre correctement, cela provient de quoi?
 
Bonjour,

Quand tu utilise "fopen" (file open=ouverture de fichier) avec comme parametre "r" (read=lecture) le fichier doit etre présent sur le disque dur.
Dans ce type d'ouverture tu peut seulement lire sur le descripteur de fichier par "getc","fscanf" par exemple.

Quand tu utilise "w" (write=ecriture) le fichier est créé, si il existe deja son contenu est remis à zero.
Dans ce type d'ouverture tu peut seulement écrire sur le descripteur de fichier par "putc","fprintf" par exemple.

Des modes te permettent d'ouvrir en lecture ET écriture mais c'est une autre histoire.

Cordialement
 
Je continue dans mes petits essais et je voulais créer un programme détérminant des nombres premier puis les écrires dans un fichiers. La première partie fut de trouver un algorithme pour trouver ces nombres premiers. J'ai pensé à ceci:


#include <stdio.h>
#define cste 200

int main (int argc, const char * argv[])
{
int nombre;
int i;
int mod;


for(nombre=1;nombre<cste;nombre++)
{
i = 2;
mod = nombre % i;


while ((mod!=0) || (i<nombre))
{
i++;
mod = nombre % i;
}

if(i==nombre)
{
printf("Ceci est un nombre premier %d\n\n", nombre);
}


}
return 0;
}


Mais malheureusement cela ne fonctionne pas et j'ai un peu du mal à le débugger...
le while est-il bien une boucle TANTQUE?

le principe étant que pour chaque nombre présenté, la boucle le divise par des nombres croissant (variable i) et regarde si il y a un reste et ceci TANTQUE il trouve un reste OU que le nombre croissant est plus petit que le nombre à tester. Donc il sort de la boucle soit parce qu'il a ttrouvé un diviseur qui ne produit soit de reste soit parce qu'il est arrivé à concurrence du nombre lui même. Puis par un teste on repere de quel facon il est sorti de la boucle... Bon je sais mon algo est un peu mal exprimé... :heu:
 
Oups je viens de m'apercevoir de ma boulette, en faite il s'agissait simplement de la condition de sortie de la boucle. Voici une version qui semble fonctionner:

#include <stdio.h>
#define cste 10000

int main (int argc, const char * argv[])
{
int nombre;
int i;
int mod;


for(nombre=2;nombre<cste;nombre++)
{
i = 2;
mod = nombre % i;


while (mod!=0)
{
i++;
mod = nombre % i;
}


if(i==nombre)
{
printf("Ceci est un nombre premier %d\n\n", nombre);
}


}
return 0;
}

Cela me sort effectivement des nombres premiers... Par contre un pot m'avais filé un code qui semble beaucoup plus performant. Pour avoir testé les deux, le sien est beaucoup plus rapide, mais je comprend moins bien le principe:

#include <stdio.h>
#define n 10000

int main (int argc, const char * argv[])
{
int Nombres[n];
int i;
int j;

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

Nombres[0] = Nombres[1] = Nombres[2] = 0;

for(i=2;i<n;i++)
for(j=i*2;j<n;j+=i)
Nombres[j] = 0;

for(i=0;i<n;i++)
if(Nombres != 0)
printf("%d\n", Nombres);

return 0;
}


David
 
Bonjour,

Quelques remarques :

- Usage de "int" dont nous avons deja parlé.
- Création d'un tableau de 10000 elements sur la pile (10000*4=40000 octets) pas glop.
J'aurait plutot ecrit :

/* Declaration du pointeur sur les nombres */
long * Nombres;

/* Allocation de 10000 elements */
Nombres=(long*) malloc(sizeof(long)*10000);
/* L'allocation s'est bien passée ? */
if(Nombres !=NULL)
{
/* Travail sur le tableau (cela ne change pas) */
...

/* Liberation du tableau */
free(Nombres);
}
A noter que "10000" gagnerait à ete placé en constante comme dans ton premier exemple.

Cordialement