Langage C : lire un tableau depuis un fichier

Résolu/Fermé
Metabolic - 2 déc. 2010 à 14:54
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 7 déc. 2010 à 00:11
Bonjour,

Je suis étudiant et je travaille sur un petit projet de bataille navale en langage C sur Unix.
J'ai une fonction save, qui écrit dans un fichier les grilles des deux joueurs du jeu en guise de sauvegarde.
Je voudrai maintenant pouvoir les charger et les utiliser dans mon programme pour continuer la partie. Comment faire?

Voici ma fonction save :

#include <stdio.h>
#include <cstdio.h>
void save(Grille A,Grille B,Grille A2,Grille B2){
freopen ("save.txt","w",stdout);
aff_Grille(A,B); //affiche les grilles en paramètre, cote a cote
printf("\n");
aff_Grille(A2,B2);
fclose(stdout);
}

et le type Grille :

#define N 10;
typedef char Grille[N][N];

Merci :)

5 réponses

Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
2 déc. 2010 à 15:29
la lecture est en effet un peu plus compliqué compliqué. il faut utiliser fscanf pour lire le fichier.
ton freopen est plutôt malin pour éviter de faire une deuxième fonction d'écriture. Je me pose juste une question, est-ce que close(stdout) restaure le flux sur la sortie standard ?
Pour ta lecture de grille :
FILE* fi=fopen("save.txt","r");
for(j=0;j<2;++j)
for(n=0;n<N;++n)
{
     for(m=0;m<N;++m)
          scanf("%c",&grille[n][m]);
     scanf("\n");
}
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
2 déc. 2010 à 23:09
Bonjour Char Snipeur,

scanf("%\n") ?
Tu souhaites faire quoi ?
Ensuite, j'imagine que tu voulais mettre fscanf au lieu du scanf ?
Et pourquoi une boucle j<2 ?
Sinon, attention au redirection...
Il n'y a pas de solution portable pour restaurer le flux sur la sortie standard.
Pour réussir, il faut jouer avec dup / dup2 et sauvegarder le descripteur par dup(fileno(stdout));
Bref rien de très joli. Il vaut mieux éviter ce genre de redirection.

