Bonjour à tous !
Etant débutante en C, je me pose une question...
y a t'il une différence entre EOF et '/O' pour marquer la fin d'un flot de caractères ?
Merci d'avance !
Bonjour à tous !
Etant débutante en C, je me pose une question...
y a t'il une différence entre EOF et '/O' pour marquer la fin d'un flot de caractères ?
Merci d'avance !
Bonjour,
Attention, c'est '\0' et non '/O'.
'\0' correspond à un caractère ayant pour valeur 0x00, il sert à marquer la fin d'une chaîne de caractère.
Dans un flux de caractère, on peut très bien avoir des caractère valant '\0'.
Pour EOF, il ne me semble pas qu'il soit réellement écris dans le flux mais qu'il serve juste à indiquer aux fonctions d'écriture de caractère qu'on souhaite fermer le flux (?) ou aux fonctions de lecture de caractères de nous indiquer que le flux est fini.
EOF étant un int, ceci permet donc de différencier facilement les caractères à lire/écrire de EOF.
Sinon je pense que ce sujet pourrais t'intéresser.
Bonjour !
Merci pour cette réponse rapide
Donc si j'ai bien compris, "/0" marquerait la fin d'une string tandis que EOF indiquerait la fin d'un flux (et le fermerait) ?
Il faut faire attention car EOF n'est pas "physiquement" présent à la fin du flux.
Sinon les sockets planteraient dès qu'on essayerais de passer un int en binaire valant -1.
EOF est une valeur retournée par les fonctions de lecture pour indiquer au programmeur qu'il y a eu une erreur (fin de fichier ou autre).
Pour :
J'ai testé et cela ne ferme pas le flux (contrairement à ce que je supposais), il caste EOF en char et écrit alors 255 (ou -1) ce qui donne un caractère non-imprimable.
Code : Sélectionner tout - Visualiser dans une fenêtre à part fputc(EOF, monFichier);
Par contre il me semblait que EOF est bien présent à la fin d'un flux particulier pour des raisons historiques, je n'en suis pas vraiment sûr et je ne saurais pas dire de quel flux il s'agissait (stdin? stdout?).
EDIT : je pense que je confond avec EOT (End Of Transmission = Ctrl+D) 0x04 et ETX (End of Texte = Ctrl+C) 0x03 qui ferment tous les deux stdin.
Bonsoir,
Attention, comme dit plus haut, c'est un anti-slash « \ » qu'il faut utiliser.
Pas tout-à-fait : « \0 » est une combinaison permettant de représenter le caractère ASCII numéro 00 exactement (qui par nature est un caractère non affichable). Et par convention, le langage C utilise un char ayant une valeur nulle comme marqueur de fin de chaîne.… tandis que EOF indiquerait la fin d'un flux (et le fermerait) ?
EOF est une macro #define définie à une certaine valeur (généralement « -1 » mais cette valeur est censée être cachée aux yeux du programmeur) qui est renvoyée par fgetc() lorsque la lecture n'a pu avoir lieu. Ce n'est donc absolument pas un caractère en soi, et elle ne fait pas du tout partie du flux.
C'est la raison pour laquelle fgetc() renvoie un int et pas directement un char : il s'agit de pouvoir renvoyer toutes les valeurs possibles valides pour un caractère, plus une autre servant de marqueur en cas d'échec.
Initialement, EOF signifie bien « End Of File » parce que l'atteinte de la fin d'un fichier est un événement normal lorsqu'on lit ce fichier. On a ensuite conservé ce marqueur pour tous les autres cas où fgetc() ne peut renvoyer de caractère et il appartient alors au programmeur d'aller vérifier pourquoi on l'a reçu.
Effectivement, EOF n'est pas un caractère mais « EOT » en est bien un dans la table ASCII. Comme tu le signales, il signifie « End Of Transmission » et sert à indiquer que l'on a fini de transmettre, sur un canal qui par nature n'a pas de fin, comme un clavier. Il porte bien le numéro 4 et est donc généré par Ctrl+D.
On ne le met pas à la fin d'un fichier, mais lors d'une transmission en ASCII entre deux pairs (typiquement un terminal et le serveur central), c'était un moyen d'indiquer que l'on avait fini. En principe, sur les terminaux Unix, cette combinaison permet d'indiquer au terminal lui-même qu'on a fini et donc d'envoyer immédiatement ce qui est en attente dans le buffer, ce qui est pratique quand on utilise une discipline qui maintient une ligne dans le tampon jusqu'à l'appui sur le retour à la ligne (ce qui permet éventuellement de la corriger avant de l'envoyer) : ça permet d'envoyer un flux de caractère qui ne contient PAS le retour à la ligne.
Si la ligne est vide, alors le système reçoit une trame de zéro caractères, et les logiciels qui utilisent read(), par convention là encore, interprètent ceci comme une fin de fichier. C'est d'ailleurs pourquoi on peut quitter une session avec Ctrl+D.
Ctrl+C n'est pour ainsi dire jamais utilisé sous la forme donnée par la table ASCII, mais a été utilisé pour faire un break depuis pratiquement l'aube des ordinateurs et a été repris dans ce sens par pratiquement tous les autres systèmes. Sous Unix et dans un terminal, Ctrl+C envoie donc SIGINT au programme en cours d'exécution.
On en parlait ici.
Obsidian, j'aime ce genre de message !
Tout d'abord, merci beaucoup Obsidian pour ces explications ! D'après ce que j'ai (humblement) compris, "\O" signifierait donc la fin d'une chaîne de caractères, tandis que EOF concernerait plutôt la fin d'un fichier ?
j'ai cependant encore un peu de mal à voir comment EOF et "\O" s'utilisent. Pour essayer de mieux comprendre, j'essaie en ce moment d'écrire un programme simple comptant les caractères rentrés dans un terminal...
Le problème est de "signifier" à mon programme que lorsque l'utilisateur ne tape plus rien (et donc, lorsque c'est la fin de la chaîne de caractère) ou bien qu'il appuie sur "Entrée", il faut arrêter l'exécution.
Voilà pour le moment mon code :
merci d'avance !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 #include <Stdio.h> main() { long i; char entree; for (i = 0; entree = getchar() != "\O"; i++) ; printf("%s %ld \n", "Nombre de caratères tapés: ", i); }
Bonjour,
- Ce n'est pas un O, c'est un 0 (zéro)
- getchar() lit un flux, donc il n'est pas question de \0 ici. Mais getchar() retournera EOF si l'entrée est fermée (par Ctrl+D, voir plus haut) ou s'il l'on a redirigé un fichier texte vers l'entrée et qu'il a déjà retourné le dernier caractère dudit fichier.
- L'EOF n'est pas physiquement présent dans le fichier, alors que le caractère \0 est physiquement présent dans la mémoire.
Ton printf attend un pointeur avant l'entier.- La fin d'une ligne est différente de la fin de flux et de la fin de texte; la fin d'une ligne est représentée par le caractère \n (newline)
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Merci beaucoup! (décidement, '\0' me pose des soucis )Ce n'est pas un O, c'est un 0 (zéro)
En fait la représentation mémoire d'une chaîne de caractère est telle que le \0 est compté dedans:
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 #include <stdio.h> int main(void) { char abcde[] = "abcde"; /*correspond à {'a', 'b', 'c', 'd', 'e', '\0'}*/ printf("Sizeof %s: %d\n", abcde, (int)sizeof abcde); }
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Concernant les trois premiers points, ça commence à devenir plus clair dans mon esprit ! ^^
Par contre, le problème liant le pointeur et le printf, jee ne comprends pas très bien ... (malgré le fait que je connaisse le principe des pointeurs, je n'ai pas encore bien vu leur utilisation en C, pourrais-tu m'éclairer un peu plus sur ce point ?
Merci d'avance !
PS : merci beaucoup pour l'exemple concernant le "\0" ! c'est encore un peu plus clair ^^
EDIT : Médinoc m'a clairement induit en erreur et j'ai pas essayé de faire marcher mon cerveau. Le message suivant est "faux" (voir après).
Ce n'est pas un problème de pointeur, c'est un problème d'utilisation de la chaine formatée de printf().
Chacun %qqchose devrait être remplacé par une valeur. Ces valeurs sont donnés par la liste de variables suivant la chaîne formatée. Ici, tu as %s et %ld. %ld attend un entier de type long. %s attend une chaîne de caractères, donc un pointeur sur char.
Code : Sélectionner tout - Visualiser dans une fenêtre à part printf("%s %ld \n", "Nombre de caratères tapés: ", i);
Il faudrait donc écrire quelque chose comme :
Tu n'as pas déclaré de chaîne de caractère dans ton code, pourquoi souhaites-tu en afficher une d'ailleurs ? ^^
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 char [] str = "Mon message"; printf("%s %ld \n", "Nombre de caratères tapés: ", str, i);
Pour le printf(), c'est moi qui suis aveugle (et qui ai entrainé Bktero avec moi), je n'avais pas vu que "Nombre de caratères tapés: " était la chaîne passée au %s (je n'ai pas l'habitude de ça, donc j'ai du mal à le repérer).
J'ai édité mon message.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
En effet, en cherchant toujours à indiquer à mon programme la fin de la saisie pour l'utilisateur (ou en fait, j'ai commencé à utiliser fget() puis à parcourir le string lu pour arriver au fameux '\0'),
je me suis rendue compte d'une chose qui pourrait être à l'origine d'un de mes troubles : le type string n'existe pas en C c'est ça ? O.O il faut forcément l'identifier comme un pointeur sur un tableau de char et donc, obligatoirement passer par une phase de déclaration préalable ?
Le type string n'existe effectivement pas.
Chaque chaine de caractères est par un tableau de caractères.
Chaque fois qu'une chaine est utilisée, on connait l'adresse en mémoire de son premier caractère, adresse stoqué dans un pointeur de caractères (char* et variantes constantes)
Une fonction utilisant une chaine parcourra la mémoire en commencant à ce pointeur, et jusqu'à atteindre un caractère null (le fameux '\0', qui à pour valeur 0 en ASCII).
En pratique, une chaine peut-être stoquée dans un tableau.
ainsi, char[] message = "hello"; est équivalent à char[] message = {'h', 'e', 'l', 'l', 'o', '\0'};. Remercie donc les concepteurs du langage de t'épargner cette syntaxe laborieuse.
Fais toujours attention qu'à case de ce \0, une chaine occupe toujours exactement un caractère de plus que les caractères entre guillemets dans la mémoire (la taille de "hello" est 6)
Autre point, la déclaration char* message = "hello"; est dangereuse, car "hello" est un littéral de chaine, qui peut être conservé dans le code binaire, et donc ne pas être modifiable du tout, malgré le que message soit déclaré comme un pointeur (modifiable) de caractère modifiable (char pas const * pas const).
Les compilateurs récents émettent un warning quand une telle écriture est faite.
Il n'y a que deux solutions à ce problème: char const* message = "hello"; (ou const char* message = "hello";) et char[6] message = "hello";
Mes principes de bases du codeur qui veut pouvoir dormir:Pour faire des graphes, essayez yEd.
- Une variable de moins est une source d'erreur en moins.
- Un pointeur de moins est une montagne d'erreurs en moins.
- Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
- jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
- La plus sotte des questions est celle qu'on ne pose pas.
le ter nel est le titre porté par un de mes personnages de jeu de rôle
--> "un littéral de chaîne" ? O.O Késako ?
Une autre question, dans la continuité de mon dernier post, j'ai continué ma fonction qui compte les tabulations, espaces et fin de ligne dans un flux écrit par l'utilisateur (et où j'avais déclaré "string entree"...), et dès que j'appuie sur la touche entrée (vu que je veux rentrer un message de plusieurs lignes et voir si le programme compte bien les fins de ligne...), il arrête l'exécution et me donne le résultat du comptage : pourquoi ? Je ne vois pas ... Voilà le code :
Merci beaucoup pour toutes vos réponses en tout cas ^^"
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 include <Stdio.h> main() { printf("%s \n", "Entrez un message n'ayant pas plus que 20 caractères:"); char entree[21]; int i = 0; long nombre_espace = 0; long nombre_tab = 0; long nombre_fin_ligne = 0; char courant; while ((courant = entree[i]) != '\0') { if (courant == ' ') { nombre_espace++; } if (courant == '\t') { nombre_tab++; } if (courant == '\n') { nombre_fin_ligne++; } i++; } printf("%s %ld \n %s %ld \n %s %ld \n", "Nombre d'espaces : ", nombre_espace, "Nombre de tabulations :", nombre_tab, "Nombre de fin de lignes : ", nombre_fin_ligne); }
[EDIT] j'ai modifié mon code et maintenant, je peux mettre un message sur plusieurs lignes par contre, je ne comprends pas pourquoi ça fait exactement ce que je veux si j'appuie sur.... Ctrl-D xD :
Merci d'avance pour vos idées
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <Stdio.h> main() { printf("%s \n", "Entrez un message n'ayant pas plus que 20 caractères:"); char entree[21]; int i = 0; fgets(entree, sizeof(entree), stdin); long nombre_espace = 0; long nombre_tab = 0; long nombre_fin_ligne = 0; char courant; while (fgets(entree, sizeof(entree), stdin) != NULL) { while ((courant = entree[i]) != '\0') { if (courant == ' ') { nombre_espace++; } if (courant == '\t') { nombre_tab++; } if (courant == '\n') { nombre_fin_ligne++; } i++; } } printf("%s %ld \n %s %ld \n %s %ld \n", "Nombre d'espaces : ", nombre_espace, "Nombre de tabulations :", nombre_tab, "Nombre de fin de lignes : ", nombre_fin_ligne); }
Bonjour
Il s'agit d'une chaine non modifiable parce que stockée comme valeur littérale en mémoire. Tu as juste l'adresse de départ de cette chaine donc tu peux la traiter mais tu n'as pas le droit de modifier son contenu.
Tu ne comprends pas pourquoi ça fait ce que tu veux ? Voilà qui est inquiétant...
Faut pas oublier qu'entre ton fgets() et tes doigts, il y a au milieu plein de trucs dont notamment un clavier et surtout un driver pour le piloter et traiter ses entrées.
Or ctrl-d est un marquant signifiant conventionnellement "End of Transmission". Donc le driver s'il est bien fait a été codé pour gérer ce ctrl-d.
Et donc quand tu tapes ctrl-d, le driver obéit gentiment et indique que c'est fini. Au dessus le fgets() reçoit cette indication et arrête donc de traiter le flux stdin et renvoie NULL puisqu'on lui a dit que c'était fini...
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Ctrl+D ferme le flux d'entrée, donc à la prochaine lecture fgets() retournera NULL, donc ta boucle se terminera et affichera les comptes.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
En fait, j'ai testé avec Ctrl D sans trop réfléchir, mais j'ai du me souvenir inconsciemment de ce que l'ensemble des gens m'ont dit plus haut Merci en tout cas ça maaaaarche et je sais pourquoi (grâce à vous) ! Génial !
Un petit truc, est-ce qu'il existe un autre moyen de signifier à la machine que c'est la fin de la "transmission" ou bien du message rentré par l'utilisateur ? (simple question de curiosité )
Merci !
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager