Probleme avec getc sur windows en c

Résolu
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024 - 12 juin 2024 à 23:47
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024 - 30 juin 2024 à 14:27

Bonjour, je suis sous windows et j'ai créé un fichier .bin pour un programme en c.

Mais au momment du le premier getc (j'ai aussi essayé avec fgetc), le pointeur augmente brusquement. 

Voici les valeurs que j'ai obtenu par un appel a ftell après le fgetc

Serait-il possible de m'expliquer d'où vient le problème et comment le résoudre?

Merci

A voir également:

10 réponses

yg_be Messages postés 23316 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 8 novembre 2024 Ambassadeur 1 552
13 juin 2024 à 08:18

bonjour,

serait-il possible de partager le code de ton programme?

0
yg_be Messages postés 23316 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 8 novembre 2024 Ambassadeur 1 552
13 juin 2024 à 08:26

Si tu lis du texte, tu ne peux pas utiliser ftell() pour déterminer le nombre de caractères lus, ni considérer ftell() comme te retournant la position dans le fichier.

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
13 juin 2024 à 12:58

Salut SerpentGentil87,

Les comportements de getc() et de ftell() sont expliqués dans leur documentation respective.

Si cela ne répond pas à la question, il va falloir fournir ton code et des explications plus claires.

0
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024
Modifié le 13 juin 2024 à 17:09

Bonjour, merci de vos réponses.

J'ai créer ce tout petit code pour tester la lecture en dehors des perturbations possibles de mon gros programme et j'ai toujours le même problème.

Voici le petit code :

#include <stdio.h>

int main() {
    FILE* fichier = fopen("Base2.bin", "r");
    int tmp;
    printf("%d\n", ftell(fichier));
    tmp = fgetc(fichier);
    printf("%d\n", ftell(fichier));
    tmp = fgetc(fichier);
    printf("%d\n", ftell(fichier));
    fclose(fichier);
}

C'est bien car je n'ai pas trouvé dans les spécifications des fonctions concernant ce problème que j'ai posté ma demande ici.

Par exemple avec un fichier constitué de 560 caracteres, le programme retourne : 

0

443

444

Alors que d'après ce que je lis partout, il aurait du retourner : 

0

1

2

0
yg_be Messages postés 23316 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 8 novembre 2024 1 552
13 juin 2024 à 17:49

Je ne sais pas où tu lis quoi.

La spécification de ftell() indique clairement que le résultat n'a pas de signification dans le cas d'un fichier texte.

Dans quel but utilises-tu ftell()?

0
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024 > yg_be Messages postés 23316 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 8 novembre 2024
13 juin 2024 à 18:32

Pour connaitre ma position dans le fichier. Je fais comment sinon?

0
yg_be Messages postés 23316 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 8 novembre 2024 1 552 > SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024
14 juin 2024 à 09:28

Pourquoi veux-tu connaitre ta position?

Tu pourrais peut-être compter le nombre de caractères obtenus.

0

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

Posez votre question
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024
13 juin 2024 à 20:23

J'ai aussi oublié de dire que j'ai compilé tous mes programmes avec gcc.

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 14 juin 2024 à 19:20

Salut SerpentGentil87,

Merci pour ton code minimal, qui est utile pour comprendre ton problème.

Sous mon Linux ton programme retourne bien 0, 1, 2, mais comme cela a été dit à plusieurs reprises, la spécification précise bien que ftell() ne retourne pas une valeur fiable lorsque tu travailles sur un fichier ouvert comme un fichier texte, ce que tu fais lorsque tu utilises le spécificateur "r" avec fopen().

https://cplusplus.com/reference/cstdio/fopen/

On ne sais pas ce que contient "Base2.bin" (ni si son contenu est bien "binaire"), ni pourquoi tu tiens à avoir cette information.

Essayes de l'ouvrir avec "rb".

Par ailleurs, tu pourrais utiliser un fread() pour lire ton octet, et un type unsigned char pour stocker ta donnée binaire.

https://cplusplus.com/reference/cstdio/fread/

Cela donnerait :

#include <stdio.h>

int main(void) {
    FILE * fichier = fopen("Base2.bin", "rb");
    unsigned char tmp;
    printf("%ld\n", ftell(fichier));
    fread(&tmp, 1, 1, fichier);
    printf("%ld\n", ftell(fichier));
    fread(&tmp, 1, 1, fichier);
    printf("%ld\n", ftell(fichier));
    fclose(fichier);
    return 0;
}

Ce n'est pas très optimisé car il serait mieux de lire un bloc d'octets d'un coup, mais, pour l'exemple, cela devrait retourner le résultat que tu attends.

0
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024
17 juin 2024 à 20:50

Bonjour, merci de vos réponses.

Ouvrir le fichier avec l'option rb a effectivement réglé le problème.

Cependant je n'ai toujours pas compris la différence entre un fichier texte et un fichier binaire. De plus j'ai lu que fread et getc ne devaient pas être utilisés simultanéments. Quelle est la différence entre les deux?

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 20 juin 2024 à 13:12

Bonjour SerpentGentil87,

Ouvrir le fichier avec l'option rb a effectivement réglé le problème

 Oui, parce que tu as ouvert ton fichier en tant que flux binaire.

Je pense que tu as résolu le problème pour lequel tu postais ta question initiale. Peux-tu passer ce fil de discussion en "résolu" ?

je n'ai toujours pas compris la différence entre un fichier texte et un fichier binaire

C'est un raccourci de langage car en réalité tous les fichiers sont stockés sous forme "binaire". Cependant les "fichiers texte" sont conçus pour contenir des données correspondant à des caractères affichables, des caractères "blancs" (espaces, tabulations), et d'autres caractères "blancs" particuliers que sont les retours à la ligne, avec une spécificité sous Windows qui est que les retours à la ligne sont encodés avec deux caractères \r\n et le reste du monde juste \n (les versions anciennes des OS Mac jusqu'à OS 9 utilisaient seulement \r pour signifier le retour à la ligne, ce n'est plus le cas et c'est juste \n depuis que MacOS est basé sur l'implémentation BSD d'Unix).

Pour gérer ces particularités, la bibliothèque standard du langage C adapte le fonctionnement des fonctions de lecture et écriture selon le mode d'ouverture du fichier, binaire ou texte, et dispose de fonctions permettant comme fscanf() permettant de rechercher dans le flux du texte correspondant aux spécificateurs de format en ignorant les caractères blancs, de fonctions comme fgets() qui comprennent le concept de ligne (le compilateur pour tel système gérant les idiosyncrasies de l'OS sur comment on signifie qu'on passe à une ligne suivante), etc.

j'ai lu que fread et getc ne devaient pas être utilisés simultanéments

Ah, quelle est ta source ?

Quelle est la différence entre les deux

fread() est conçue pour lire des données en bloc dans un flux binaire et les stocker dans un tampon mémoire (ton tampon mémoire peut faire 1 byte ou être aussi grand que ce que ton compilateur peut adresser sur ta machine).

fgetc() est conçue pour lire un seul byte dans un flux ouvert.

Elles ont des usages différentes, une syntaxe différente et des résultats différents. Vois les page de manuel de ces deux fonctions.

Si tu te contentes de lire un seul byte, le résultat sera le même, car fgetc() ne fait aucune transformation sur le "caractère" (le byte) qu'elle lit, tout comme fread() qui lit les données brutes binaires enregistrées.

Tu peux lire un "fichier texte" avec fread(). Les données récupérées dans le tampon seront des données brutes et les caractères "blancs" y compris les caractères de retours à la ligne figureront de façon brute dans le tampon. Pour interpréter le contenu du tampon en tant que texte, ou lignes de texte, il faudra retraiter le tampon.

Tu peux aussi lire un "fichier binaire" avec fgetc(), byte par byte. Ce n'est pas très efficace car tu fais un appel système par appel à fgetc() (alors que fread() est optimisée et conçue pour lire des blocs de données), mais cela marchera.

Par exemple, le code suivant, tiré de ce post sur SO par l'utilisateur Mike, copie un fichier .jpg à coups de fgetc() et de fputc() :

int main()
{
    FILE * fptr = fopen("small_pic.jpg", "rb");  // open existing binary picture
    char buffer[10000] = {0}; // the pic is 6kb or so, so 10k bytes will hold it
    FILE * fptr2 = fopen("new_small_pic.jpg", "wb"); // open a new binary file 
                                                       // for our copy of the pic
    unsigned long fileLen;
    unsigned long counter;

    fseek(fptr, 0, SEEK_END);
    fileLen=ftell(fptr);      // get the exact size of the pic
    fseek(fptr, 0, SEEK_SET);

    for(counter=0; counter<fileLen; counter++)
        fputc(fgetc(fptr),fptr2);  // read each byte of the small_pic.jpg and make
                                           // a new pic from it

    fclose(fptr);
    fclose(fptr2);
return 0;
}

(Licence CC BY-SA 3.0 par son auteur)

0
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024
24 juin 2024 à 18:49

Bonjour, merci de ta réponse

J'ai vu que les deux fonction ne pouvaient pas être mélangés sur ce site : https://www.man-linux-magique.net/man3/gets.html

Sinon je pense avoir tout compris.

Merci!!!

Je peux marquer cette discution comme résolue?

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 24 juin 2024 à 19:14

J'ai vu que les deux fonction ne pouvaient pas être mélangés sur ce site : https://www.man-linux-magique.net/man3/gets.html

SI c'est ce passage :

       Il est fortement déconseillé de mélanger les appels  aux  fonctions  de
       lecture  de  la  bibliothèque  stdio  avec  les appels aux fonctions de
       lecture bas-niveau read(2) sur le descripteur  de  fichier  associé  au
       flux.  Les résultats sont indéfinis, et très probablement indésirables.

il parle de read() qui est une fonction accessible par unistd.h, et non de fread() qui relève de stdio.h

Sinon je pense avoir tout compris.

Merci!!!

Je peux marquer cette discution comme résolue?

Oui !  Tu fais cela sur ton sujet initial, en cliquant sur "Résolu".

0
SerpentGentil87 Messages postés 7 Date d'inscription mercredi 12 juin 2024 Statut Membre Dernière intervention 30 juin 2024
30 juin 2024 à 14:27

Bon alors merci!!!

0