Cdlt,
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
3 déc. 2010 à 08:19
ouai, c'est plein de merde. j'ai oublié le fscanf.
Je voulais juste donner l'algorithme général. La boucle sur "j", c'est car tu as deux grilles. Mais après relecture, il y en a 4 : 2 pour chaque joueur.
Merci de ta réponse sur stdout, ça me semblait trop simple aussi.
0
Merci pour le code mais tu dis qu'il faut utiliser fscanf et t'as juste utilisé des scanf.
(un oubli sans importance vu qu'ils sont bien placés :) )
Et pr répondre à ta question je pense que oui après le fclose, stdout redevient standard.
0
Hum sa serait quoi alors si je devais changer aussi mon code pour save?
Un truc genre :

FILE* fi=fopen("save.txt","r");
blabla avec fprintf
fclose(fi)

??
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
3 déc. 2010 à 08:22
une solution si tu veux faire qu'une routine, c'est de modifier ta fonction aff_grille et mettre :
aff_grille(Grille A,Grille B,FILE * s=stdout);
vérifier qu'en C on peut bien mettre un argument par défaut.
Ensuite, tu modifie tout les printf de ta fonction par des fprintf(s,...)
Dans le reste du code, la seule modification à faire sera alors d'appeler aff_grille avec en argument l'identifiant du fichier.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 déc. 2010 à 09:06
Nop, pas d'argument par défaut en C..

Pour écrire dans un fichier, tu peux simplement utliser un fprintf.

Sinon, tu as deux joueurs dans une bataille navale, il faut donc 2 grilles. Chacune des grilles contiendra 4 valeurs (0 si aucun bateau et pas de missile lancée sur cette zone, 1 si présence bateau et pas de missile lancée, ...). Tu peux faire un enum pour plus de clarté.

Ensuite, pour ta grille, il te faut une autre dimension pour stocker les deux grilles. Par exemple : int grille[2][N][N]; Sinon tu peux utiliser une structure aussi.

Ensuite plutôt que t'embêter avec fprintf/fscanf, un simple fread/fwrite te fera la lecture/écriture en une passe.

Cordialement,
0
t'inquiète pas pr les grilles, j'ai déja fait une grande partie du programme du jeu. Simplement, j'aimerai savoir si cette version de load, codée à partir de vos commentaires, est correcte. Je vous mets aussi les structs de départ pr pouvoir comprendre.

#define N 10

typedef char Grille[N][N];
typedef struct{
char typeB;
int Nbcases;
int absOrig;
int ordOrig;
int Orientation[2];
}bateau;
typedef struct{
int Nbship;
bateau tabShip[N];
}listeBateau;



void load(Grille A,Grille B,Grille A2,Grille B2,listeBateau lp,listeBateau lo){
FILE* fi=fopen("save.txt","r");
for(n=0;n<N;++n){
for(m=0;m<N;++m){
fscanf("%c",&A[n][m]);
}
fscanf("\n");
}
for(n=0;n<N;++n){
for(m=0;m<N;++m){
fscanf("%c",&B[n][m]);
}
fscanf("\n");
}
fscanf("\n");
for(n=0;n<N;++n){
for(m=0;m<N;++m){
fscanf("%c",&A2[n][m]);
}
fscanf("\n");
}
for(n=0;n<N;++n){
for(m=0;m<N;++m){
fscanf("%c",&B2[n][m]);
}
fscanf("\n");
}
fscanf("%d",&lp.Nbship);
for(i=0;i<N;i++){
fscanf(" %c,%d,%d,%d,%d,%d",&((lp.tabShip)[i].typeB),&((lp.tabShip)[i].Nbcases),&((lp.tabShip)[i].absOrig),&((lp.tabShip)[i].ordOrig),&((lp.tabShip)[i].Orientation[0]),&((lp.tabShip)[i].Orientation[1]));
}
fscanf("\n");
fscanf("%d",&lo.Nbship);
for(i=0;i<N;i++){
fscanf(" %c,%d,%d,%d,%d,%d",&((lo.tabShip)[i].typeB),&((lo.tabShip)[i].Nbcases),&((lo.tabShip)[i].absOrig),&((lo.tabShip)[i].ordOrig),&((lo.tabShip)[i].Orientation[0]),&((lo.tabShip)[i].Orientation[1]));
}
fclose(fi);
}

Je sais que niveau lisibilité c'est pas la fête mais bon si ça marche sa me suffira pour le moment. Quant à save je prévois de faire la même chose en remplaçant les fscanf par des fprintf.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 déc. 2010 à 14:00
Effectivement, c'est pas clair du tout.
Quand tu postes du code, utilise les balises "code" (à droite du bouton souligné), ça sera beaucoup plus lisible pour nous.
Sinon, tu as mis des fscanf("\n"), ça ne correspond à rien.
Ensuite, ton code est bien trop compliqué...
En une ligne, tu peux faire ta fonction load et open avec fread et fwrite. Pas besoin de faire de boucle etc.

Cdlt,
0
ya pas besoin de lire les retours a la ligne? ah ok....mais par contre je vois pas comment en une ligne je peux faire ma fonction load ou save vu que fread est assez compliqué à utiliser et j'ai 4 grilles et 2 structures à charger/sauvegarder.
On a pas encore vraiment étudié les pbs de fichier et mémoire en c donc je comprends pas tout...
0
fanowine Messages postés 20 Date d'inscription vendredi 9 avril 2010 Statut Membre Dernière intervention 24 juillet 2019 1
6 déc. 2010 à 23:44
le probleme avec fscanf est que cette fonction lit mot apres mot
alors que tu conviens avec moi que cela est un peut rude parcontre avec le cas de caractere par caractère tu gere ton contenue comme tu veux
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
7 déc. 2010 à 00:11
le probleme avec fscanf est que cette fonction lit mot apres mot
Sauf que fscanf n'est pas une fonction qui lit mot à mot. Cela dépend du format passé en argument. Dans nos exemples, on utilisait fscanf(fp,"%c",...) et dans ce cas ça lit caractère par caractère comme ton fgetc... Un petit lien pour voir ce que fait scanf : http://www.linux-france.org/article/man-fr/man3/scanf-3.html

alors que tu conviens avec moi que cela est un peut rude parcontre avec le cas de caractere par caractère tu gere ton contenue comme tu veux
Oui je conviens. Par contre, tu conviendras avec moi qu'un simple fread est encore moins rude que la gestion du caractère par caractère...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
fanowine Messages postés 20 Date d'inscription vendredi 9 avril 2010 Statut Membre Dernière intervention 24 juillet 2019 1
5 déc. 2010 à 11:34
je suggère que tu utilise la fonction 'fget(FILE *fi)'.
cette fonction retourne un caractère.
cette fonction te permet de parcourir bien ton fichier et de copier dans ton tableau les caractères dont tu a besoin
exemple tu connais le code asci de tout les chiffres si c'est sa que tu as besoin
alors tu pourras copier tous les chiffres de la maniere qu'il ont été sauvegardé
-1
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
5 déc. 2010 à 12:18
Ce n'est pas la fonction fget mais fgetc.
Et c'est un peu le même problème que la fonction scanf("%c",...), cela rend le code compliqué car il faut user de boucle for et traduire la "complexité" des structures.
Un simple fread suffit...
0